summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens-Heiner Rechtien <hr@openoffice.org>2000-09-22 14:33:37 +0000
committerJens-Heiner Rechtien <hr@openoffice.org>2000-09-22 14:33:37 +0000
commitb501a54cf959bc549810fb24ca6f9584dc5c9cf3 (patch)
treeb78fbbc5c0f6959529f2553e3bbb83b077eaa17c
parent17e0108b4e8d91f9acfe376ee231418830392460 (diff)
initial import
-rw-r--r--dmake/alloc.h59
-rw-r--r--dmake/dag.c577
-rw-r--r--dmake/db.h66
-rw-r--r--dmake/dbug/dbug.mk66
-rw-r--r--dmake/dbug/dbug/dbug.c1834
-rw-r--r--dmake/dbug/dbug/dbug.h164
-rw-r--r--dmake/dbug/dbug/dbug.uue368
-rw-r--r--dmake/dbug/dbug/readme6
-rw-r--r--dmake/dbug/getwd.c6
-rw-r--r--dmake/dbug/malloc/_changes9
-rw-r--r--dmake/dbug/malloc/_readme133
-rw-r--r--dmake/dbug/malloc/calloc.c91
-rw-r--r--dmake/dbug/malloc/debug.h129
-rw-r--r--dmake/dbug/malloc/dump.c142
-rw-r--r--dmake/dbug/malloc/free.c206
-rw-r--r--dmake/dbug/malloc/m_init.c121
-rw-r--r--dmake/dbug/malloc/m_perror.c111
-rw-r--r--dmake/dbug/malloc/makefile77
-rw-r--r--dmake/dbug/malloc/malloc.3223
-rw-r--r--dmake/dbug/malloc/malloc.c672
-rw-r--r--dmake/dbug/malloc/malloc.h121
-rw-r--r--dmake/dbug/malloc/mallopt.c143
-rw-r--r--dmake/dbug/malloc/memory.c243
-rw-r--r--dmake/dbug/malloc/mlc_chk.c297
-rw-r--r--dmake/dbug/malloc/mlc_chn.c188
-rw-r--r--dmake/dbug/malloc/patchlev1
-rw-r--r--dmake/dbug/malloc/realloc.c233
-rw-r--r--dmake/dbug/malloc/string.c581
-rw-r--r--dmake/dbug/malloc/testmem.c646
-rw-r--r--dmake/dbug/malloc/testmlc.c176
-rw-r--r--dmake/dbug/malloc/tostring.c169
-rw-r--r--dmake/dbug/malloc/tostring.h43
-rw-r--r--dmake/dbug/readme13
-rw-r--r--dmake/dmake.c843
-rw-r--r--dmake/dmake.h200
-rw-r--r--dmake/dmdump.c259
-rw-r--r--dmake/dmstring.c287
-rw-r--r--dmake/dstdarg.h43
-rw-r--r--dmake/expand.c1066
-rw-r--r--dmake/extern.h66
-rw-r--r--dmake/function.c625
-rw-r--r--dmake/getinp.c671
-rw-r--r--dmake/hash.c52
-rw-r--r--dmake/imacs.c181
-rw-r--r--dmake/infer.c832
-rw-r--r--dmake/itypes.h47
-rw-r--r--dmake/mac/arlib.c56
-rw-r--r--dmake/mac/bogus.c99
-rw-r--r--dmake/mac/config.mk44
-rw-r--r--dmake/mac/dirbrk.c42
-rw-r--r--dmake/mac/directry.c264
-rw-r--r--dmake/mac/dompwmak67
-rw-r--r--dmake/mac/environ.c231
-rw-r--r--dmake/mac/eold.c119
-rw-r--r--dmake/mac/main.c43
-rw-r--r--dmake/mac/make.sh107
-rw-r--r--dmake/mac/make_mac.sh105
-rw-r--r--dmake/mac/public.h172
-rw-r--r--dmake/mac/rmprq.c38
-rw-r--r--dmake/mac/ruletab.c43
-rw-r--r--dmake/mac/startup.h28
-rw-r--r--dmake/mac/sysintf.h42
-rw-r--r--dmake/mac/template.mk7
-rw-r--r--dmake/mac/tempnam.c65
-rw-r--r--dmake/mac/tomacfil.c38
-rw-r--r--dmake/macparse.c211
-rwxr-xr-xdmake/make.bat273
-rw-r--r--dmake/make.c1412
-rwxr-xr-xdmake/make.cmd102
-rw-r--r--dmake/makefile.mk429
-rw-r--r--dmake/man/dmake.nc3696
-rw-r--r--dmake/man/dmake.tf3152
-rw-r--r--dmake/man/readme26
-rw-r--r--dmake/msdos/arlib.c56
-rw-r--r--dmake/msdos/borland/bcc30/config.h48
-rw-r--r--dmake/msdos/borland/bcc30/config.mk8
-rw-r--r--dmake/msdos/borland/bcc30/lib.rsp1
-rw-r--r--dmake/msdos/borland/bcc30/libswp.rsp1
-rwxr-xr-xdmake/msdos/borland/bcc30/mkswp.bat107
-rw-r--r--dmake/msdos/borland/bcc30/obj.rsp34
-rw-r--r--dmake/msdos/borland/bcc30/objswp.rsp36
-rw-r--r--dmake/msdos/borland/bcc30/public.h169
-rw-r--r--dmake/msdos/borland/bcc30/template.mk7
-rw-r--r--dmake/msdos/borland/bcc40/config.h51
-rw-r--r--dmake/msdos/borland/bcc40/config.mk7
-rw-r--r--dmake/msdos/borland/bcc40/lib.rsp2
-rw-r--r--dmake/msdos/borland/bcc40/libswp.rsp1
-rwxr-xr-xdmake/msdos/borland/bcc40/mkswp.bat107
-rw-r--r--dmake/msdos/borland/bcc40/obj.rsp34
-rw-r--r--dmake/msdos/borland/bcc40/objswp.rsp36
-rw-r--r--dmake/msdos/borland/bcc40/public.h169
-rw-r--r--dmake/msdos/borland/bcc40/template.mk7
-rw-r--r--dmake/msdos/borland/bcc45/config.h51
-rw-r--r--dmake/msdos/borland/bcc45/config.mk7
-rw-r--r--dmake/msdos/borland/bcc45/lib.rsp2
-rw-r--r--dmake/msdos/borland/bcc45/libswp.rsp1
-rwxr-xr-xdmake/msdos/borland/bcc45/mkswp.bat107
-rw-r--r--dmake/msdos/borland/bcc45/obj.rsp34
-rw-r--r--dmake/msdos/borland/bcc45/objswp.rsp36
-rw-r--r--dmake/msdos/borland/bcc45/public.h169
-rw-r--r--dmake/msdos/borland/bcc45/template.mk7
-rw-r--r--dmake/msdos/borland/bcc50/config.h51
-rw-r--r--dmake/msdos/borland/bcc50/config.mk7
-rw-r--r--dmake/msdos/borland/bcc50/lib.rsp2
-rw-r--r--dmake/msdos/borland/bcc50/libswp.rsp1
-rwxr-xr-xdmake/msdos/borland/bcc50/mkswp.bat107
-rw-r--r--dmake/msdos/borland/bcc50/obj.rsp34
-rw-r--r--dmake/msdos/borland/bcc50/objswp.rsp36
-rw-r--r--dmake/msdos/borland/bcc50/public.h169
-rw-r--r--dmake/msdos/borland/bcc50/template.mk7
-rw-r--r--dmake/msdos/borland/config.mk46
-rw-r--r--dmake/msdos/borland/tcc20/config.h48
-rw-r--r--dmake/msdos/borland/tcc20/config.mk10
-rw-r--r--dmake/msdos/borland/tcc20/libswp.rsp1
-rwxr-xr-xdmake/msdos/borland/tcc20/mkswp.bat107
-rw-r--r--dmake/msdos/borland/tcc20/objswp.rsp36
-rw-r--r--dmake/msdos/borland/tcc20/public.h169
-rw-r--r--dmake/msdos/borland/tcc20/template.mk7
-rw-r--r--dmake/msdos/borland/tempnam.c109
-rw-r--r--dmake/msdos/borland/utime.c66
-rw-r--r--dmake/msdos/config.mk71
-rw-r--r--dmake/msdos/dchdir.c47
-rw-r--r--dmake/msdos/dirbrk.c42
-rw-r--r--dmake/msdos/dirent.h32
-rw-r--r--dmake/msdos/dirlib.c285
-rw-r--r--dmake/msdos/dosdta.h16
-rw-r--r--dmake/msdos/dstrlwr.c49
-rw-r--r--dmake/msdos/exec.asm1234
-rw-r--r--dmake/msdos/exec.h43
-rw-r--r--dmake/msdos/exec.uue63
-rw-r--r--dmake/msdos/find.c130
-rw-r--r--dmake/msdos/microsft/config.h77
-rw-r--r--dmake/msdos/microsft/config.mk59
-rw-r--r--dmake/msdos/microsft/msc51/config.mk11
-rw-r--r--dmake/msdos/microsft/msc51/lib.rsp1
-rw-r--r--dmake/msdos/microsft/msc51/libswp.rsp1
-rwxr-xr-xdmake/msdos/microsft/msc51/mk.bat102
-rwxr-xr-xdmake/msdos/microsft/msc51/mkswp.bat104
-rw-r--r--dmake/msdos/microsft/msc51/obj.rsp33
-rw-r--r--dmake/msdos/microsft/msc51/objswp.rsp34
-rw-r--r--dmake/msdos/microsft/msc51/public.h169
-rw-r--r--dmake/msdos/microsft/msc51/template.mk7
-rw-r--r--dmake/msdos/microsft/msc60/config.mk11
-rw-r--r--dmake/msdos/microsft/msc60/lib.rsp1
-rw-r--r--dmake/msdos/microsft/msc60/libswp.rsp1
-rwxr-xr-xdmake/msdos/microsft/msc60/mk.bat102
-rwxr-xr-xdmake/msdos/microsft/msc60/mkswp.bat104
-rw-r--r--dmake/msdos/microsft/msc60/obj.rsp33
-rw-r--r--dmake/msdos/microsft/msc60/objswp.rsp34
-rw-r--r--dmake/msdos/microsft/msc60/public.h169
-rw-r--r--dmake/msdos/microsft/msc60/template.mk7
-rw-r--r--dmake/msdos/microsft/optoff.h27
-rw-r--r--dmake/msdos/microsft/tempnam.c110
-rw-r--r--dmake/msdos/rmprq.c38
-rw-r--r--dmake/msdos/ruletab.c45
-rw-r--r--dmake/msdos/runargv.c132
-rw-r--r--dmake/msdos/spawn.c414
-rw-r--r--dmake/msdos/startup.h26
-rw-r--r--dmake/msdos/switchar.c55
-rw-r--r--dmake/msdos/sysintf.h53
-rw-r--r--dmake/msdos/tee.c31
-rw-r--r--dmake/msdos/zortech/config.h52
-rw-r--r--dmake/msdos/zortech/config.mk73
-rw-r--r--dmake/msdos/zortech/environ.c59
-rw-r--r--dmake/msdos/zortech/lib.rsp1
-rw-r--r--dmake/msdos/zortech/libswp.rsp1
-rwxr-xr-xdmake/msdos/zortech/mkswp.bat36
-rw-r--r--dmake/msdos/zortech/obj.rsp34
-rw-r--r--dmake/msdos/zortech/objswp.rsp35
-rw-r--r--dmake/msdos/zortech/public.h168
-rw-r--r--dmake/msdos/zortech/startup.mk153
-rw-r--r--dmake/msdos/zortech/tempnam.c106
-rw-r--r--dmake/os2/config.mk54
-rw-r--r--dmake/os2/dchdir.c41
-rw-r--r--dmake/os2/dirent.h36
-rw-r--r--dmake/os2/ibm/config.h78
-rw-r--r--dmake/os2/ibm/config.mk54
-rw-r--r--dmake/os2/ibm/icc/config.mk11
-rw-r--r--dmake/os2/ibm/icc/lib.rsp1
-rwxr-xr-xdmake/os2/ibm/icc/mk.cmd96
-rw-r--r--dmake/os2/ibm/icc/obj.rsp31
-rw-r--r--dmake/os2/ibm/icc/public.h168
-rw-r--r--dmake/os2/ibm/icc/template.mk7
-rw-r--r--dmake/os2/ibm/icc3/config.mk11
-rw-r--r--dmake/os2/ibm/icc3/lib.rsp1
-rwxr-xr-xdmake/os2/ibm/icc3/mk.cmd192
-rw-r--r--dmake/os2/ibm/icc3/obj.rsp30
-rw-r--r--dmake/os2/ibm/icc3/public.h168
-rw-r--r--dmake/os2/ibm/icc3/template.mk7
-rw-r--r--dmake/os2/ibm/tempnam.c111
-rw-r--r--dmake/os2/ruletab.c46
-rw-r--r--dmake/os2/startup.h27
-rw-r--r--dmake/os2/switchar.c43
-rw-r--r--dmake/os2/sysintf.h60
-rw-r--r--dmake/parse.c168
-rw-r--r--dmake/path.c161
-rw-r--r--dmake/percent.c251
-rw-r--r--dmake/posix.h54
-rw-r--r--dmake/qssl/config.mk43
-rw-r--r--dmake/qssl/make.sh62
-rw-r--r--dmake/qssl/public.h165
-rw-r--r--dmake/qssl/ruletab.c41
-rw-r--r--dmake/qssl/runargv.c296
-rw-r--r--dmake/qssl/setup40
-rw-r--r--dmake/qssl/startup.h27
-rw-r--r--dmake/qssl/stdlib.h48
-rw-r--r--dmake/qssl/sysintf.h43
-rw-r--r--dmake/qssl/template.mk7
-rw-r--r--dmake/qssl/tempnam.c102
-rw-r--r--dmake/qssl/time.h32
-rw-r--r--dmake/quit.c69
-rw-r--r--dmake/rcsclean.awk57
-rw-r--r--dmake/readme/intro.txt43
-rw-r--r--dmake/readme/license.txt248
-rw-r--r--dmake/readme/public/install.txt203
-rw-r--r--dmake/readme/public/mac.txt43
-rw-r--r--dmake/readme/public/msdos.txt124
-rw-r--r--dmake/readme/public/os2.txt76
-rw-r--r--dmake/readme/public/qssl-qnx.txt5
-rw-r--r--dmake/readme/public/srcorg.txt74
-rw-r--r--dmake/readme/public/tos.txt31
-rw-r--r--dmake/readme/public/unix.txt171
-rw-r--r--dmake/readme/read1st.txt41
-rw-r--r--dmake/readme/release.txt194
-rw-r--r--dmake/rulparse.c1473
-rw-r--r--dmake/startup/mac/macros.mk41
-rw-r--r--dmake/startup/msdos/borland/bcc30/macros.mk4
-rw-r--r--dmake/startup/msdos/borland/bcc40/macros.mk4
-rw-r--r--dmake/startup/msdos/borland/bcc45/macros.mk4
-rw-r--r--dmake/startup/msdos/borland/bcc50.32/macros.mk4
-rw-r--r--dmake/startup/msdos/borland/bcc50/macros.mk4
-rw-r--r--dmake/startup/msdos/borland/macros.mk33
-rw-r--r--dmake/startup/msdos/borland/tcc20/macros.mk4
-rw-r--r--dmake/startup/msdos/macros.mk62
-rw-r--r--dmake/startup/msdos/microsft/macros.mk34
-rw-r--r--dmake/startup/msdos/recipes.mk9
-rw-r--r--dmake/startup/msdos/zortech/macros.mk30
-rw-r--r--dmake/startup/os2/ibm/macros.mk30
-rw-r--r--dmake/startup/os2/macros.mk60
-rw-r--r--dmake/startup/qssl/macros.mk11
-rw-r--r--dmake/startup/qssl/qnx/macros.mk11
-rw-r--r--dmake/startup/qssl/qnx/recipes.mk8
-rw-r--r--dmake/startup/qssl/recipes.mk8
-rw-r--r--dmake/startup/startup.mk209
-rw-r--r--dmake/startup/summary3
-rw-r--r--dmake/startup/template.mk7
-rw-r--r--dmake/startup/templates/mac/template.mk7
-rw-r--r--dmake/startup/templates/msdos/borland/bcc30/template.mk7
-rw-r--r--dmake/startup/templates/msdos/borland/bcc40/template.mk7
-rw-r--r--dmake/startup/templates/msdos/borland/bcc45/template.mk7
-rw-r--r--dmake/startup/templates/msdos/borland/bcc50/template.mk7
-rw-r--r--dmake/startup/templates/msdos/borland/tcc20/template.mk7
-rw-r--r--dmake/startup/templates/msdos/microsft/msc51/template.mk7
-rw-r--r--dmake/startup/templates/msdos/microsft/msc60/template.mk7
-rw-r--r--dmake/startup/templates/os2/ibm/icc/template.mk7
-rw-r--r--dmake/startup/templates/qssl/template.mk7
-rw-r--r--dmake/startup/templates/tos/template.mk7
-rw-r--r--dmake/startup/templates/unix/386ix/template.mk7
-rw-r--r--dmake/startup/templates/unix/bsd43/template.mk7
-rw-r--r--dmake/startup/templates/unix/bsd43/uw/template.mk7
-rw-r--r--dmake/startup/templates/unix/bsd43/vf/template.mk7
-rw-r--r--dmake/startup/templates/unix/coherent/ver40/template.mk7
-rw-r--r--dmake/startup/templates/unix/coherent/ver42/template.mk7
-rw-r--r--dmake/startup/templates/unix/linux/gnu/template.mk7
-rw-r--r--dmake/startup/templates/unix/solaris/gnu/template.mk7
-rw-r--r--dmake/startup/templates/unix/solaris/template.mk7
-rw-r--r--dmake/startup/templates/unix/sysvr1/template.mk7
-rw-r--r--dmake/startup/templates/unix/sysvr3/pwd/template.mk7
-rw-r--r--dmake/startup/templates/unix/sysvr3/template.mk7
-rw-r--r--dmake/startup/templates/unix/sysvr4/template.mk7
-rw-r--r--dmake/startup/templates/unix/xenix/pwd/template.mk7
-rw-r--r--dmake/startup/templates/unix/xenix/template.mk7
-rw-r--r--dmake/startup/templates/win95/borland/bcc50/template.mk7
-rw-r--r--dmake/startup/templates/win95/microsft/vpp40/template.mk7
-rw-r--r--dmake/startup/templates/winnt/borland/bcc50/template.mk7
-rw-r--r--dmake/startup/templates/winnt/microsft/vpp40/template.mk7
-rw-r--r--dmake/startup/tos/macros.mk24
-rw-r--r--dmake/startup/unix/386ix/macros.mk6
-rw-r--r--dmake/startup/unix/bsd43/macros.mk11
-rw-r--r--dmake/startup/unix/bsd43/recipes.mk13
-rw-r--r--dmake/startup/unix/coherent/macros.mk6
-rw-r--r--dmake/startup/unix/coherent/recipes.mk6
-rw-r--r--dmake/startup/unix/linux/gnu/macros.mk6
-rw-r--r--dmake/startup/unix/linux/macros.mk10
-rw-r--r--dmake/startup/unix/macosx/gnu/macros.mk6
-rw-r--r--dmake/startup/unix/macosx/macros.mk10
-rw-r--r--dmake/startup/unix/macros.mk5
-rw-r--r--dmake/startup/unix/recipes.mk15
-rw-r--r--dmake/startup/unix/solaris/macros.mk6
-rw-r--r--dmake/startup/unix/sysvr1/macros.mk6
-rw-r--r--dmake/startup/unix/sysvr3/gnu/macros.mk12
-rw-r--r--dmake/startup/unix/sysvr3/macros.mk7
-rw-r--r--dmake/startup/unix/sysvr4/macros.mk6
-rw-r--r--dmake/startup/unix/xenix/macros.mk6
-rw-r--r--dmake/startup/win95/borland/macros.mk34
-rw-r--r--dmake/startup/win95/macros.mk64
-rw-r--r--dmake/startup/win95/microsft/macros.mk38
-rw-r--r--dmake/startup/win95/recipes.mk9
-rw-r--r--dmake/startup/winnt/borland/macros.mk34
-rw-r--r--dmake/startup/winnt/macros.mk64
-rw-r--r--dmake/startup/winnt/microsft/macros.mk37
-rw-r--r--dmake/startup/winnt/recipes.mk9
-rw-r--r--dmake/stat.c263
-rw-r--r--dmake/state.c229
-rw-r--r--dmake/stdmacs.h56
-rw-r--r--dmake/struct.h256
-rw-r--r--dmake/sysintf.c753
-rw-r--r--dmake/tos/config.mk49
-rw-r--r--dmake/tos/make.sh57
-rw-r--r--dmake/tos/public.h163
-rw-r--r--dmake/tos/putenv.c78
-rw-r--r--dmake/tos/ruletab.c42
-rw-r--r--dmake/tos/startup.h27
-rw-r--r--dmake/tos/sysintf.h46
-rw-r--r--dmake/tos/template.mk7
-rw-r--r--dmake/tos/tempnam.c104
-rw-r--r--dmake/unix/386ix/ar.h27
-rw-r--r--dmake/unix/386ix/config.mk27
-rw-r--r--dmake/unix/386ix/make.sh60
-rw-r--r--dmake/unix/386ix/public.h164
-rw-r--r--dmake/unix/386ix/stdlib.h44
-rw-r--r--dmake/unix/386ix/template.mk7
-rw-r--r--dmake/unix/386ix/time.h35
-rw-r--r--dmake/unix/arlib.c609
-rw-r--r--dmake/unix/bsd43/config.mk27
-rw-r--r--dmake/unix/bsd43/dirent.h28
-rw-r--r--dmake/unix/bsd43/limits.h32
-rw-r--r--dmake/unix/bsd43/make.sh69
-rw-r--r--dmake/unix/bsd43/public.h164
-rw-r--r--dmake/unix/bsd43/putenv.c78
-rw-r--r--dmake/unix/bsd43/setvbuf.c40
-rw-r--r--dmake/unix/bsd43/stdlib.h44
-rw-r--r--dmake/unix/bsd43/string.h43
-rw-r--r--dmake/unix/bsd43/template.mk7
-rw-r--r--dmake/unix/bsd43/tempnam.c103
-rw-r--r--dmake/unix/bsd43/utime.c70
-rw-r--r--dmake/unix/bsd43/uw/config.mk17
-rw-r--r--dmake/unix/bsd43/uw/make.sh69
-rw-r--r--dmake/unix/bsd43/uw/public.h164
-rw-r--r--dmake/unix/bsd43/uw/template.mk7
-rw-r--r--dmake/unix/bsd43/vf/config.mk11
-rw-r--r--dmake/unix/bsd43/vf/ctype.h51
-rw-r--r--dmake/unix/bsd43/vf/make.sh73
-rw-r--r--dmake/unix/bsd43/vf/memcpy.c36
-rw-r--r--dmake/unix/bsd43/vf/public.h164
-rw-r--r--dmake/unix/bsd43/vf/template.mk7
-rw-r--r--dmake/unix/bsd43/vf/vfprintf.c48
-rw-r--r--dmake/unix/bsdarm32/config.mk27
-rw-r--r--dmake/unix/bsdarm32/dirent.h30
-rw-r--r--dmake/unix/bsdarm32/limits.h29
-rw-r--r--dmake/unix/bsdarm32/make.sh67
-rw-r--r--dmake/unix/bsdarm32/public.h164
-rw-r--r--dmake/unix/bsdarm32/putenv.c78
-rw-r--r--dmake/unix/bsdarm32/stdlib.h44
-rw-r--r--dmake/unix/bsdarm32/string.h42
-rw-r--r--dmake/unix/bsdarm32/template.mk7
-rw-r--r--dmake/unix/bsdarm32/tempnam.c105
-rw-r--r--dmake/unix/bsdarm32/utime.c70
-rw-r--r--dmake/unix/coherent/config.mk26
-rw-r--r--dmake/unix/coherent/stdlib.h44
-rw-r--r--dmake/unix/coherent/time.h32
-rw-r--r--dmake/unix/coherent/ver40/config.mk11
-rw-r--r--dmake/unix/coherent/ver40/getcwd.c49
-rw-r--r--dmake/unix/coherent/ver40/make.sh64
-rw-r--r--dmake/unix/coherent/ver40/public.h164
-rw-r--r--dmake/unix/coherent/ver40/template.mk7
-rw-r--r--dmake/unix/coherent/ver40/vfprintf.c190
-rw-r--r--dmake/unix/coherent/ver42/config.mk11
-rw-r--r--dmake/unix/coherent/ver42/make.sh60
-rw-r--r--dmake/unix/coherent/ver42/public.h164
-rw-r--r--dmake/unix/coherent/ver42/template.mk7
-rw-r--r--dmake/unix/config.mk39
-rw-r--r--dmake/unix/dcache.c198
-rw-r--r--dmake/unix/dirbrk.c42
-rw-r--r--dmake/unix/linux/config.mk27
-rw-r--r--dmake/unix/linux/gnu/config.mk4
-rw-r--r--dmake/unix/linux/gnu/make.sh193
-rw-r--r--dmake/unix/linux/gnu/public.h164
-rw-r--r--dmake/unix/linux/gnu/template.mk7
-rw-r--r--dmake/unix/macosx/config.mk27
-rw-r--r--dmake/unix/macosx/gnu/config.mk4
-rw-r--r--dmake/unix/macosx/gnu/make.sh60
-rw-r--r--dmake/unix/macosx/gnu/public.h164
-rw-r--r--dmake/unix/macosx/gnu/template.mk7
-rw-r--r--dmake/unix/rmprq.c96
-rw-r--r--dmake/unix/ruletab.c41
-rw-r--r--dmake/unix/runargv.c307
-rw-r--r--dmake/unix/solaris/config.mk27
-rw-r--r--dmake/unix/solaris/getcwd.c231
-rw-r--r--dmake/unix/solaris/gnu/config.mk8
-rw-r--r--dmake/unix/solaris/gnu/make.sh64
-rw-r--r--dmake/unix/solaris/gnu/public.h164
-rw-r--r--dmake/unix/solaris/gnu/template.mk7
-rw-r--r--dmake/unix/solaris/make.sh64
-rw-r--r--dmake/unix/solaris/public.h164
-rw-r--r--dmake/unix/solaris/template.mk7
-rw-r--r--dmake/unix/solaris/tempnam.c103
-rw-r--r--dmake/unix/startup.h27
-rw-r--r--dmake/unix/sysintf.h51
-rw-r--r--dmake/unix/sysvr1/config.mk28
-rw-r--r--dmake/unix/sysvr1/make.sh62
-rw-r--r--dmake/unix/sysvr1/public.h164
-rw-r--r--dmake/unix/sysvr1/putenv.c78
-rw-r--r--dmake/unix/sysvr1/stdlib.h44
-rw-r--r--dmake/unix/sysvr1/template.mk7
-rw-r--r--dmake/unix/sysvr1/time.h32
-rw-r--r--dmake/unix/sysvr1/vfprintf.c58
-rw-r--r--dmake/unix/sysvr3/config.mk27
-rw-r--r--dmake/unix/sysvr3/gnu/public.h162
-rw-r--r--dmake/unix/sysvr3/make.sh60
-rw-r--r--dmake/unix/sysvr3/public.h164
-rw-r--r--dmake/unix/sysvr3/pwd/config.mk20
-rw-r--r--dmake/unix/sysvr3/pwd/getcwd.c231
-rw-r--r--dmake/unix/sysvr3/pwd/make.sh62
-rw-r--r--dmake/unix/sysvr3/pwd/public.h164
-rw-r--r--dmake/unix/sysvr3/pwd/template.mk7
-rw-r--r--dmake/unix/sysvr3/stdlib.h55
-rw-r--r--dmake/unix/sysvr3/template.mk7
-rw-r--r--dmake/unix/sysvr3/time.h32
-rw-r--r--dmake/unix/sysvr4/config.mk27
-rw-r--r--dmake/unix/sysvr4/make.sh60
-rw-r--r--dmake/unix/sysvr4/public.h164
-rw-r--r--dmake/unix/sysvr4/template.mk7
-rw-r--r--dmake/unix/xenix/config.mk27
-rw-r--r--dmake/unix/xenix/make.sh60
-rw-r--r--dmake/unix/xenix/public.h164
-rw-r--r--dmake/unix/xenix/pwd/config.mk23
-rw-r--r--dmake/unix/xenix/pwd/getcwd.c231
-rw-r--r--dmake/unix/xenix/pwd/make.sh62
-rw-r--r--dmake/unix/xenix/pwd/public.h164
-rw-r--r--dmake/unix/xenix/pwd/template.mk7
-rw-r--r--dmake/unix/xenix/stdlib.h50
-rw-r--r--dmake/unix/xenix/template.mk7
-rw-r--r--dmake/unix/xenix/time.h32
-rw-r--r--dmake/vextern.h107
-rw-r--r--dmake/win95/borland/bcc50/config.h44
-rw-r--r--dmake/win95/borland/bcc50/config.mk14
-rw-r--r--dmake/win95/borland/bcc50/lib.rsp2
-rwxr-xr-xdmake/win95/borland/bcc50/mk.bat96
-rw-r--r--dmake/win95/borland/bcc50/obj.rsp32
-rw-r--r--dmake/win95/borland/bcc50/public.h167
-rw-r--r--dmake/win95/borland/bcc50/template.mk7
-rw-r--r--dmake/win95/borland/config.mk51
-rw-r--r--dmake/win95/borland/ruletab.c44
-rw-r--r--dmake/win95/borland/sysintf.h56
-rw-r--r--dmake/win95/borland/tempnam.c114
-rw-r--r--dmake/win95/config.mk53
-rw-r--r--dmake/win95/dchdir.c49
-rw-r--r--dmake/win95/microsft/config.h78
-rw-r--r--dmake/win95/microsft/config.mk61
-rw-r--r--dmake/win95/microsft/optoff.h27
-rw-r--r--dmake/win95/microsft/ruletab.c45
-rw-r--r--dmake/win95/microsft/sysintf.h58
-rw-r--r--dmake/win95/microsft/tempnam.c110
-rw-r--r--dmake/win95/microsft/vpp40/config.mk14
-rw-r--r--dmake/win95/microsft/vpp40/lib.rsp1
-rwxr-xr-xdmake/win95/microsft/vpp40/mk.bat37
-rw-r--r--dmake/win95/microsft/vpp40/obj.rsp29
-rw-r--r--dmake/win95/microsft/vpp40/public.h166
-rw-r--r--dmake/win95/microsft/vpp40/runargv.c290
-rw-r--r--dmake/win95/microsft/vpp40/template.mk7
-rw-r--r--dmake/win95/microsft/vpp40/tempnam.c110
-rw-r--r--dmake/win95/startup.h28
-rw-r--r--dmake/win95/switchar.c43
-rw-r--r--dmake/winnt/borland/bcc50/config.h44
-rw-r--r--dmake/winnt/borland/bcc50/config.mk12
-rw-r--r--dmake/winnt/borland/bcc50/lib.rsp2
-rwxr-xr-xdmake/winnt/borland/bcc50/mk.bat95
-rwxr-xr-xdmake/winnt/borland/bcc50/mk.cmd93
-rw-r--r--dmake/winnt/borland/bcc50/obj.rsp31
-rw-r--r--dmake/winnt/borland/bcc50/public.h167
-rw-r--r--dmake/winnt/borland/bcc50/template.mk7
-rw-r--r--dmake/winnt/borland/config.mk51
-rw-r--r--dmake/winnt/borland/ruletab.c44
-rw-r--r--dmake/winnt/borland/sysintf.h56
-rw-r--r--dmake/winnt/borland/tempnam.c114
-rw-r--r--dmake/winnt/config.mk57
-rw-r--r--dmake/winnt/dchdir.c47
-rw-r--r--dmake/winnt/microsft/config.h78
-rw-r--r--dmake/winnt/microsft/config.mk61
-rw-r--r--dmake/winnt/microsft/optoff.h27
-rw-r--r--dmake/winnt/microsft/ruletab.c45
-rw-r--r--dmake/winnt/microsft/sysintf.h58
-rw-r--r--dmake/winnt/microsft/tempnam.c110
-rw-r--r--dmake/winnt/microsft/vpp40/config.mk14
-rw-r--r--dmake/winnt/microsft/vpp40/lib.rsp1
-rwxr-xr-xdmake/winnt/microsft/vpp40/mk.bat32
-rwxr-xr-xdmake/winnt/microsft/vpp40/mk.cmd31
-rw-r--r--dmake/winnt/microsft/vpp40/obj.rsp28
-rw-r--r--dmake/winnt/microsft/vpp40/public.h166
-rw-r--r--dmake/winnt/microsft/vpp40/runargv.c290
-rw-r--r--dmake/winnt/microsft/vpp40/template.mk7
-rw-r--r--dmake/winnt/microsft/vpp40/tempnam.c110
-rw-r--r--dmake/winnt/startup.h29
494 files changed, 52571 insertions, 0 deletions
diff --git a/dmake/alloc.h b/dmake/alloc.h
new file mode 100644
index 000000000000..876284de06a8
--- /dev/null
+++ b/dmake/alloc.h
@@ -0,0 +1,59 @@
+/* RCS $Id: alloc.h,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Macros for allocating memory.
+--
+-- DESCRIPTION
+-- A somewhat nicer interface to malloc and calloc.
+-- Here we standardise the calling convention with a common macro
+-- interface.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef ALLOC_h
+#define ALLOC_h
+
+/* DO NOT CHANGE these! These are the definitions that the make source
+ * uses for allocating memory. They must be defined for make to compile
+ * properly.
+ */
+
+/* This is the only place that we define size_t now. This should be more
+ * than enough! */
+#if __STDC__
+#else
+# if !defined(_TYPES_) && !defined(M_XENIX) && !defined(atarist) && !defined(_MPW) && !defined(_SIZE_T) && !defined(_SIZE_T_) && !defined(__size_t) && !defined(_WIN32)
+# if defined(MSDOS) || defined(__MSDOS__)
+# undef size_t
+ typedef unsigned size_t;
+# else
+ typedef long size_t;
+# endif
+# endif
+#endif
+
+#define usizeof(t) (size_t)sizeof(t)
+
+#define FREE(p) free((char*)(p))
+#define MALLOC(n, t) (t*) malloc((unsigned int)(n)*usizeof(t))
+#define CALLOC(n, t) (t*) calloc((unsigned int)(n), usizeof(t))
+
+#define TALLOC(p, n, t) if ((p = CALLOC(n, t)) == (t*)0) {No_ram();}
+
+#endif
+
diff --git a/dmake/dag.c b/dmake/dag.c
new file mode 100644
index 000000000000..09efcb510c99
--- /dev/null
+++ b/dmake/dag.c
@@ -0,0 +1,577 @@
+/* RCS $Id: dag.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Routines to construct the internal dag.
+--
+-- DESCRIPTION
+-- This file contains all the routines that are responsible for
+-- defining and manipulating all objects used by the make facility.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+static void
+set_macro_value(hp)
+HASHPTR hp;
+{
+ switch( hp->ht_flag & M_VAR_MASK ) /* only one var type per var */
+ {
+ case M_VAR_STRING:
+ *hp->MV_SVAR = hp->ht_value;
+ break;
+
+ case M_VAR_CHAR:
+ *hp->MV_CVAR = (hp->ht_value == NIL(char)) ? '\0':*hp->ht_value;
+ break;
+
+ case M_VAR_INT: {
+ int tvalue;
+ if( hp->MV_IVAR == NIL(int) ) break; /* first time */
+
+ tvalue = atoi(hp->ht_value);
+ if( hp->MV_IVAR == &Buffer_size ) {
+ /* If Buffer_size is modified then make sure you change the
+ * size of the real buffer as well. */
+ tvalue = (tvalue < (BUFSIZ-2)) ? BUFSIZ : tvalue+2;
+ if( Buffer_size == tvalue ) break;
+ if( Buffer ) FREE(Buffer);
+ if((Buffer=MALLOC(tvalue, char)) == NIL(char)) No_ram();
+ *Buffer = '\0';
+ }
+ *hp->MV_IVAR = tvalue;
+
+ if( hp->MV_IVAR == &Max_proc || hp->MV_IVAR == &Max_proclmt ) {
+ if( tvalue < 1 )
+ Fatal( "Process limit value must be > 1" );
+
+ if( Max_proc > Max_proclmt )
+ Fatal( "Specified # of processes exceeds limit of [%d]",
+ Max_proclmt );
+ }
+ } break;
+
+ case M_VAR_BIT:
+ /* Bit variables are set to 1 if ht_value is not NULL and 0
+ * otherwise */
+
+ if( hp->ht_value == NIL(char) )
+ *hp->MV_BVAR &= ~hp->MV_MASK;
+ else
+ *hp->MV_BVAR |= hp->MV_MASK;
+ break;
+ }
+}
+
+
+PUBLIC HASHPTR
+Get_name( name, tab, define )/*
+===============================
+ Look to see if the name is defined, if it is then return
+ a pointer to its node, if not return NIL(HASH).
+ If define is TRUE and the name is not found it will be added. */
+
+char *name; /* name we are looking for */
+HASHPTR *tab; /* the hash table to look in */
+int define; /* TRUE => add to table */
+{
+ register HASHPTR hp;
+ register char *p;
+ uint16 hv;
+ uint32 hash_key;
+
+ DB_ENTER( "Get_name" );
+ DB_PRINT( "name", ("Looking for %s", name) );
+
+ hp = Search_table( tab, name, &hv, &hash_key );
+
+ if( hp == NIL(HASH) && define ) {
+ /* Check to make sure that CELL name contains only printable chars */
+ for( p=name; *p; p++ )
+ if( !isprint(*p) && !iswhite(*p) && *p != '\n' )
+ Fatal( "Name contains non-printable character [0x%02x]", *p );
+
+ TALLOC( hp, 1, HASH ); /* allocate a cell and add it in */
+
+ hp->ht_name = DmStrDup( name );
+ hp->ht_hash = hash_key;
+ hp->ht_next = tab[ hv ];
+ tab[ hv ] = hp;
+
+ DB_PRINT( "name", ("Adding %s", name) );
+ }
+
+ DB_PRINT( "name",("Returning: [%s,%lu]",
+ (hp == NIL(HASH)) ? "":hp->ht_name, hv) );
+ DB_RETURN( hp );
+}
+
+
+PUBLIC HASHPTR
+Search_table( tab, name, phv, phkey )
+HASHPTR *tab;
+char *name;
+uint16 *phv;
+uint32 *phkey;
+{
+ HASHPTR hp;
+
+ *phv = Hash( name, phkey );
+
+ for( hp = tab[ *phv ]; hp != NIL(HASH); hp = hp->ht_next )
+ if( hp->ht_hash == *phkey
+ && !strcmp(hp->ht_name, name) )
+ break;
+
+ return( hp );
+}
+
+
+PUBLIC HASHPTR
+Push_macro(hp)
+HASHPTR hp;
+{
+ HASHPTR cur,prev;
+ uint16 hv;
+ uint32 key;
+
+ hv = Hash(hp->ht_name, &key);
+
+ for(prev=NIL(HASH),cur=Macs[hv]; cur!=NIL(HASH); prev=cur,cur=cur->ht_next)
+ if( cur->ht_hash == key
+ && !strcmp(cur->ht_name, hp->ht_name) )
+ break;
+
+ if (cur == NIL(HASH) || prev == NIL(HASH)) {
+ hp->ht_next = Macs[hv];
+ Macs[hv] = hp;
+ }
+ else {
+ hp->ht_next = prev->ht_next;
+ prev->ht_next = hp;
+ }
+
+ if (cur) {
+ memcpy((void *)&hp->var, (void *)&cur->var, sizeof(hp->var));
+ hp->ht_flag |= ((M_VAR_MASK|M_PRECIOUS) & cur->ht_flag);
+ }
+
+ return(hp);
+}
+
+
+PUBLIC HASHPTR
+Pop_macro(hp)
+HASHPTR hp;
+{
+ HASHPTR cur,prev;
+ uint16 hv;
+ uint32 key;
+
+ hv = Hash(hp->ht_name, &key);
+
+ for(prev=NIL(HASH),cur=Macs[hv]; cur != NIL(HASH);prev=cur,cur=cur->ht_next)
+ if (cur == hp)
+ break;
+
+ if (cur == NIL(HASH))
+ return(NIL(HASH));
+
+ if (prev)
+ prev->ht_next = cur->ht_next;
+ else
+ Macs[hv] = cur->ht_next;
+
+ for(cur=cur->ht_next; cur != NIL(HASH); cur=cur->ht_next)
+ if( cur->ht_hash == key
+ && !strcmp(cur->ht_name, hp->ht_name) )
+ break;
+
+ if (cur)
+ set_macro_value(cur);
+
+ hp->ht_next = NIL(HASH);
+ return(hp);
+}
+
+
+
+PUBLIC HASHPTR
+Def_macro( name, value, flags )/*
+=================================
+ This routine is used to define a macro, and it's value.
+ The flags indicates if it is a permanent macro or if it's value
+ can be redefined. A flags of M_PRECIOUS means it is a precious
+ macro and cannot be further redefined. If the flags flag also
+ contains the M_MULTI bit it means that the macro can be redefined
+ multiple times and no warning of the redefinitions should be issued.
+ Once a macro's VAR flags are set they are preserved through all future
+ macro definitions.
+
+ Macro definitions that have one of the variable bits set are treated
+ specially. In each case the hash table entry var field points at the
+ global variable that can be set by assigning to the macro.
+
+ bit valued global vars must be computed when the macro value is changed.
+ char valued global vars must have the first char of ht_value copied to
+ them. string valued global vars have the same value as ht_value and should
+ just have the new value of ht_value copied to them. */
+
+char *name; /* macro name to define */
+char *value; /* macro value to set */
+int flags; /* initial ht_flags */
+{
+ register HASHPTR hp;
+ register char *p, *q;
+
+ DB_ENTER( "Def_macro" );
+ DB_PRINT( "mac", ("Defining macro %s = %s, %x", name, value, flags) );
+
+ /* check to see if name is in the table, if so then just overwrite
+ the previous definition. Otherwise allocate a new node, and
+ stuff it in the hash table, at the front of any linked list */
+
+ if( Readenv ) flags |= M_LITERAL|M_EXPANDED;
+
+ hp = Get_name( name, Macs, TRUE );
+
+ if ((flags & M_PUSH) && hp->ht_name != NIL(char)) {
+ HASHPTR thp=hp;
+ TALLOC(hp,1,HASH);
+ hp->ht_name = DmStrDup(thp->ht_name);
+ hp->ht_hash = thp->ht_hash;
+ Push_macro(hp);
+ flags |= hp->ht_flag;
+ }
+ flags &= ~M_PUSH;
+
+ if( (hp->ht_flag & M_PRECIOUS) && !(flags & M_FORCE) ) {
+ if (Verbose & V_WARNALL)
+ Warning( "Macro `%s' cannot be redefined", name );
+ DB_RETURN( hp );
+ }
+
+ /* Make sure we don't export macros whose names contain legal macro
+ * assignment operators, since we can't do proper quoting in the
+ * environment. */
+ if( *DmStrPbrk(name, "*+:=") != '\0' ) flags |= M_NOEXPORT;
+
+ if( hp->ht_value != NIL(char) ) FREE( hp->ht_value );
+
+ if( (hp->ht_flag & M_USED) && !((flags | hp->ht_flag) & M_MULTI) )
+ Warning( "Macro `%s' redefined after use", name );
+
+ if( (value != NIL(char)) && (*value) ) {
+ /* strip out any \<nl> combinations where \ is the current CONTINUATION
+ * char */
+
+ for( p = value; (p = strchr(p, CONTINUATION_CHAR)) != NIL(char); )
+ if( p[1] == '\n' )
+ strcpy( p, p+2 );
+ else
+ p++;
+
+ if( !(flags & M_LITERAL) ) {
+ p = DmStrDup( DmStrSpn(value," \t")); /* strip white space before */
+ /* ... and after value */
+ if( *p ) {
+ for(q=p+strlen(p)-1; ((*q == ' ')||(*q == '\t')); q--);
+ *++q = '\0';
+ }
+ flags &= ~M_LITERAL;
+ }
+ else
+ p = DmStrDup( value ); /* take string literally */
+
+ if( !*p ) { /* check if result is "" */
+ FREE( p );
+ p = NIL(char);
+ flags |= M_EXPANDED;
+ }
+ else if( *DmStrPbrk( p, "${}" ) == '\0' )
+ flags |= M_EXPANDED;
+
+ hp->ht_value = p;
+ }
+ else
+ hp->ht_value = NIL(char);
+
+ /* Assign the hash table flag less the M_MULTI flag, it is used only
+ * to silence the warning. But carry it over if it was previously
+ * defined in ht_flag, as this is a permanent M_MULTI variable. */
+
+ hp->ht_flag = (((flags & ~(M_MULTI|M_FORCE)) |
+ (hp->ht_flag & (M_VAR_MASK | M_MULTI)))) & ~M_INIT;
+
+ /* Check for macro variables and make the necessary adjustment in the
+ * corresponding global variables */
+
+ if( hp->ht_flag & M_VAR_MASK )
+ if( !(flags & M_EXPANDED) )
+ Error( "Macro variable '%s' must be assigned with :=", name );
+ else
+ set_macro_value(hp);
+
+ DB_RETURN( hp );
+}
+
+
+
+PUBLIC CELLPTR
+Def_cell( name )/*
+==================
+ Take a string passed in and define it as a cell
+ If the cell exists then return a pointer to it. */
+char *name;
+{
+ register HASHPTR hp;
+ register CELLPTR cp;
+ register CELLPTR lib;
+ char *member;
+ char *end;
+
+ DB_ENTER( "Def_cell" );
+
+ /* Check to see if the cell is a member of the form lib(member) or
+ * lib((symbol)) and handle the cases appropriately.
+ * What we do is we look at the target, if it is of the above two
+ * forms we get the lib, and add the member/symbol to the list of
+ * prerequisites for the library. If this is a symbol name def'n
+ * we additionally add the attribute A_SYMBOL, so that stat can
+ * try to do the right thing. */
+
+ if( ((member = strchr(name, '(')) != NIL(char)) &&
+ ((end = strrchr(member, ')')) != NIL(char)) &&
+ (member > name) && (member[-1] != '$') &&
+ (end > member+1) && (end[1] == '\0') )
+ {
+ *member++ = *end = '\0';
+
+ if( (*member == '(') && (member[strlen(member)-1] == ')') ) {
+ member[ strlen(member)-1 ] = '\0';
+ cp = Def_cell( member+1 );
+ cp->ce_attr |= A_SYMBOL;
+ }
+ else
+ cp = Def_cell( member );
+
+ lib = Def_cell( name );
+
+ Add_prerequisite( lib, cp, FALSE, FALSE );
+ lib->ce_attr |= A_LIBRARY | A_COMPOSITE;
+
+ if( !Def_targets ) cp = lib;
+ }
+ else {
+ hp = Get_name( name, Defs, TRUE );/* get the name from hash table */
+
+ if( hp->CP_OWNR == NIL(CELL) ) /* was it previously defined */
+ { /* NO, so define a new cell */
+ DB_PRINT( "cell", ("Defining cell [%s]", name) );
+
+ TALLOC( cp, 1, CELL );
+ hp->CP_OWNR = cp;
+ cp->ce_name = hp;
+ cp->ce_fname = hp->ht_name;
+ cp->ce_all.cl_prq = cp;
+ }
+ else /* YES, so return the old cell */
+ {
+ DB_PRINT( "cell", ("Getting cell [%s]", hp->ht_name) );
+ cp = hp->CP_OWNR;
+ }
+ }
+
+ DB_RETURN( cp );
+}
+
+
+
+
+PUBLIC LINKPTR
+Add_prerequisite( cell, prq, head, force )/*
+============================================
+ Add a dependency node to the dag. It adds it to the prerequisites,
+ if any, of the cell and makes certain they are in linear order.
+ If head == 1, then add to head of the prerequisite list, else
+ add to tail. */
+CELLPTR cell;
+CELLPTR prq;
+int head;
+int force;
+{
+ register LINKPTR lp, tlp;
+
+ DB_ENTER( "Add_prerequisite" );
+ DB_PRINT( "cell", ("Defining prerequisite %s", prq->CE_NAME) );
+
+ if( (prq->ce_flag & (F_MAGIC | F_PERCENT)) && !force )
+ Fatal( "Special target [%s] cannot be a prerequisite",
+ prq->CE_NAME );
+
+ if( cell->ce_prq == NIL(LINK) ) { /* it's the first one */
+ TALLOC( lp, 1, LINK );
+ lp->cl_prq = prq;
+ cell->ce_prq = lp;
+ }
+ else { /* search the list, checking for duplicates */
+ for( lp = cell->ce_prq;
+ (lp->cl_next != NIL(LINK)) && (lp->cl_prq != prq);
+ lp = lp->cl_next );
+
+ /* If the prq is not found and we are at the last prq in the list,
+ * allocate a new prq and place it into the list, insert it at the
+ * head if head == 1, else we add it to the end. */
+
+ if( lp->cl_prq != prq ) {
+ TALLOC( tlp, 1, LINK );
+ tlp->cl_prq = prq;
+
+ if( head ) {
+ tlp->cl_next = cell->ce_prq;
+ cell->ce_prq = tlp;
+ }
+ else
+ lp->cl_next = tlp;
+
+ lp = tlp;
+ }
+ }
+
+ DB_RETURN( lp );
+}
+
+
+
+PUBLIC void
+Clear_prerequisites( cell )/*
+=============================
+ Clear out the list of prerequisites, freeing all of the LINK nodes,
+ and setting the list to NULL */
+CELLPTR cell;
+{
+ LINKPTR lp, tlp;
+
+ DB_ENTER( "Clear_prerequisites" );
+ DB_PRINT( "cell", ("Nuking prerequisites") );
+
+ if( cell == NIL(CELL) ) { DB_VOID_RETURN; }
+
+ for( lp=cell->ce_prq; lp != NIL(LINK); lp=tlp ) {
+ tlp=lp->cl_next;
+ FREE( lp );
+ }
+
+ cell->ce_prq = NIL(LINK);
+
+ DB_VOID_RETURN;
+}
+
+
+PUBLIC int
+Test_circle( cp, fail )/*
+=========================
+ Actually run through the graph */
+CELLPTR cp;
+int fail;
+{
+ register LINKPTR lp;
+ int res = 0;
+
+ DB_ENTER( "Test_circle" );
+ DB_PRINT( "tc", ("checking [%s]", cp->CE_NAME) );
+
+ if( cp->ce_flag & F_MARK )
+ if( fail )
+ Fatal("Detected circular dependency in graph at [%s]", cp->CE_NAME);
+ else
+ DB_RETURN( 1 );
+
+ cp->ce_flag |= F_MARK;
+ for( lp = cp->ce_prq; !res && lp != NIL(LINK); lp = lp->cl_next )
+ res = Test_circle( lp->cl_prq, fail );
+ cp->ce_flag ^= F_MARK;
+
+ DB_RETURN( res );
+}
+
+
+
+PUBLIC STRINGPTR
+Def_recipe( rcp, sp, white_too, no_check )/*
+=============================================
+ Take the recipe and add it to the list of recipes
+ pointed to by sp. sp points to the last element.
+ return a pointer to the new recipe. If white_too == TRUE add the
+ recipe even if it contains only white space.
+ If no_check is true then don't look for -@ at the start of the
+ recipe line. */
+char *rcp;
+STRINGPTR sp;
+int white_too;
+int no_check;
+{
+ register STRINGPTR nsp;
+ register char *rp;
+
+ DB_ENTER( "Def_recipe" );
+ DB_PRINT( "rul", ("Defining recipe %s", rcp) );
+
+ if( !white_too ) rcp = DmStrSpn( rcp, " \t" );
+ if( (rcp == NIL(char)) || (*rcp == 0 && !white_too) )
+ DB_RETURN( sp ); /* return last recipe when new recipe not added */
+
+ rp = no_check ? rcp : DmStrSpn( rcp, " \t@-+%" );
+
+ TALLOC(nsp, 1, STRING);
+ nsp->st_string = DmStrDup( rp );
+
+ if( sp != NIL(STRING) ) sp->st_next = nsp;
+ nsp->st_next = NIL(STRING);
+
+ if( !no_check ) nsp->st_attr |= Rcp_attribute( rcp );
+
+ DB_RETURN( nsp );
+}
+
+
+PUBLIC t_attr
+Rcp_attribute( rp )/*
+======================
+ Look at the recipe and return the set of attributes that it defines. */
+char *rp;
+{
+ t_attr flag = A_DEFAULT;
+ int done = FALSE;
+
+ while( !done )
+ switch( *rp++ )
+ {
+ case '@' : flag |= A_SILENT; break;
+ case '-' : flag |= A_IGNORE; break;
+ case '+' : flag |= A_SHELL; break;
+ case '%' : flag |= A_SWAP; break;
+
+ case ' ' :
+ case '\t': break;
+
+ default: done = TRUE; break;
+ }
+
+ return(flag);
+}
diff --git a/dmake/db.h b/dmake/db.h
new file mode 100644
index 000000000000..a640dfaee7a4
--- /dev/null
+++ b/dmake/db.h
@@ -0,0 +1,66 @@
+/* RCS $Id: db.h,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Front end to DBUG macros.
+--
+-- DESCRIPTION
+-- This is a front end to Fred Fish's DBUG macros. The intent was
+-- to provide an interface so that if you don't have the DBUG code
+-- you can still compile dmake, by undefining DBUG, if you do have
+-- the code then you can use Fred Fish's DBUG package. Originally
+-- the DBUG stuff was copyrighted, it is now in the public domain
+-- so the need for this is not as apparent.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef DB_h
+#define DB_h
+
+#ifdef DBUG
+
+# include "dbug.h"
+
+# define DB_ENTER(a1) DBUG_ENTER(a1)
+# define DB_RETURN(a1) DBUG_RETURN(a1)
+# define DB_VOID_RETURN DBUG_VOID_RETURN
+# define DB_EXECUTE(keyword, a1) DBUG_EXECUTE(keyword,a1)
+# define DB_PRINT(keyword,arglist) DBUG_PRINT(keyword,arglist)
+# define DB_PUSH(a1) DBUG_PUSH(a1)
+# define DB_POP() DBUG_POP()
+# define DB_PROCESS(a1) DBUG_PROCESS(a1)
+# define DB_FILE(file) DBUG_FILE(file)
+# define DB_SETJMP DBUG_SETJMP
+# define DB_LONGJMP DBUG_LONGJMP
+
+#else
+
+# define DB_ENTER(a1)
+# define DB_RETURN(a1) return (a1)
+# define DB_VOID_RETURN return
+# define DB_EXECUTE(keyword, a1)
+# define DB_PRINT(keyword,arglist)
+# define DB_PUSH(a1)
+# define DB_POP()
+# define DB_PROCESS(a1)
+# define DB_FILE(file)
+# define DB_SETJMP setjmp
+# define DB_LONGJMP longjmp
+
+#endif
+#endif
+
diff --git a/dmake/dbug/dbug.mk b/dmake/dbug/dbug.mk
new file mode 100644
index 000000000000..09aa82d7f37d
--- /dev/null
+++ b/dmake/dbug/dbug.mk
@@ -0,0 +1,66 @@
+# Set the proper macros based on whether we are making the debugging version
+# or not. The valid parameters to this file are:
+#
+# DEBUG=1 ==> enable the making of the DBUG version
+# DBMALLOC=1 ==> enable DBUG version with extensive MALLOC checking
+#
+# DB_CFLAGS ==> CFLAGS is set to this value at the end if DEBUG=1
+# DB_LDFLAGS ==> LDFLAGS is set to this at the end if DEBUG=1
+# DB_LDLIBS ==> LDLIBS is set to this at end if DEBUG=1
+#
+# The non debug versions of the above three macros are:
+#
+# NDB_CFLAGS
+# NDB_LDFLAGS
+# NDB_LDLIBS
+#
+# One of the set of three should have values set appropriately prior to
+# sourcing this file.
+
+.IF $(DEBUG)
+ DBUG_SRC += dbug.c
+ DB_CFLAGS += -Idbug/dbug
+
+ .SETDIR=dbug/dbug : $(DBUG_SRC)
+
+ # If DBMALLOC is requested (ie non-NULL) then include the sources for
+ # compilation. BSD 4.3 needs the getwd.c source compiled in due to a bug
+ # in the clib getwd routine.
+ .IF $(DBMALLOC)
+ # Serious bug in bsd43 getwd.c would free a string and then use its
+ # value. The DBMALLOC code clears a string when it is free'd so the
+ # value was no longer valid and the returned path for the current
+ # directory was now completely wrong.
+ .IF $(OSRELEASE) == bsd43
+ GETWD_SRC += getwd.c
+ .SETDIR=dbug : $(GETWD_SRC)
+ .END
+
+ MLC_SRC += malloc.c free.c realloc.c calloc.c string.c\
+ mlc_chk.c mlc_chn.c memory.c tostring.c m_perror.c\
+ m_init.c mallopt.c dump.c
+
+ .SETDIR=dbug/malloc : $(MLC_SRC)
+
+ DB_CFLAGS += -Idbug/malloc
+ .END
+
+ SRC += $(DBUG_SRC) $(MLC_SRC) $(GETWD_SRC)
+ HDR += db.h
+
+ LDFLAGS += $(DB_LDFLAGS)
+ LDLIBS += $(DB_LDLIBS)
+
+ __.SILENT !:= $(.SILENT)
+ .SILENT !:= yes
+ TARGET := db$(TARGET)
+ OBJDIR := $(OBJDIR).dbg
+ .SILENT !:= $(__.SILENT)
+
+ CFLAGS += $(DB_CFLAGS)
+ .KEEP_STATE := _dbstate.mk
+.ELSE
+ CFLAGS += $(NDB_CFLAGS)
+ LDFLAGS += $(NDB_LDFLAGS)
+ LDLIBS += $(NDB_LDLIBS)
+.END
diff --git a/dmake/dbug/dbug/dbug.c b/dmake/dbug/dbug/dbug.c
new file mode 100644
index 000000000000..c20db79315b6
--- /dev/null
+++ b/dmake/dbug/dbug/dbug.c
@@ -0,0 +1,1834 @@
+/******************************************************************************
+ * *
+ * N O T I C E *
+ * *
+ * Copyright Abandoned, 1987, Fred Fish *
+ * *
+ * *
+ * This previously copyrighted work has been placed into the public *
+ * domain by the author and may be freely used for any purpose, *
+ * private or commercial. *
+ * *
+ * Because of the number of inquiries I was receiving about the use *
+ * of this product in commercially developed works I have decided to *
+ * simply make it public domain to further its unrestricted use. I *
+ * specifically would be most happy to see this material become a *
+ * part of the standard Unix distributions by AT&T and the Berkeley *
+ * Computer Science Research Group, and a standard part of the GNU *
+ * system from the Free Software Foundation. *
+ * *
+ * I would appreciate it, as a courtesy, if this notice is left in *
+ * all copies and derivative works. Thank you. *
+ * *
+ * The author makes no warranty of any kind with respect to this *
+ * product and explicitly disclaims any implied warranties of mer- *
+ * chantability or fitness for any particular purpose. *
+ * *
+ ******************************************************************************
+ */
+
+
+/*
+ * FILE
+ *
+ * dbug.c runtime support routines for dbug package
+ *
+ * SCCS
+ *
+ * @(#)dbug.c 1.19 9/5/87
+ *
+ * DESCRIPTION
+ *
+ * These are the runtime support routines for the dbug package.
+ * The dbug package has two main components; the user include
+ * file containing various macro definitions, and the runtime
+ * support routines which are called from the macro expansions.
+ *
+ * Externally visible functions in the runtime support module
+ * use the naming convention pattern "_db_xx...xx_", thus
+ * they are unlikely to collide with user defined function names.
+ *
+ * AUTHOR(S)
+ *
+ * Fred Fish (base code)
+ * (Currently at Motorola Computer Division, Tempe, Az.)
+ * hao!noao!mcdsun!fnf
+ * (602) 438-3614
+ *
+ * Binayak Banerjee (profiling enhancements)
+ * seismo!bpa!sjuvax!bbanerje
+ */
+
+
+#include <stdio.h>
+#ifdef amiga
+#define AMIGA
+#endif
+
+#ifdef AMIGA
+#define HZ (50) /* Probably in some header somewhere */
+#endif
+
+/*
+ * Manifest constants that should not require any changes.
+ */
+
+#define FALSE 0 /* Boolean FALSE */
+#define TRUE 1 /* Boolean TRUE */
+#define EOS '\000' /* End Of String marker */
+
+/*
+ * Manifest constants which may be "tuned" if desired.
+ */
+
+#define PRINTBUF 1024 /* Print buffer size */
+#define INDENT 4 /* Indentation per trace level */
+#define MAXDEPTH 200 /* Maximum trace depth default */
+
+/*
+ * The following flags are used to determine which
+ * capabilities the user has enabled with the state
+ * push macro.
+ */
+
+#define TRACE_ON 000001 /* Trace enabled */
+#define DEBUG_ON 000002 /* Debug enabled */
+#define FILE_ON 000004 /* File name print enabled */
+#define LINE_ON 000010 /* Line number print enabled */
+#define DEPTH_ON 000020 /* Function nest level print enabled */
+#define PROCESS_ON 000040 /* Process name print enabled */
+#define NUMBER_ON 000100 /* Number each line of output */
+#define PROFILE_ON 000200 /* Print out profiling code */
+
+#define TRACING (stack -> flags & TRACE_ON)
+#define DEBUGGING (stack -> flags & DEBUG_ON)
+#define PROFILING (stack -> flags & PROFILE_ON)
+#define STREQ(a,b) (strcmp(a,b) == 0)
+
+/*
+ * Typedefs to make things more obvious.
+ */
+
+#define VOID void /* Can't use typedef for most compilers */
+typedef int BOOLEAN;
+
+/*
+ * Make it easy to change storage classes if necessary.
+ */
+
+#define LOCAL static /* Names not needed by outside world */
+#define IMPORT extern /* Names defined externally */
+#define EXPORT /* Allocated here, available globally */
+#define AUTO auto /* Names to be allocated on stack */
+#define REGISTER register /* Names to be placed in registers */
+
+/*
+ * The following define is for the variable arguments kluge, see
+ * the comments in _db_doprnt_().
+ *
+ * Also note that the longer this list, the less prone to failing
+ * on long argument lists, but the more stuff that must be moved
+ * around for each call to the runtime support routines. The
+ * length may really be critical if the machine convention is
+ * to pass arguments in registers.
+ *
+ * Note that the default define allows up to 16 integral arguments,
+ * or 8 floating point arguments (doubles), on most machines.
+ *
+ * Someday this may be replaced with true varargs support, when
+ * ANSI C has had time to take root.
+ */
+
+#define ARGLIST a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15
+
+/*
+ * The default file for profiling. Could also add another flag
+ * (G?) which allowed the user to specify this.
+ */
+
+#define PROF_FILE "dbugmon.out"
+
+/*
+ * Variables which are available externally but should only
+ * be accessed via the macro package facilities.
+ */
+
+EXPORT FILE *_db_fp_ = stderr; /* Output stream, default stderr */
+EXPORT FILE *_db_pfp_ = (FILE *)0; /* Profile stream, 'dbugmon.out' */
+EXPORT char *_db_process_ = "dbug"; /* Pointer to process name; argv[0] */
+EXPORT BOOLEAN _db_on_ = FALSE; /* TRUE if debugging currently on */
+EXPORT BOOLEAN _db_pon_ = FALSE; /* TRUE if debugging currently on */
+
+/*
+ * Externally supplied functions.
+ */
+
+#ifdef unix /* Only needed for unix */
+IMPORT VOID perror (); /* Print system/library error */
+IMPORT int chown (); /* Change owner of a file */
+IMPORT int getgid (); /* Get real group id */
+IMPORT int getuid (); /* Get real user id */
+IMPORT int access (); /* Test file for access */
+#else
+#if !(AMIGA || LATTICE || __TURBOC__)
+LOCAL VOID perror (); /* Fake system/library error print routine */
+#endif
+#endif
+
+# if BSD4_3 || sun
+IMPORT int getrusage ();
+#endif
+
+IMPORT int atoi (); /* Convert ascii to integer */
+IMPORT VOID exit (); /* Terminate execution */
+IMPORT int fclose (); /* Close a stream */
+IMPORT FILE *fopen (); /* Open a stream */
+#if !defined(__BORLANDC__)
+IMPORT int fprintf (); /* Formatted print on file */
+#endif
+IMPORT VOID free ();
+IMPORT char *malloc (); /* Allocate memory */
+IMPORT int strcmp (); /* Compare strings */
+IMPORT char *strcpy (); /* Copy strings around */
+IMPORT int strlen (); /* Find length of string */
+
+#ifndef fflush /* This is sometimes a macro */
+IMPORT int fflush (); /* Flush output for stream */
+#endif
+
+
+/*
+ * The user may specify a list of functions to trace or
+ * debug. These lists are kept in a linear linked list,
+ * a very simple implementation.
+ */
+
+struct link {
+ char *string; /* Pointer to link's contents */
+ struct link *next_link; /* Pointer to the next link */
+};
+
+
+/*
+ * Debugging states can be pushed or popped off of a
+ * stack which is implemented as a linked list. Note
+ * that the head of the list is the current state and the
+ * stack is pushed by adding a new state to the head of the
+ * list or popped by removing the first link.
+ */
+
+struct state {
+ int flags; /* Current state flags */
+ int maxdepth; /* Current maximum trace depth */
+ unsigned int delay; /* Delay after each output line */
+ int level; /* Current function nesting level */
+ FILE *out_file; /* Current output stream */
+ FILE *prof_file; /* Current profiling stream */
+ struct link *functions; /* List of functions */
+ struct link *p_functions; /* List of profiled functions */
+ struct link *keywords; /* List of debug keywords */
+ struct link *processes; /* List of process names */
+ struct state *next_state; /* Next state in the list */
+};
+
+LOCAL struct state *stack = NULL; /* Linked list of stacked states */
+
+/*
+ * Local variables not seen by user.
+ */
+
+LOCAL int lineno = 0; /* Current debugger output line number */
+LOCAL char *func = "?func"; /* Name of current user function */
+LOCAL char *file = "?file"; /* Name of current user file */
+LOCAL BOOLEAN init_done = FALSE;/* Set to TRUE when initialization done */
+
+/*#if unix || AMIGA || M_I86*/
+LOCAL int jmplevel; /* Remember nesting level at setjmp () */
+LOCAL char *jmpfunc; /* Remember current function for setjmp */
+LOCAL char *jmpfile; /* Remember current file for setjmp */
+/*#endif*/
+
+LOCAL struct link *ListParse ();/* Parse a debug command string */
+LOCAL char *StrDup (); /* Make a fresh copy of a string */
+LOCAL VOID OpenFile (); /* Open debug output stream */
+LOCAL VOID OpenProfile (); /* Open profile output stream */
+LOCAL VOID CloseFile (); /* Close debug output stream */
+LOCAL VOID PushState (); /* Push current debug state */
+LOCAL VOID ChangeOwner (); /* Change file owner and group */
+LOCAL BOOLEAN DoTrace (); /* Test for tracing enabled */
+LOCAL BOOLEAN Writable (); /* Test to see if file is writable */
+LOCAL unsigned long Clock (); /* Return current user time (ms) */
+LOCAL char *DbugMalloc (); /* Allocate memory for runtime support */
+LOCAL char *BaseName (); /* Remove leading pathname components */
+LOCAL VOID DoPrefix (); /* Print debugger line prefix */
+LOCAL VOID FreeList (); /* Free memory from linked list */
+LOCAL VOID Indent (); /* Indent line to specified indent */
+
+ /* Supplied in Sys V runtime environ */
+LOCAL char *strtok (); /* Break string into tokens */
+LOCAL char *strrchr (); /* Find last occurance of char */
+
+/*
+ * The following local variables are used to hold the state information
+ * between the call to _db_pargs_() and _db_doprnt_(), during
+ * expansion of the DBUG_PRINT macro. This is the only macro
+ * that currently uses these variables. The DBUG_PRINT macro
+ * and the new _db_doprnt_() routine replace the older DBUG_N macros
+ * and their corresponding runtime support routine _db_printf_().
+ *
+ * These variables are currently used only by _db_pargs_() and
+ * _db_doprnt_().
+ */
+
+LOCAL int u_line = 0; /* User source code line number */
+LOCAL char *u_keyword = "?"; /* Keyword for current macro */
+
+/*
+ * Miscellaneous printf format strings.
+ */
+
+#define ERR_MISSING_RETURN "%s: missing DBUG_RETURN or DBUG_VOID_RETURN macro in function \"%s\"\n"
+#define ERR_OPEN "%s: can't open debug output stream \"%s\": "
+#define ERR_CLOSE "%s: can't close debug file: "
+#define ERR_ABORT "%s: debugger aborting because %s\n"
+#define ERR_CHOWN "%s: can't change owner/group of \"%s\": "
+#define ERR_PRINTF "%s: obsolete object file for '%s', please recompile!\n"
+
+/*
+ * Macros and defines for testing file accessibility under UNIX.
+ */
+
+#ifdef unix
+# define A_EXISTS 00 /* Test for file existance */
+# define A_EXECUTE 01 /* Test for execute permission */
+# define A_WRITE 02 /* Test for write access */
+# define A_READ 03 /* Test for read access */
+# define EXISTS(pathname) (access (pathname, A_EXISTS) == 0)
+# define WRITABLE(pathname) (access (pathname, A_WRITE) == 0)
+#else
+# define EXISTS(pathname) (FALSE) /* Assume no existance */
+#endif
+
+/*
+ * Translate some calls among different systems.
+ */
+
+#ifdef unix
+# define XDelay sleep
+IMPORT unsigned int sleep (); /* Pause for given number of seconds */
+#endif
+
+#ifdef AMIGA
+IMPORT int XDelay (); /* Pause for given number of ticks */
+#endif
+
+
+/*
+ * FUNCTION
+ *
+ * _db_push_ push current debugger state and set up new one
+ *
+ * SYNOPSIS
+ *
+ * VOID _db_push_ (control)
+ * char *control;
+ *
+ * DESCRIPTION
+ *
+ * Given pointer to a debug control string in "control", pushes
+ * the current debug state, parses the control string, and sets
+ * up a new debug state.
+ *
+ * The only attribute of the new state inherited from the previous
+ * state is the current function nesting level. This can be
+ * overridden by using the "r" flag in the control string.
+ *
+ * The debug control string is a sequence of colon separated fields
+ * as follows:
+ *
+ * <field_1>:<field_2>:...:<field_N>
+ *
+ * Each field consists of a mandatory flag character followed by
+ * an optional "," and comma separated list of modifiers:
+ *
+ * flag[,modifier,modifier,...,modifier]
+ *
+ * The currently recognized flag characters are:
+ *
+ * d Enable output from DBUG_<N> macros for
+ * for the current state. May be followed
+ * by a list of keywords which selects output
+ * only for the DBUG macros with that keyword.
+ * A null list of keywords implies output for
+ * all macros.
+ *
+ * D Delay after each debugger output line.
+ * The argument is the number of tenths of seconds
+ * to delay, subject to machine capabilities.
+ * I.E. -#D,20 is delay two seconds.
+ *
+ * f Limit debugging and/or tracing, and profiling to the
+ * list of named functions. Note that a null list will
+ * disable all functions. The appropriate "d" or "t"
+ * flags must still be given, this flag only limits their
+ * actions if they are enabled.
+ *
+ * F Identify the source file name for each
+ * line of debug or trace output.
+ *
+ * g Enable profiling. Create a file called 'dbugmon.out'
+ * containing information that can be used to profile
+ * the program. May be followed by a list of keywords
+ * that select profiling only for the functions in that
+ * list. A null list implies that all functions are
+ * considered.
+ *
+ * L Identify the source file line number for
+ * each line of debug or trace output.
+ *
+ * n Print the current function nesting depth for
+ * each line of debug or trace output.
+ *
+ * N Number each line of dbug output.
+ *
+ * p Limit debugger actions to specified processes.
+ * A process must be identified with the
+ * DBUG_PROCESS macro and match one in the list
+ * for debugger actions to occur.
+ *
+ * P Print the current process name for each
+ * line of debug or trace output.
+ *
+ * r When pushing a new state, do not inherit
+ * the previous state's function nesting level.
+ * Useful when the output is to start at the
+ * left margin.
+ *
+ * t Enable function call/exit trace lines.
+ * May be followed by a list (containing only
+ * one modifier) giving a numeric maximum
+ * trace level, beyond which no output will
+ * occur for either debugging or tracing
+ * macros. The default is a compile time
+ * option.
+ *
+ * Some examples of debug control strings which might appear
+ * on a shell command line (the "-#" is typically used to
+ * introduce a control string to an application program) are:
+ *
+ * -#d:t
+ * -#d:f,main,subr1:F:L:t,20
+ * -#d,input,output,files:n
+ *
+ * For convenience, any leading "-#" is stripped off.
+ *
+ */
+
+
+VOID _db_push_ (control)
+char *control;
+{
+ REGISTER char *scan;
+ REGISTER struct link *temp;
+
+ if (control && *control == '-') {
+ if (*++control == '#') {
+ control++;
+ }
+ }
+ control = StrDup (control);
+ PushState ();
+ scan = strtok (control, ":");
+ for (; scan != NULL; scan = strtok ((char *)NULL, ":")) {
+ switch (*scan++) {
+ case 'd':
+ _db_on_ = TRUE;
+ stack -> flags |= DEBUG_ON;
+ if (*scan++ == ',') {
+ stack -> keywords = ListParse (scan);
+ }
+ break;
+ case 'D':
+ stack -> delay = 0;
+ if (*scan++ == ',') {
+ temp = ListParse (scan);
+ stack -> delay = DelayArg (atoi (temp -> string));
+ FreeList (temp);
+ }
+ break;
+ case 'f':
+ if (*scan++ == ',') {
+ stack -> functions = ListParse (scan);
+ }
+ break;
+ case 'F':
+ stack -> flags |= FILE_ON;
+ break;
+ case 'g':
+ _db_pon_ = TRUE;
+ OpenProfile(PROF_FILE);
+ stack -> flags |= PROFILE_ON;
+ if (*scan++ == ',') {
+ stack -> p_functions = ListParse (scan);
+ }
+ break;
+ case 'L':
+ stack -> flags |= LINE_ON;
+ break;
+ case 'n':
+ stack -> flags |= DEPTH_ON;
+ break;
+ case 'N':
+ stack -> flags |= NUMBER_ON;
+ break;
+ case 'o':
+ if (*scan++ == ',') {
+ temp = ListParse (scan);
+ OpenFile (temp -> string);
+ FreeList (temp);
+ } else {
+ OpenFile ("-");
+ }
+ break;
+ case 'p':
+ if (*scan++ == ',') {
+ stack -> processes = ListParse (scan);
+ }
+ break;
+ case 'P':
+ stack -> flags |= PROCESS_ON;
+ break;
+ case 'r':
+ stack -> level = 0;
+ break;
+ case 't':
+ stack -> flags |= TRACE_ON;
+ if (*scan++ == ',') {
+ temp = ListParse (scan);
+ stack -> maxdepth = atoi (temp -> string);
+ FreeList (temp);
+ }
+ break;
+ }
+ }
+ free (control);
+}
+
+
+
+/*
+ * FUNCTION
+ *
+ * _db_pop_ pop the debug stack
+ *
+ * DESCRIPTION
+ *
+ * Pops the debug stack, returning the debug state to its
+ * condition prior to the most recent _db_push_ invocation.
+ * Note that the pop will fail if it would remove the last
+ * valid state from the stack. This prevents user errors
+ * in the push/pop sequence from screwing up the debugger.
+ * Maybe there should be some kind of warning printed if the
+ * user tries to pop too many states.
+ *
+ */
+
+VOID _db_pop_ ()
+{
+ REGISTER struct state *discard;
+
+ discard = stack;
+ if (discard != NULL && discard -> next_state != NULL) {
+ stack = discard -> next_state;
+ _db_fp_ = stack -> out_file;
+ _db_pfp_ = stack -> prof_file;
+ if (discard -> keywords != NULL) {
+ FreeList (discard -> keywords);
+ }
+ if (discard -> functions != NULL) {
+ FreeList (discard -> functions);
+ }
+ if (discard -> processes != NULL) {
+ FreeList (discard -> processes);
+ }
+ if (discard -> p_functions != NULL) {
+ FreeList (discard -> p_functions);
+ }
+ CloseFile (discard -> out_file);
+ CloseFile (discard -> prof_file);
+ free ((char *) discard);
+ }
+}
+
+
+/*
+ * FUNCTION
+ *
+ * _db_enter_ process entry point to user function
+ *
+ * SYNOPSIS
+ *
+ * VOID _db_enter_ (_func_, _file_, _line_, _sfunc_, _sfile_, _slevel_)
+ * char *_func_; points to current function name
+ * char *_file_; points to current file name
+ * int _line_; called from source line number
+ * char **_sfunc_; save previous _func_
+ * char **_sfile_; save previous _file_
+ * int *_slevel_; save previous nesting level
+ *
+ * DESCRIPTION
+ *
+ * Called at the beginning of each user function to tell
+ * the debugger that a new function has been entered.
+ * Note that the pointers to the previous user function
+ * name and previous user file name are stored on the
+ * caller's stack (this is why the ENTER macro must be
+ * the first "executable" code in a function, since it
+ * allocates these storage locations). The previous nesting
+ * level is also stored on the callers stack for internal
+ * self consistency checks.
+ *
+ * Also prints a trace line if tracing is enabled and
+ * increments the current function nesting depth.
+ *
+ * Note that this mechanism allows the debugger to know
+ * what the current user function is at all times, without
+ * maintaining an internal stack for the function names.
+ *
+ */
+
+VOID _db_enter_ (_func_, _file_, _line_, _sfunc_, _sfile_, _slevel_)
+char *_func_;
+char *_file_;
+int _line_;
+char **_sfunc_;
+char **_sfile_;
+int *_slevel_;
+{
+ if (!init_done) {
+ _db_push_ ("");
+ }
+ *_sfunc_ = func;
+ *_sfile_ = file;
+ func = _func_;
+ file = BaseName (_file_);
+ stack -> level++;
+ *_slevel_ = stack -> level;
+ if (DoProfile ()) {
+ (VOID) fprintf (_db_pfp_, "%s\tE\t%ld\n",func, Clock());
+ (VOID) fflush (_db_pfp_);
+ }
+ if (DoTrace ()) {
+ DoPrefix (_line_);
+ Indent (stack -> level);
+ (VOID) fprintf (_db_fp_, ">%s\n", func);
+ (VOID) fflush (_db_fp_);
+ (VOID) XDelay (stack -> delay);
+ }
+}
+
+
+/*
+ * FUNCTION
+ *
+ * _db_return_ process exit from user function
+ *
+ * SYNOPSIS
+ *
+ * VOID _db_return_ (_line_, _sfunc_, _sfile_, _slevel_)
+ * int _line_; current source line number
+ * char **_sfunc_; where previous _func_ is to be retrieved
+ * char **_sfile_; where previous _file_ is to be retrieved
+ * int *_slevel_; where previous level was stashed
+ *
+ * DESCRIPTION
+ *
+ * Called just before user function executes an explicit or implicit
+ * return. Prints a trace line if trace is enabled, decrements
+ * the current nesting level, and restores the current function and
+ * file names from the defunct function's stack.
+ *
+ */
+
+VOID _db_return_ (_line_, _sfunc_, _sfile_, _slevel_)
+int _line_;
+char **_sfunc_;
+char **_sfile_;
+int *_slevel_;
+{
+ if (!init_done) {
+ _db_push_ ("");
+ }
+ if (stack -> level != *_slevel_ && (TRACING || DEBUGGING || PROFILING)) {
+ (VOID) fprintf (_db_fp_, ERR_MISSING_RETURN, _db_process_, func);
+ (VOID) XDelay (stack -> delay);
+ } else if (DoProfile ()) {
+ (VOID) fprintf (_db_pfp_, "%s\tX\t%ld\n", func, Clock());
+ (VOID) XDelay (stack -> delay);
+ } else if (DoTrace ()) {
+ DoPrefix (_line_);
+ Indent (stack -> level);
+ (VOID) fprintf (_db_fp_, "<%s\n", func);
+ (VOID) XDelay (stack -> delay);
+ }
+ (VOID) fflush (_db_fp_);
+ stack -> level = *_slevel_ - 1;
+ func = *_sfunc_;
+ file = *_sfile_;
+}
+
+
+/*
+ * FUNCTION
+ *
+ * _db_pargs_ log arguments for subsequent use by _db_doprnt_()
+ *
+ * SYNOPSIS
+ *
+ * VOID _db_pargs_ (_line_, keyword)
+ * int _line_;
+ * char *keyword;
+ *
+ * DESCRIPTION
+ *
+ * The new universal printing macro DBUG_PRINT, which replaces
+ * all forms of the DBUG_N macros, needs two calls to runtime
+ * support routines. The first, this function, remembers arguments
+ * that are used by the subsequent call to _db_doprnt_().
+*
+ */
+
+VOID _db_pargs_ (_line_, keyword)
+int _line_;
+char *keyword;
+{
+ u_line = _line_;
+ u_keyword = keyword;
+}
+
+
+/*
+ * FUNCTION
+ *
+ * _db_doprnt_ handle print of debug lines
+ *
+ * SYNOPSIS
+ *
+ * VOID _db_doprnt_ (format, ARGLIST)
+ * char *format;
+ * long ARGLIST;
+ *
+ * DESCRIPTION
+ *
+ * When invoked via one of the DBUG macros, tests the current keyword
+ * set by calling _db_pargs_() to see if that macro has been selected
+ * for processing via the debugger control string, and if so, handles
+ * printing of the arguments via the format string. The line number
+ * of the DBUG macro in the source is found in u_line.
+ *
+ * Note that the format string SHOULD NOT include a terminating
+ * newline, this is supplied automatically.
+ *
+ * NOTES
+ *
+ * This runtime support routine replaces the older _db_printf_()
+ * routine which is temporarily kept around for compatibility.
+ *
+ * The rather ugly argument declaration is to handle some
+ * magic with respect to the number of arguments passed
+ * via the DBUG macros. The current maximum is 3 arguments
+ * (not including the keyword and format strings).
+ *
+ * The new <varargs.h> facility is not yet common enough to
+ * convert to it quite yet...
+ *
+ */
+
+/*VARARGS1*/
+VOID _db_doprnt_ (format, ARGLIST)
+char *format;
+long ARGLIST;
+{
+ if (_db_keyword_ (u_keyword)) {
+ DoPrefix (u_line);
+ if (TRACING) {
+ Indent (stack -> level + 1);
+ } else {
+ (VOID) fprintf (_db_fp_, "%s: ", func);
+ }
+ (VOID) fprintf (_db_fp_, "%s: ", u_keyword);
+ (VOID) fprintf (_db_fp_, format, ARGLIST);
+ (VOID) fprintf (_db_fp_, "\n");
+ (VOID) fflush (_db_fp_);
+ (VOID) XDelay (stack -> delay);
+ }
+}
+
+/*
+ * The following routine is kept around temporarily for compatibility
+ * with older objects that were compiled with the DBUG_N macro form
+ * of the print routine. It will print a warning message on first
+ * usage. It will go away in subsequent releases...
+ */
+
+/*VARARGS3*/
+VOID _db_printf_ (_line_, keyword, format, ARGLIST)
+int _line_;
+char *keyword, *format;
+long ARGLIST;
+{
+ static BOOLEAN firsttime = TRUE;
+
+ if (firsttime) {
+ (VOID) fprintf (stderr, ERR_PRINTF, _db_process_, file);
+ firsttime = FALSE;
+ }
+ _db_pargs_ (_line_, keyword);
+ _db_doprnt_ (format, ARGLIST);
+}
+
+
+/*
+ * FUNCTION
+ *
+ * ListParse parse list of modifiers in debug control string
+ *
+ * SYNOPSIS
+ *
+ * LOCAL struct link *ListParse (ctlp)
+ * char *ctlp;
+ *
+ * DESCRIPTION
+ *
+ * Given pointer to a comma separated list of strings in "cltp",
+ * parses the list, building a list and returning a pointer to it.
+ * The original comma separated list is destroyed in the process of
+ * building the linked list, thus it had better be a duplicate
+ * if it is important.
+ *
+ * Note that since each link is added at the head of the list,
+ * the final list will be in "reverse order", which is not
+ * significant for our usage here.
+ *
+ */
+
+LOCAL struct link *ListParse (ctlp)
+char *ctlp;
+{
+ REGISTER char *start;
+ REGISTER struct link *new;
+ REGISTER struct link *head;
+
+ head = NULL;
+ while (*ctlp != EOS) {
+ start = ctlp;
+ while (*ctlp != EOS && *ctlp != ',') {
+ ctlp++;
+ }
+ if (*ctlp == ',') {
+ *ctlp++ = EOS;
+ }
+ new = (struct link *) DbugMalloc (sizeof (struct link));
+ new -> string = StrDup (start);
+ new -> next_link = head;
+ head = new;
+ }
+ return (head);
+}
+
+
+/*
+ * FUNCTION
+ *
+ * InList test a given string for member of a given list
+ *
+ * SYNOPSIS
+ *
+ * LOCAL BOOLEAN InList (linkp, cp)
+ * struct link *linkp;
+ * char *cp;
+ *
+ * DESCRIPTION
+ *
+ * Tests the string pointed to by "cp" to determine if it is in
+ * the list pointed to by "linkp". Linkp points to the first
+ * link in the list. If linkp is NULL then the string is treated
+ * as if it is in the list (I.E all strings are in the null list).
+ * This may seem rather strange at first but leads to the desired
+ * operation if no list is given. The net effect is that all
+ * strings will be accepted when there is no list, and when there
+ * is a list, only those strings in the list will be accepted.
+ *
+ */
+
+LOCAL BOOLEAN InList (linkp, cp)
+struct link *linkp;
+char *cp;
+{
+ REGISTER struct link *scan;
+ REGISTER BOOLEAN accept;
+
+ if (linkp == NULL) {
+ accept = TRUE;
+ } else {
+ accept = FALSE;
+ for (scan = linkp; scan != NULL; scan = scan -> next_link) {
+ if (STREQ (scan -> string, cp)) {
+ accept = TRUE;
+ break;
+ }
+ }
+ }
+ return (accept);
+}
+
+
+/*
+ * FUNCTION
+ *
+ * PushState push current state onto stack and set up new one
+ *
+ * SYNOPSIS
+ *
+ * LOCAL VOID PushState ()
+ *
+ * DESCRIPTION
+ *
+ * Pushes the current state on the state stack, and initializes
+ * a new state. The only parameter inherited from the previous
+ * state is the function nesting level. This action can be
+ * inhibited if desired, via the "r" flag.
+ *
+ * The state stack is a linked list of states, with the new
+ * state added at the head. This allows the stack to grow
+ * to the limits of memory if necessary.
+ *
+ */
+
+LOCAL VOID PushState ()
+{
+ REGISTER struct state *new;
+
+ new = (struct state *) DbugMalloc (sizeof (struct state));
+ new -> flags = 0;
+ new -> delay = 0;
+ new -> maxdepth = MAXDEPTH;
+ if (stack != NULL) {
+ new -> level = stack -> level;
+ } else {
+ new -> level = 0;
+ }
+ new -> out_file = stderr;
+ new -> functions = NULL;
+ new -> p_functions = NULL;
+ new -> keywords = NULL;
+ new -> processes = NULL;
+ new -> next_state = stack;
+ stack = new;
+ init_done = TRUE;
+}
+
+
+/*
+ * FUNCTION
+ *
+ * DoTrace check to see if tracing is current enabled
+ *
+ * SYNOPSIS
+ *
+ * LOCAL BOOLEAN DoTrace ()
+ *
+ * DESCRIPTION
+ *
+ * Checks to see if tracing is enabled based on whether the
+ * user has specified tracing, the maximum trace depth has
+ * not yet been reached, the current function is selected,
+ * and the current process is selected. Returns TRUE if
+ * tracing is enabled, FALSE otherwise.
+ *
+ */
+
+LOCAL BOOLEAN DoTrace ()
+{
+ REGISTER BOOLEAN trace;
+
+ trace = FALSE;
+ if (TRACING) {
+ if (stack -> level <= stack -> maxdepth) {
+ if (InList (stack -> functions, func)) {
+ if (InList (stack -> processes, _db_process_)) {
+ trace = TRUE;
+ }
+ }
+ }
+ }
+ return (trace);
+}
+
+
+/*
+ * FUNCTION
+ *
+ * DoProfile check to see if profiling is current enabled
+ *
+ * SYNOPSIS
+ *
+ * LOCAL BOOLEAN DoProfile ()
+ *
+ * DESCRIPTION
+ *
+ * Checks to see if profiling is enabled based on whether the
+ * user has specified profiling, the maximum trace depth has
+ * not yet been reached, the current function is selected,
+ * and the current process is selected. Returns TRUE if
+ * profiling is enabled, FALSE otherwise.
+ *
+ */
+
+LOCAL BOOLEAN DoProfile ()
+{
+ REGISTER BOOLEAN profile;
+
+ profile = FALSE;
+ if (PROFILING) {
+ if (stack -> level <= stack -> maxdepth) {
+ if (InList (stack -> p_functions, func)) {
+ if (InList (stack -> processes, _db_process_)) {
+ profile = TRUE;
+ }
+ }
+ }
+ }
+ return (profile);
+}
+
+
+/*
+ * FUNCTION
+ *
+ * _db_keyword_ test keyword for member of keyword list
+ *
+ * SYNOPSIS
+ *
+ * BOOLEAN _db_keyword_ (keyword)
+ * char *keyword;
+ *
+ * DESCRIPTION
+ *
+ * Test a keyword to determine if it is in the currently active
+ * keyword list. As with the function list, a keyword is accepted
+ * if the list is null, otherwise it must match one of the list
+ * members. When debugging is not on, no keywords are accepted.
+ * After the maximum trace level is exceeded, no keywords are
+ * accepted (this behavior subject to change). Additionally,
+ * the current function and process must be accepted based on
+ * their respective lists.
+ *
+ * Returns TRUE if keyword accepted, FALSE otherwise.
+ *
+ */
+
+BOOLEAN _db_keyword_ (keyword)
+char *keyword;
+{
+ REGISTER BOOLEAN accept;
+
+ if (!init_done) {
+ _db_push_ ("");
+ }
+ accept = FALSE;
+ if (DEBUGGING) {
+ if (stack -> level <= stack -> maxdepth) {
+ if (InList (stack -> functions, func)) {
+ if (InList (stack -> keywords, keyword)) {
+ if (InList (stack -> processes, _db_process_)) {
+ accept = TRUE;
+ }
+ }
+ }
+ }
+ }
+ return (accept);
+}
+
+
+/*
+ * FUNCTION
+ *
+ * Indent indent a line to the given indentation level
+ *
+ * SYNOPSIS
+ *
+ * LOCAL VOID Indent (indent)
+ * int indent;
+ *
+ * DESCRIPTION
+ *
+ * Indent a line to the given level. Note that this is
+ * a simple minded but portable implementation.
+ * There are better ways.
+ *
+ * Also, the indent must be scaled by the compile time option
+ * of character positions per nesting level.
+ *
+ */
+
+LOCAL VOID Indent (indent)
+int indent;
+{
+ REGISTER int count;
+ AUTO char buffer[PRINTBUF];
+
+ indent *= INDENT;
+ for (count = 0; (count < (indent - INDENT)) && (count < (PRINTBUF - 1)); count++) {
+ if ((count % INDENT) == 0) {
+ buffer[count] = '|';
+ } else {
+ buffer[count] = ' ';
+ }
+ }
+ buffer[count] = EOS;
+ (VOID) fprintf (_db_fp_, buffer);
+ (VOID) fflush (_db_fp_);
+}
+
+
+/*
+ * FUNCTION
+ *
+ * FreeList free all memory associated with a linked list
+ *
+ * SYNOPSIS
+ *
+ * LOCAL VOID FreeList (linkp)
+ * struct link *linkp;
+ *
+ * DESCRIPTION
+ *
+ * Given pointer to the head of a linked list, frees all
+ * memory held by the list and the members of the list.
+ *
+ */
+
+LOCAL VOID FreeList (linkp)
+struct link *linkp;
+{
+ REGISTER struct link *old;
+
+ while (linkp != NULL) {
+ old = linkp;
+ linkp = linkp -> next_link;
+ if (old -> string != NULL) {
+ free (old -> string);
+ }
+ free ((char *) old);
+ }
+}
+
+
+/*
+ * FUNCTION
+ *
+ * StrDup make a duplicate of a string in new memory
+ *
+ * SYNOPSIS
+ *
+ * LOCAL char *StrDup (string)
+ * char *string;
+ *
+ * DESCRIPTION
+ *
+ * Given pointer to a string, allocates sufficient memory to make
+ * a duplicate copy, and copies the string to the newly allocated
+ * memory. Failure to allocated sufficient memory is immediately
+ * fatal.
+ *
+ */
+
+
+LOCAL char *StrDup (string)
+char *string;
+{
+ REGISTER char *new;
+
+ new = DbugMalloc (strlen (string) + 1);
+ (VOID) strcpy (new, string);
+ return (new);
+}
+
+
+/*
+ * FUNCTION
+ *
+ * DoPrefix print debugger line prefix prior to indentation
+ *
+ * SYNOPSIS
+ *
+ * LOCAL VOID DoPrefix (_line_)
+ * int _line_;
+ *
+ * DESCRIPTION
+ *
+ * Print prefix common to all debugger output lines, prior to
+ * doing indentation if necessary. Print such information as
+ * current process name, current source file name and line number,
+ * and current function nesting depth.
+ *
+ */
+
+
+LOCAL VOID DoPrefix (_line_)
+int _line_;
+{
+ lineno++;
+ if (stack -> flags & NUMBER_ON) {
+ (VOID) fprintf (_db_fp_, "%5d: ", lineno);
+ }
+ if (stack -> flags & PROCESS_ON) {
+ (VOID) fprintf (_db_fp_, "%s: ", _db_process_);
+ }
+ if (stack -> flags & FILE_ON) {
+ (VOID) fprintf (_db_fp_, "%14s: ", file);
+ }
+ if (stack -> flags & LINE_ON) {
+ (VOID) fprintf (_db_fp_, "%5d: ", _line_);
+ }
+ if (stack -> flags & DEPTH_ON) {
+ (VOID) fprintf (_db_fp_, "%4d: ", stack -> level);
+ }
+ (VOID) fflush (_db_fp_);
+}
+
+
+/*
+ * FUNCTION
+ *
+ * OpenFile open new output stream for debugger output
+ *
+ * SYNOPSIS
+ *
+ * LOCAL VOID OpenFile (name)
+ * char *name;
+ *
+ * DESCRIPTION
+ *
+ * Given name of a new file (or "-" for stdout) opens the file
+ * and sets the output stream to the new file.
+ *
+ */
+
+LOCAL VOID OpenFile (name)
+char *name;
+{
+ REGISTER FILE *fp;
+ REGISTER BOOLEAN newfile;
+
+ if (name != NULL) {
+ if (strcmp (name, "-") == 0) {
+ _db_fp_ = stdout;
+ stack -> out_file = _db_fp_;
+ } else {
+ if (!Writable (name)) {
+ (VOID) fprintf (_db_fp_, ERR_OPEN, _db_process_, name);
+ perror ("");
+ (VOID) fflush (_db_fp_);
+ (VOID) XDelay (stack -> delay);
+ } else {
+ if (EXISTS (name)) {
+ newfile = FALSE;
+ } else {
+ newfile = TRUE;
+ }
+ fp = fopen (name, "a");
+ if (fp == NULL) {
+ (VOID) fprintf (_db_fp_, ERR_OPEN, _db_process_, name);
+ perror ("");
+ (VOID) fflush (_db_fp_);
+ (VOID) XDelay (stack -> delay);
+ } else {
+ _db_fp_ = fp;
+ stack -> out_file = fp;
+ if (newfile) {
+ ChangeOwner (name);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/*
+ * FUNCTION
+ *
+ * OpenProfile open new output stream for profiler output
+ *
+ * SYNOPSIS
+ *
+ * LOCAL VOID OpenProfile (name)
+ * char *name;
+ *
+ * DESCRIPTION
+ *
+ * Given name of a new file, opens the file
+ * and sets the profiler output stream to the new file.
+ *
+ * It is currently unclear whether the prefered behavior is
+ * to truncate any existing file, or simply append to it.
+ * The latter behavior would be desirable for collecting
+ * accumulated runtime history over a number of separate
+ * runs. It might take some changes to the analyzer program
+ * though, and the notes that Binayak sent with the profiling
+ * diffs indicated that append was the normal mode, but this
+ * does not appear to agree with the actual code. I haven't
+ * investigated at this time [fnf; 24-Jul-87].
+ */
+
+LOCAL VOID OpenProfile (name)
+char *name;
+{
+ REGISTER FILE *fp;
+ REGISTER BOOLEAN newfile;
+
+ if (name != NULL) {
+ if (!Writable (name)) {
+ (VOID) fprintf (_db_fp_, ERR_OPEN, _db_process_, name);
+ perror ("");
+ (VOID) fflush (_db_fp_);
+ (VOID) XDelay (stack -> delay);
+ } else {
+ if (EXISTS (name)) {
+ newfile = FALSE;
+ } else {
+ newfile = TRUE;
+ }
+ fp = fopen (name, "w");
+ if (fp == NULL) {
+ (VOID) fprintf (_db_fp_, ERR_OPEN, _db_process_, name);
+ perror ("");
+ (VOID) fflush (_db_fp_);
+ (VOID) XDelay (stack -> delay);
+ } else {
+ _db_pfp_ = fp;
+ stack -> prof_file = fp;
+ if (newfile) {
+ ChangeOwner (name);
+ }
+ }
+ }
+ }
+}
+
+
+/*
+ * FUNCTION
+ *
+ * CloseFile close the debug output stream
+ *
+ * SYNOPSIS
+ *
+ * LOCAL VOID CloseFile (fp)
+ * FILE *fp;
+ *
+ * DESCRIPTION
+ *
+ * Closes the debug output stream unless it is standard output
+ * or standard error.
+ *
+ */
+
+LOCAL VOID CloseFile (fp)
+FILE *fp;
+{
+ if (fp != stderr && fp != stdout) {
+ if (fclose (fp) == EOF) {
+ (VOID) fprintf (stderr, ERR_CLOSE, _db_process_);
+ perror ("");
+ (VOID) fflush (stderr);
+ (VOID) XDelay (stack -> delay);
+ }
+ }
+}
+
+
+/*
+ * FUNCTION
+ *
+ * DbugExit print error message and exit
+ *
+ * SYNOPSIS
+ *
+ * LOCAL VOID DbugExit (why)
+ * char *why;
+ *
+ * DESCRIPTION
+ *
+ * Prints error message using current process name, the reason for
+ * aborting (typically out of memory), and exits with status 1.
+ * This should probably be changed to use a status code
+ * defined in the user's debugger include file.
+ *
+ */
+
+LOCAL VOID DbugExit (why)
+char *why;
+{
+ (VOID) fprintf (stderr, ERR_ABORT, _db_process_, why);
+ (VOID) fflush (stderr);
+ (VOID) XDelay (stack -> delay);
+ exit (1);
+}
+
+
+/*
+ * FUNCTION
+ *
+ * DbugMalloc allocate memory for debugger runtime support
+ *
+ * SYNOPSIS
+ *
+ * LOCAL char *DbugMalloc (size)
+ * int size;
+ *
+ * DESCRIPTION
+ *
+ * Allocate more memory for debugger runtime support functions.
+ * Failure to to allocate the requested number of bytes is
+ * immediately fatal to the current process. This may be
+ * rather unfriendly behavior. It might be better to simply
+ * print a warning message, freeze the current debugger state,
+ * and continue execution.
+ *
+ */
+
+LOCAL char *DbugMalloc (size)
+int size;
+{
+ register char *new;
+
+ new = malloc ( size );
+ if (new == NULL) {
+ DbugExit ("out of memory");
+ }
+ return (new);
+}
+
+
+/*
+ * This function may be eliminated when strtok is available
+ * in the runtime environment (missing from BSD4.1).
+ */
+
+LOCAL char *strtok (s1, s2)
+char *s1, *s2;
+{
+ static char *end = NULL;
+ REGISTER char *rtnval;
+
+ rtnval = NULL;
+ if (s2 != NULL) {
+ if (s1 != NULL) {
+ end = s1;
+ rtnval = strtok ((char *) NULL, s2);
+ } else if (end != NULL) {
+ if (*end != EOS) {
+ rtnval = end;
+ while (*end != *s2 && *end != EOS) {end++;}
+ if (*end != EOS) {
+ *end++ = EOS;
+ }
+ }
+ }
+ }
+ return (rtnval);
+}
+
+
+/*
+ * FUNCTION
+ *
+ * BaseName strip leading pathname components from name
+ *
+ * SYNOPSIS
+ *
+ * LOCAL char *BaseName (pathname)
+ * char *pathname;
+ *
+ * DESCRIPTION
+ *
+ * Given pointer to a complete pathname, locates the base file
+ * name at the end of the pathname and returns a pointer to
+ * it.
+ *
+ */
+
+LOCAL char *BaseName (pathname)
+char *pathname;
+{
+ register char *base;
+
+ base = strrchr (pathname, '/');
+ if (base++ == NULL) {
+ base = pathname;
+ }
+ return (base);
+}
+
+
+/*
+ * FUNCTION
+ *
+ * Writable test to see if a pathname is writable/creatable
+ *
+ * SYNOPSIS
+ *
+ * LOCAL BOOLEAN Writable (pathname)
+ * char *pathname;
+ *
+ * DESCRIPTION
+ *
+ * Because the debugger might be linked in with a program that
+ * runs with the set-uid-bit (suid) set, we have to be careful
+ * about opening a user named file for debug output. This consists
+ * of checking the file for write access with the real user id,
+ * or checking the directory where the file will be created.
+ *
+ * Returns TRUE if the user would normally be allowed write or
+ * create access to the named file. Returns FALSE otherwise.
+ *
+ */
+
+LOCAL BOOLEAN Writable (pathname)
+char *pathname;
+{
+ REGISTER BOOLEAN granted;
+#ifdef unix
+ REGISTER char *lastslash;
+#endif
+
+#ifndef unix
+ granted = TRUE;
+#else
+ granted = FALSE;
+ if (EXISTS (pathname)) {
+ if (WRITABLE (pathname)) {
+ granted = TRUE;
+ }
+ } else {
+ lastslash = strrchr (pathname, '/');
+ if (lastslash != NULL) {
+ *lastslash = EOS;
+ } else {
+ pathname = ".";
+ }
+ if (WRITABLE (pathname)) {
+ granted = TRUE;
+ }
+ if (lastslash != NULL) {
+ *lastslash = '/';
+ }
+ }
+#endif
+ return (granted);
+}
+
+
+/*
+ * This function may be eliminated when strrchr is available
+ * in the runtime environment (missing from BSD4.1).
+ * Alternately, you can use rindex() on BSD systems.
+ */
+
+LOCAL char *strrchr (s, c)
+char *s;
+char c;
+{
+ REGISTER char *scan;
+
+ for (scan = s; *scan != EOS; scan++) {;}
+ while (scan > s && *--scan != c) {;}
+ if (*scan != c) {
+ scan = NULL;
+ }
+ return (scan);
+}
+
+
+/*
+ * FUNCTION
+ *
+ * ChangeOwner change owner to real user for suid programs
+ *
+ * SYNOPSIS
+ *
+ * LOCAL VOID ChangeOwner (pathname)
+ *
+ * DESCRIPTION
+ *
+ * For unix systems, change the owner of the newly created debug
+ * file to the real owner. This is strictly for the benefit of
+ * programs that are running with the set-user-id bit set.
+ *
+ * Note that at this point, the fact that pathname represents
+ * a newly created file has already been established. If the
+ * program that the debugger is linked to is not running with
+ * the suid bit set, then this operation is redundant (but
+ * harmless).
+ *
+ */
+
+LOCAL VOID ChangeOwner (pathname)
+char *pathname;
+{
+#ifdef unix
+ if (chown (pathname, getuid (), getgid ()) == -1) {
+ (VOID) fprintf (stderr, ERR_CHOWN, _db_process_, pathname);
+ perror ("");
+ (VOID) fflush (stderr);
+ (VOID) XDelay (stack -> delay);
+ }
+#endif
+}
+
+
+/*
+ * FUNCTION
+ *
+ * _db_setjmp_ save debugger environment
+ *
+ * SYNOPSIS
+ *
+ * VOID _db_setjmp_ ()
+ *
+ * DESCRIPTION
+ *
+ * Invoked as part of the user's DBUG_SETJMP macro to save
+ * the debugger environment in parallel with saving the user's
+ * environment.
+ *
+ */
+
+VOID _db_setjmp_ ()
+{
+ jmplevel = stack -> level;
+ jmpfunc = func;
+ jmpfile = file;
+}
+
+
+/*
+ * FUNCTION
+ *
+ * _db_longjmp_ restore previously saved debugger environment
+ *
+ * SYNOPSIS
+ *
+ * VOID _db_longjmp_ ()
+ *
+ * DESCRIPTION
+ *
+ * Invoked as part of the user's DBUG_LONGJMP macro to restore
+ * the debugger environment in parallel with restoring the user's
+ * previously saved environment.
+ *
+ */
+
+VOID _db_longjmp_ ()
+{
+ stack -> level = jmplevel;
+ if (jmpfunc) {
+ func = jmpfunc;
+ }
+ if (jmpfile) {
+ file = jmpfile;
+ }
+}
+
+
+/*
+ * FUNCTION
+ *
+ * DelayArg convert D flag argument to appropriate value
+ *
+ * SYNOPSIS
+ *
+ * LOCAL int DelayArg (value)
+ * int value;
+ *
+ * DESCRIPTION
+ *
+ * Converts delay argument, given in tenths of a second, to the
+ * appropriate numerical argument used by the system to delay
+ * that that many tenths of a second. For example, on the
+ * AMIGA, there is a system call "Delay()" which takes an
+ * argument in ticks (50 per second). On unix, the sleep
+ * command takes seconds. Thus a value of "10", for one
+ * second of delay, gets converted to 50 on the amiga, and 1
+ * on unix. Other systems will need to use a timing loop.
+ *
+ */
+
+LOCAL int DelayArg (value)
+int value;
+{
+ int delayarg = 0;
+
+#ifdef unix
+ delayarg = value / 10; /* Delay is in seconds for sleep () */
+#endif
+#ifdef AMIGA
+ delayarg = (HZ * value) / 10; /* Delay in ticks for XDelay () */
+#endif
+ return (delayarg);
+}
+
+
+/*
+ * A dummy delay stub for systems that do not support delays.
+ * With a little work, this can be turned into a timing loop.
+ */
+
+#ifndef unix
+#ifndef AMIGA
+XDelay ()
+{
+}
+#endif
+#endif
+
+
+/*
+ * FUNCTION
+ *
+ * perror perror simulation for systems that don't have it
+ *
+ * SYNOPSIS
+ *
+ * LOCAL VOID perror (s)
+ * char *s;
+ *
+ * DESCRIPTION
+ *
+ * Perror produces a message on the standard error stream which
+ * provides more information about the library or system error
+ * just encountered. The argument string s is printed, followed
+ * by a ':', a blank, and then a message and a newline.
+ *
+ * An undocumented feature of the unix perror is that if the string
+ * 's' is a null string (NOT a NULL pointer!), then the ':' and
+ * blank are not printed.
+ *
+ * This version just complains about an "unknown system error".
+ *
+ */
+
+#if !unix && !(AMIGA || LATTICE || __TURBOC__ )
+LOCAL VOID perror (s)
+#if __STDC__
+const char *s;
+#else
+char *s;
+#endif
+{
+ if (s && *s != EOS) {
+ (VOID) fprintf (stderr, "%s: ", s);
+ }
+ (VOID) fprintf (stderr, "<unknown system error>\n");
+}
+#endif /* !unix && !(AMIGA && LATTICE) */
+
+/*
+ * Here we need the definitions of the clock routine. Add your
+ * own for whatever system that you have.
+ */
+
+#if unix
+
+# include <sys/param.h>
+# if !defined(Solaris) && (BSD4_3 || sun)
+
+/*
+ * Definition of the Clock() routine for 4.3 BSD.
+ */
+
+#include <sys/time.h>
+#include <sys/resource.h>
+
+
+/*
+ * Returns the user time in milliseconds used by this process so
+ * far.
+ */
+
+LOCAL unsigned long Clock ()
+{
+ struct rusage ru;
+
+ (VOID) getrusage (RUSAGE_SELF, &ru);
+ return ((ru.ru_utime.tv_sec * 1000) + (ru.ru_utime.tv_usec / 1000));
+}
+
+#else
+
+LOCAL unsigned long Clock ()
+{
+ return (0);
+}
+
+# endif
+
+#else
+
+#if AMIGA
+
+struct DateStamp { /* Yes, this is a hack, but doing it right */
+ long ds_Days; /* is incredibly ugly without splitting this */
+ long ds_Minute; /* off into a separate file */
+ long ds_Tick;
+};
+
+static int first_clock = TRUE;
+static struct DateStamp begin;
+static struct DateStamp elapsed;
+
+LOCAL unsigned long Clock ()
+{
+ register struct DateStamp *now;
+ register unsigned long millisec = 0;
+ extern VOID *AllocMem ();
+
+ now = (struct DateStamp *) AllocMem ((long) sizeof (struct DateStamp), 0L);
+ if (now != NULL) {
+ if (first_clock == TRUE) {
+ first_clock = FALSE;
+ (VOID) DateStamp (now);
+ begin = *now;
+ }
+ (VOID) DateStamp (now);
+ millisec = 24 * 3600 * (1000 / HZ) * (now -> ds_Days - begin.ds_Days);
+ millisec += 60 * (1000 / HZ) * (now -> ds_Minute - begin.ds_Minute);
+ millisec += (1000 / HZ) * (now -> ds_Tick - begin.ds_Tick);
+ (VOID) FreeMem (now, (long) sizeof (struct DateStamp));
+ }
+ return (millisec);
+}
+
+#else
+
+LOCAL unsigned long Clock ()
+{
+ return (0);
+}
+
+#endif /* AMIGA */
+
+#endif /* unix */
+
+#ifdef AMIGA
+XDelay(x)
+int x;
+{
+ if (x) Delay(x); /* fix Delay bug in AmigaDOS */
+}
+#endif
+
diff --git a/dmake/dbug/dbug/dbug.h b/dmake/dbug/dbug/dbug.h
new file mode 100644
index 000000000000..0f171e0d349f
--- /dev/null
+++ b/dmake/dbug/dbug/dbug.h
@@ -0,0 +1,164 @@
+/******************************************************************************
+ * *
+ * N O T I C E *
+ * *
+ * Copyright Abandoned, 1987, Fred Fish *
+ * *
+ * *
+ * This previously copyrighted work has been placed into the public *
+ * domain by the author and may be freely used for any purpose, *
+ * private or commercial. *
+ * *
+ * Because of the number of inquiries I was receiving about the use *
+ * of this product in commercially developed works I have decided to *
+ * simply make it public domain to further its unrestricted use. I *
+ * specifically would be most happy to see this material become a *
+ * part of the standard Unix distributions by AT&T and the Berkeley *
+ * Computer Science Research Group, and a standard part of the GNU *
+ * system from the Free Software Foundation. *
+ * *
+ * I would appreciate it, as a courtesy, if this notice is left in *
+ * all copies and derivative works. Thank you. *
+ * *
+ * The author makes no warranty of any kind with respect to this *
+ * product and explicitly disclaims any implied warranties of mer- *
+ * chantability or fitness for any particular purpose. *
+ * *
+ ******************************************************************************
+ */
+
+
+/*
+ * FILE
+ *
+ * dbug.h user include file for programs using the dbug package
+ *
+ * SYNOPSIS
+ *
+ * #include <local/dbug.h>
+ *
+ * SCCS ID
+ *
+ * @(#)dbug.h 1.11 9/5/87
+ *
+ * DESCRIPTION
+ *
+ * Programs which use the dbug package must include this file.
+ * It contains the appropriate macros to call support routines
+ * in the dbug runtime library.
+ *
+ * To disable compilation of the macro expansions define the
+ * preprocessor symbol "DBUG_OFF". This will result in null
+ * macros expansions so that the resulting code will be smaller
+ * and faster. (The difference may be smaller than you think
+ * so this step is recommended only when absolutely necessary).
+ * In general, tradeoffs between space and efficiency are
+ * decided in favor of efficiency since space is seldom a
+ * problem on the new machines).
+ *
+ * All externally visible symbol names follow the pattern
+ * "_db_xxx..xx_" to minimize the possibility of a dbug package
+ * symbol colliding with a user defined symbol.
+ *
+ * The DBUG_<N> style macros are obsolete and should not be used
+ * in new code. Macros to map them to instances of DBUG_PRINT
+ * are provided for compatibility with older code. They may go
+ * away completely in subsequent releases.
+ *
+ * AUTHOR
+ *
+ * Fred Fish
+ * (Currently employed by Motorola Computer Division, Tempe, Az.)
+ * hao!noao!mcdsun!fnf
+ * (602) 438-3614
+ *
+ */
+
+
+/*
+ * Internally used dbug variables which must be global.
+ */
+
+#ifndef DBUG_OFF
+ extern int _db_on_; /* TRUE if debug currently enabled */
+ extern FILE *_db_fp_; /* Current debug output stream */
+ extern char *_db_process_; /* Name of current process */
+ extern int _db_keyword_ (); /* Accept/reject keyword */
+ extern void _db_push_ (); /* Push state, set up new state */
+ extern void _db_pop_ (); /* Pop previous debug state */
+ extern void _db_enter_ (); /* New user function entered */
+ extern void _db_return_ (); /* User function return */
+ extern void _db_pargs_ (); /* Remember args for line */
+ extern void _db_doprnt_ (); /* Print debug output */
+ extern void _db_setjmp_ (); /* Save debugger environment */
+ extern void _db_longjmp_ (); /* Restore debugger environment */
+# endif
+
+
+/*
+ * These macros provide a user interface into functions in the
+ * dbug runtime support library. They isolate users from changes
+ * in the MACROS and/or runtime support.
+ *
+ * The symbols "__LINE__" and "__FILE__" are expanded by the
+ * preprocessor to the current source file line number and file
+ * name respectively.
+ *
+ * WARNING --- Because the DBUG_ENTER macro allocates space on
+ * the user function's stack, it must precede any executable
+ * statements in the user function.
+ *
+ */
+
+# ifdef DBUG_OFF
+# define DBUG_ENTER(a1)
+# define DBUG_MALLOC(a1)
+# define DBUG_RETURN(a1) return(a1)
+# define DBUG_VOID_RETURN return
+# define DBUG_EXECUTE(keyword,a1)
+# define DBUG_PRINT(keyword,arglist)
+# define DBUG_2(keyword,format) /* Obsolete */
+# define DBUG_3(keyword,format,a1) /* Obsolete */
+# define DBUG_4(keyword,format,a1,a2) /* Obsolete */
+# define DBUG_5(keyword,format,a1,a2,a3) /* Obsolete */
+# define DBUG_PUSH(a1)
+# define DBUG_POP()
+# define DBUG_PROCESS(a1)
+# define DBUG_FILE (stderr)
+# define DBUG_SETJMP setjmp
+# define DBUG_LONGJMP longjmp
+# else
+# define DBUG_ENTER(a) \
+ auto char *_db_func_, *_db_file_; \
+ int _db_level_; \
+ _db_enter_ (a,__FILE__,__LINE__,&_db_func_,&_db_file_,&_db_level_)
+# define DBUG_MALLOC(a) \
+ auto char *_db_func_, *_db_file_; \
+ int _db_level_; \
+ malloc_init();\
+ _db_enter_ (a,__FILE__,__LINE__,&_db_func_,&_db_file_,&_db_level_)
+# define DBUG_LEAVE \
+ (_db_return_ (__LINE__, &_db_func_, &_db_file_, &_db_level_))
+# define DBUG_RETURN(a1) return (DBUG_LEAVE, (a1))
+/* define DBUG_RETURN(a1) {DBUG_LEAVE; return(a1);} Alternate form */
+# define DBUG_VOID_RETURN DBUG_LEAVE; return
+# define DBUG_EXECUTE(keyword,a1) \
+ {if (_db_on_) {if (_db_keyword_ (keyword)) { a1 }}}
+# define DBUG_PRINT(keyword,arglist) \
+ {if (_db_on_) {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;}}
+# define DBUG_2(keyword,format) \
+ DBUG_PRINT(keyword,(format)) /* Obsolete */
+# define DBUG_3(keyword,format,a1) \
+ DBUG_PRINT(keyword,(format,a1)) /* Obsolete */
+# define DBUG_4(keyword,format,a1,a2) \
+ DBUG_PRINT(keyword,(format,a1,a2)) /* Obsolete */
+# define DBUG_5(keyword,format,a1,a2,a3) \
+ DBUG_PRINT(keyword,(format,a1,a2,a3)) /* Obsolete */
+# define DBUG_PUSH(a1) _db_push_ (a1)
+# define DBUG_POP() _db_pop_ ()
+# define DBUG_PROCESS(a1) (_db_process_ = a1)
+# define DBUG_FILE (_db_fp_)
+# define DBUG_SETJMP(a1) (_db_setjmp_ (), setjmp (a1))
+# define DBUG_LONGJMP(a1,a2) (_db_longjmp_ (), longjmp (a1, a2))
+# endif
+
diff --git a/dmake/dbug/dbug/dbug.uue b/dmake/dbug/dbug/dbug.uue
new file mode 100644
index 000000000000..da8743b7e128
--- /dev/null
+++ b/dmake/dbug/dbug/dbug.uue
@@ -0,0 +1,368 @@
+begin 650 dbug.Z
+M'YV,"@*"&$BPH,&#" T2 2$$1!401P0FG&AP" @H<MZ<D1.F#0@B9<34.7,F
+MC9LS%\.,61/F3!F)%&/*!"$F#\R9. <:D5.&# @C:>:@"4@481($1Y,Z0;"T
+M*14$3Z-*03"UZA,$5[,20;"U:Q4$7\,.03"V;%2H4),B19H5*]:F3)D6C1F$
+M39LW<^B *&.GC)P\(.!DW-@1!!F^9=B\@=.FC!N]CNVDR>BF\6,0=][(H8,&
+M,(@W9A0@Y%QFH)N.I06_D7QX#H@Y;QJ_UJP7M.&0(TN>!&%&91HV:>CD<3&P
+MRIPZ8=BPL3D:35 0=,*L*>.:]$ SFCU^-C,PS$#5A+7?<3X&S<#G(,:$@1-&
+M#)O2VT4?'//F<4;E)E'NQ5-F3!TZ:=0WD&V?D29'8(-QU(9K8;CA4QEX=&12
+M?M"A\1)")M'AUVELO!:=AML5:.&!$/;W'X7@*3@'<2!08>$<I0D'!W4#AH90
+MBAVY=L=O'8I1&D]F^,633W2\ 4(8KD&HH1P<WB8227ZY-H=)8\1HH7P&'?:D
+M2P<^Y\8;>K&W68C6E>@?@+OAV :+1438!ASON19?<^C)"!^!6N;FUWENC,%&
+M'8<-9%T8"!!J*!D((*JH& @PZNB1#KZ&P!R33JIHHHDZVFBC3NHIQQQ8%J0:
+M:SUA%IQYUH4%%EAP-:564E@@$.NL&^ 0 P*WYKI!#I_-R!&:*,V11UYEK#D7
+M14^X49IMUJGF7K$,S@';&&F$H:%/.W)V6U^*P8%B@CF&2I!)W;DQ4&23U6>9
+M7J9J"\(9;[SATWY+-MDIE)^"\!QGUHH[T&'<+E:JFG)J&"ET1H* 1AA]#00<
+M'72\-^"!('S)9[W)^:NO&WG)4<>ZU@;H!HLM.B<G>G4<E]QRIH'9'8)O/.L1
+M=@>2IC' B0E\X)1]EF:AOG.P\-F!UCI<!I+L"O5&'6S,ZZ/0&P/8AK6),7=0
+M;VW\5BW%V9I7(7P9;IC<T&<TF(8>(=<G-!G6>M=Q'6/040=/06O<H$_TV?=&
+MAV8H=@>9/ZM)4QD4WNL2&20GP2YZ86@,HQP!IDR0L^]IQYMF TT=]FD]?P=N
+M&XU]"O5X"8?!D\9UN '<="P7J3##I1U7'F\2 F=Z<)YU+>C/,(<WD(_Y::SY
+M8V&8U!/4=Y&1AAEI'#]T8+25ZGJ#8(ZXEQN24;8NBXIK_%QRL!T)L\Q"(V8N
+MS5]OF[.O0H_G6/J]*^B]G'?U-:_KD%Z?O;J.Z:6[=X))0]8 U##,I0YK6C/=
+MS7"#+Z%ASGP5,U*>\.6"8TTD6>FKWIX6YB"A?2%1'Q3#!^OP091\SUP0Z@B<
+M[L2=_$5-;&Q8X);\PB(A]"<,*2M-<$# DSC483(T"AN3QF:2MX$,0 *R3>-N
+M]#FAW4U?=)!3REH"'S*\@4819-=A9G0P 4'*,W.8$;4RAA#UL$<,6@,0%@ED
+MG?V8"(GFTE^Z*M,_J.WP>VRX0QB&93<[%(\-[9'8$W>DG'/QYTQ@BV.#/(,N
+M[?5O=T7[FL8$!T48L8$[A.R0F?ZCPY$-) GF"@,9E ='H?&L2E $VI$T1I\W
+MO0=$@5$)2UPR$-V)[S5B7%X:QC"0'%),B+VI$M2.I)Q)?DY.F"&/UW)X'G9E
+M\G?P&54:#C,O6TXI:X"4@PQS0R$SMB>-S5O10%STG'*:2RBF@T-ZZD,'CN0%
+M80,RD 4)\H5ZVO.>-RE(#(A3!2<D 0NJ]$X[15DLTZTA1$&@@@FHP)#$=(@)
+M[=&,M303S@H216,YD4D+0! #$+3@HA=%"!&$4(4C..1Q(&A"@Y#3H8S&Y EQ
+MB]F>9) #H<4@!SBP04BOEAW7V$:(32IB.S_6O[29RWT\V8M*O(:S;NWI=:!J
+M#N$H]H8[N$%H*6,IR^+D&F\^2V@T\\A/'P-#P]%08Z!\S<>F]A>A^4@]S/P@
+M&4(XPA(&U%Q '=L$N91*:;:&E?69$K'Z!!B59$1:O?)+R';32/X])FB0\LE;
+M<0BC5 :ECW\,9(R,M#+U.35?._0K%O,F6(.-P3.&Q4M4#])9@FTL?7- C1P=
+M^1B+8K0@+BJ-7.F* !(B "7L60D5]?4FO-"H/BQS&W#.@ :]A+$, W-,<H3S
+M&3=H;)/ BE^.A":C7:X,,&V FWFX6J$&<10&@?%+E1[C1 ?9#03)HXYSSY8:
+MZ;)!.%#KKGJ4XYD8H!>>()#!?WVU7CJ03 A6RU(9F.>&PKDME\SCI44$4P;5
+M5$E:F!-6&\2P-YI4#W#4*8UZK(L0'_&P)W"3GI'TX!<CZ<YBY6F02US3PQ\.
+M25 ):R-LYE8EP![&MC+)[77VYK?" >>=JKRE#W=YT($<!W2F\TR(=G>A^:SG
+MFP\+9XVH/)#=-JJNOXVE<%W"IJ6FY\IH?!A@1CPX[SDH#:S1*F"D^RR?8$YY
+ML:WSD?1B':G!QSO:U<YE,82]-TQG7C21\G.I988\% Y^1X*#:@)(M8&T<FH'
+M XZR[":',Q#UL1;-B9':]$:108<CJ'P-&JI:.#.D+FZF!L%[N&5I=M[GM@GI
+M6U4+0JZ7.;E8:6@!8>! GN\2!-/*HA@(4A8\EYKD,,2#(SR?[5T0*2LO%-HB
+M9T*-$R,]X3]P^$_Z_/BGXW)G90XDFAO 6 <QP(A=H(':=!*,D[QVR(^0T^R*
+M\DD1(S%!@#L\$JP#BV-?+UJ7O/PUNZ9<,=20 =<(<76?X+AOB!?$WP#7B\0'
+M;JZ!HG)ZN.R/+DMU[>QJ&PW<GHF_VY,8I<YN:70(MUXT71K=[5@.J&2>Q!HN
+MF\A:W" TK]C'?"2'E,MDY3YJZ=%F]QEPBUO6QJOEJ4PCVRG[1PX\><S/1961
+M"U=<U!=)F7DP!X?%7*RLABM<7BH-X)55=>L$P:ZI=2>2W^B%7'O-]H)Q>-^O
+M=QL$4N@)$./&Y7L-R.E):^?1M(._M3O(= ]W*<QE/A 4Y,6*_TG!Q'Q]FL;,
+M2^=E8)&0#],;IM$![H>/N;@[MO@D.YYM<IB7D# ' LO3X3!83P')<HOZ$RN/
+M)QR';W\X&!2//*>5*]00RYY=8<= NS8VRNB7Y#"U#EWZB4$?TN"EW78[O&&:
+MJ9=Y[_/6MUU&T;;S=*E& ^Q1D*;_(R0UJ7'VI%(WL%3]R(HIT0-<4X[B5*?O
+M!P4((( $6!54016O@A1-@ +V( )F 1G$14/: 4(0($66 0(@($:^!%<T8%$
+MH($9F(%"@ C6(*J$A9'@ IN((KJ((J^("MPA0MN((M@A91 8(:6!9D019(
+M@ ]^(,QZ$]KD111@ !%>(0G"!8XF(%3@ !-^(3O9Q"@A#$=(E0><T2FAD<\
+M(4J%13O8M#6UUC-P<'JC821W\4YJ$CJ0=4HZ='>ND57&9AW,\REZD7<GH3$:
+M4AX-YD/P\1ZFHRR(@UMYX"W[M1S#) (!=!EKIR'K,@<B0!"F4V4&441^<2U\
+M EM+@W,B)B^E431")%\H\GV/Q5T_0Q^',3\GAGR_42I/A%W.$UF%1S>F5SB3
+M]W2#=A IE#6 ^%KF92V,.(;P=!A+HHLU-R)6DAH9(3- 8W0$(606AF))54Y+
+M$C)],3I3YW)>$QR*Q7V.EAC*<X<(<1=)!8OPI1EW@GA0\T0*(S"NQE^%=W.H
+MQ"Q7PD0Q4SFJA&?TT1<WYB,T<XQ-IWIZ\5:Q02-%8B391$M%LD!CTRY>0WL4
+M)AE+,P<LLS&/8XD>0C6-:!K0121&XB,:PQ/UTQ,L A2>EE0==4+[H4(2(X_[
+M,H@LY#D9!V>26!!VB!)YB 9[6 >AMU,Y,0)4\B>!P@.7%R N@ 8^P&\Q,3RU
+M9SIG, 9.U&EVD *]ER%'TFECL /CMS 'H@),:0=;T 58Z5)[T'M<ER'<@0(B
+MT)5; -= (] (E0 9<X 8B\)1GX)5LF0)AB7\@\ (J0)8%H0(#$7CO9!MJ
+M I@$H0(O@)@(8I:U)P(]\)96I"QNV0-S*0)ZV7M]$(5\B1 D.3>E$0.,61 8
+M$9,- Q);0B%4,'PY^1(@)1-%T!>/(6?I>#!PZ(Y'8@9+ HD+YX=(]AJ(P1$Q
+MA"'32''YQ3N44RQ25TB#<SFIXQ-/1!]8UQ_7PB)!0(8'P1G/47890HJEH2QW
+M,)&4N!FETIB7<9&,V#_TDS+LXI$(<1C3)77;1A#)LBQB )&2 QM_(FW[8B37
+M!"> <1BO=(QM8#?*44-EH!O)]H8JXXY65"'?PQME\#=^]H:/\1M?XQD+TQ=X
+MF# \,2.15"87FE3/B%C!"1A^)C[@21,C 3UP\(9P4$$((60PDC<^<8:U<9^1
+M(R5[<R("TI^ST1BK]C>&$12:164:4XMT #6$8R"[DQ$CX34ZEHFH9(J;"#J/
+M%$QIE <LP$I;*&U*9'CX5BW/ D\F-@?94AZEDD0' AIFD&Z)ACH\HQ]M9!$(
+M4F%=1QVP470$\9E))0-WE9*NM"SG5DS-P1,QPIIIP(<5AY2=>1 ;-0/MYWX:
+M,U(E=5+TMU(+^:@% 5-%LG\T95/_YWXNY9-] I2E(92W1Y1&Z:@30943Y)8@
+M -8V7M*B0),Z915>9=2Z6R7D:M[F1,QMI5J"9:]-Y:=Z9?F20=GF990*:LE
+M@ >7:9=1"0**R9C+4WL3I'F)R*R/J99L":UR29?4NI9=D)G)^I>/*IB )U\A
+M<ICKNIBENCRD]Q%%$'^,V:W-&IF&41^E$9F7B:X9-0+.MSR:R9F<VJ=I4)*E
+M(0.CJ1 ,]!%&6J:KJ8>+JI.@\IHQ401F=I.M"57-)">BY$?$,V/E,B]X-K(-
+M$ATSIC&V1#=BQ"[X0P9YT'F[! )V("4?<K,J04!&94I4NHFGB!"KX1<6(DI"
+M WRQX2V )&TU!D2-6#Y(0JB]!"-0 Z\'L85LDV:XPZ1T, 8D\P3ZR$Q3UD84
+M5J)[.AO[*3(:LV0KL55'0P;5823)N2 ,.1L\)K3PH;58ACLG*SS%0SPFT;?4
+ME4SO U^SN$(#,0((P+B.FP8( +F2:P8(0+F6>RF*4@8(H+F<:[F56[E.E@<;
+MMC<B.XZNXYX'07K&8V<4\YP+MKJ_,[7SXD4'%V&"XI)R@B<,M$!3,B2B]S/P
+MJ+=G9BXF-C6!(I$+VUPL(XX_$K>:I3$UH5;!<:3,%VVF)H^EX;B-V[B2&[F1
+MZ[F7BRF9N[GDNV"?:[F[^FE1!$]3\[6H,H\'4;T[ZT5L5(J<Z%;B]B5ZT5D3
+M]J%YBF'YXG9W@(<FLWN\@UR>\;0@^4B70S$Z%AV/%WO%L2IA$80/."NR(BL$
+M,03&A*=OX'68\QSH8QTG, (GD!Y:V;-[,CV2=C1=TG$_,X=Y 5A_T@97]3M/
+M!T$0*B<P BT.DP;3 8EQ5)5H-%!_(<21=Q"ILX6P<1IE>F(=8WXB0S)^"A^2
+MBI*YJ+@LN5H&,45D1JD:F[ )L5$T,*FD>A"6*G\H57_W)\8#X:DR=2"AZG\Y
+M=<8]^9. DJI#^09%>92V&KA+:974VJL9197 FI6F8ZW%&JPX@:P#.RYF4*\?
+MB*^=J:_?"I7F*J[3NJMX>:Z,/!,C$'=O%GWXYY>CR:Z$"7V!=LKR^LCG$<D+
+M9J^4S)>6C);\.IG_:IET*; ]*<K*0\HXL9FNZL95# (S\+!-8([M*DI'BA$>
+M#,('8AQ4!,;47,UV[,8&L5$U8,9A7!!IC*D'PL:;*L9P#*K]=U-U_'Y&@ #K
+MW,Y)V$]QT10Z:!8VF!9#R!9ND15!6(,1:(!5$00( - "/<]DL81% (&C<&S
+M(M !'= -R( ,2( #.(!,@ 5?=$&C; #<04UQR,7.29N*FLNW&"[$5%/UT9>
+M!4YK!,P$T49>)D*]95=B-DOP$;W+-J<O\Y\2HXO4%&C)M$M#449+RTG5$<,]
+M2U%C$Z9"MV$T1!!I-32X5W"# S%^L4!WP3$#!4MMM''<YW&ET1@QUF!ST :D
+MN)V? S3>,ZCK4BK -S=3PBW#H1,+"YH@4,;[\C-*R=6Q1C,$+,)'G6\=HB;H
+M-Z^GFL<@H*K*P\>MZE+*.G\'XEI*PS0^P4P\H!C[]0)D\"1];*VM?,>%'2@B
+MD-DC490B,,SA",BX*LB<3,@Y8<A6^<DR,:R*C,G&*I:,R1,E02POK!>R>%]"
+MDP9X -LYH20;$C6T$U. 77LIX$1%D@;*7:N=F<9?4 1.0 5%( 6/.3R8*=PX
+M(=U0( 5/, 1%, 53$,AW::Z\K'[H@P+ +:LQL /Z@@>'O:N\9 (FP,E; -Q=
+MD,G\>@(M< +P#=PKL *:Y\B<BJ;!,3NI?=[ZO04Q<*X@8.!NK!Z55<(GH ,/
+M2Q'>7053@ 2U9P(+[I4-+@/GFM[8_#M;N ;<[5*;V9DMSI?K'>#RS0/T+>,#
+M7N 9#G\E]07?G035?<EGX(A"@Y9J&9=M^98E(.3Q7:[ZG0(FSI>]K1=O&4Q%
+MDMRXVMSF+>)X4.(KGE&U+ )QN<E1_N0Y\>+X)]U24 144 52X 2U!P-D3A'"
+MG.,44<PT0.=&\-?5TB$8H1$*DE*!2W/7G!!"U@8(8.B(;BB%4BC=*[EN@ "/
+M'NF\\6K\*2<P&UAI\,3H S->YV#K!EA0=C!01YF]PGU,J;XB>S"D$4?(=R*[
+MX7-,E"$4(H=ZGM3<L73F\25NT *+(6VGOCT\>>($L5$VP,W!3A#?[-B ;G_C
+MG+#E/%/G/*H:_1.349B%R@9"H[^[9"5%TUG8:U8'HM>!Q6E@H];]4YZ2 6AG
+M^[]I"U^I)4[C9#+]2B/ZNT >IW$9X1'6P;=<2UW?;J6P.#73X1HIZQ[-QEJ%
+M%*NJV+2FUDYPMN=+^1KY(3'K_L%ZFF&BRV'87JD>R!4E2((D^,XSJ((?5/((
+M\ 5MD17MS,[LO/+M#%::<6'I,S5CD!'[P1X<(S)SVYSVIQRZ9]H@4!?AH^T?
+M]S-X/"5)U$)M=+11S1NK^"_BFRF;XBAUT%M6/Q*_E?5GX ((P/5>CP8( /9B
+MKS%FD._I8]ECP_1[ GI%"GQ5'M>U)V3ZB/1X]=D]H3'&J$I]YJYSGX5QU$:B
+MK1_!^R]!X? B 4<WLWV:D0>ZUXSRSO9Y$QU%1$P=8AVJVV 4U\"2])X,Q%<T
+M?UCMHTR4_SH-(X?9P8%=X?$@;X(4#!8C?P0F7_(*+2NSCP5>W_5=?_M>K_M=
+M7_NU#V0Q(62IWQ4?S_HG^/JQ?_(&'801"!4&[<]4X>XU;R0F$59%731[M<(+
+MXS\^ SO7158WEC[B;BZ=5RJ(?NB'KNB&TNB1&^F0#NG<HQ?A]4XF9AWZ"!@R
+MC)T&(0+8I5F/&'3DXAWC[T2ZN2>==1A^8CI&E>I);!#\J,R+)")[TO]E2G._
+M6QK#K_K%+_(NN(+)S^,378 ':!7YC!4$+=XAJ(%/Z(1.^(1.Z(32;_.W:! N
+MD6S&ED-VICJ 41^HY"L^[3K5?_J W_E5C1#C433EGSZ"HT>N81+>=V@,^;NE
+M,?RJ7_PB[X(KF/P\/M$$^,Y/Z(1.^(,^Z(/2GQ'"(R\C5]0B-C=95X>=OR>+
+M6!K1&UN2\>IFRQ/XR<4%L8A_=C#OEETJ.J'H61IB(+O5E3Z1?Q\> CG@>!#L
+M(2VLZ!K!P2"=IKZ_6QK#K_K%+_(NN(+)S^,378 '6!4P&,],T?P,)?TVGV0Y
+M=#]O8$Q4"3_DAK$A@NOINRZ:/QY +3Y4CM15R,4%<;I7*G,B&>^E,?RJ7_PB
+M[X(KF/Q? /UI'H(:V/QKWOIL?H!5L<^?GV,.53"\D_W:U!PARCO.MV76<759
+MIW&4;FH+XQH^\CY;J*;0Z5X(P1-RPR0,@K/)H9, AM(KTVJ4/L4$41<M5;\A
+M!KC3KR,>;6+MR#(0 B>!6RKD<ASN5@9\J(C4J?/,.*-&PDR6W_E^X9W'7>40
+M3TGH81+>=V@N.W7><7V1$G3?'E883N=4CM0=T@(C0 8ZH!<=!:C'K#%"!E_H
+MG^B+OO[>Z^CO+^F3/G&QIK1GT& L5C"\(P(M, )DH -T\(@> CFOCB3=L4WX
+M$H;MU&$> CDGT5X^P1[20I _D_U$TVFHKC%H208Z0 >8*=4N#4)?%M-AQD.I
+MDZ)J)6FT,1!0BB98E.Y(*E(=/U*K'_*M7U(NN(+)S^,338#O_(1.Z(0_Z(,^
+M*/T9\;O;:3H XA_9Y"&0PUA.'"?_2'EE'QL$7!K#K_K%+_(NN(+)S^,378 '
+M6!4P&,],T?P,]?DN-G4D3 8GW#<M 8MT%B?70>EL.QJH5CBV1,)T<,)]TQ*_
+M6QI4CM1\0^E96-2.P4HK(SUH@*C0(4#4T3Y3-RB=ANH@( (Q4)<#(0(R4)<G
+M.Q B, ,B(*,'X01@ A_\(K,_X]U2X.,,%1T#GY)QTSH(0 <(0 <(0 =W@ !W
+M@ !W@ "9@0!O@ !O@ "<U6FHWCZG0L"QTQ_U 9V=IKX1'U9%$\4E'2E'!F\M
+MU*W/BQ#DAK&:YQA^8EP^02YBTC\O$A3,*%(1&_GWX2&0<Q)=A>G6?DMJ+P?'
+M"1\BT (C4)=D3V1559XV#6CTH1CG5&&F0S4^<62JG/U$TVFH+J,'P;&SD_U$
+MTVGJ&U 2?Q(2,ZPJ3#%]TQ)#IAQ5=?<E5ECFTNLB,S;7!YQB0C4^<62J_.OJ
+M&7*,=K,)*57O(I/G TA;/Q!3,)""ND(,PA,8WLW"[E$@< /&_G[)OL::VE)N
+M_.QR'.WI#/0XT0(C0 8Z0 <Z\ 9TW@(C0 8L8!(L ',Z\*;#HP-&H -,@)1.
+M ";PP2_L\I [.I%T]AXHV_E/U;,Z;VGF!4V)GV?O(5DH:K]ZTR%1O!LBT (C
+M( + 3Q&C][J8?[W<0>O(#?'C;TH9OS?T!9U<7! BX 0A4)>J5!*RF6@8GN-.
+M$ *RZN:"Z00MT%&"Z0(N0!R *IBBJ3'%O,UW71I4CM0M-?ZU)/K$M4(9N<,&
+M"B^0PQG:T=:?(I/+03). ";PP2]\)N]>XC+*XG6WLQP$7!H^\DYZA*()\Z#'
+M7>5[GNJRAW6T9Z/!H?/=<3H8<@;35RK(-Z#+,=@#B\=!N<=]W'N-C5*0O6J2
+M?=.IBO9L@-F:;92<W7NFZB>&'=J:C0:E/9670>5(W2$H0&XZR=HX@=N%OR=4
+M26XZV>4((>$N)=W4;=W8C994CM1LL-V,Z=U2X.,,A98,1@9U^9@,YA-Q>=Q5
+MON=UB;/)H9-.WN4QD:TH0&XZ"0(^P%$X+L;DII/6.N6UWB$H0&XZZ5$<%><S
+M8>;JY]U2X.,,A9917I>/&>6J%)=UB;/)H9-.WN4Q@>9JSN9NC@+DII-Q/A%S
+M+NP'4<PU0.<%D>?(#?%&0.ELV\T)49]'0@8DR[*E87D#Z>Z H;_KE/-1'7"P
+MH7D QFS@F)V\\])@IA_!1=/G43#;WTQ.UD[U<083Z1CT,3=4Y!KMN!R.,U1Q
+M YIX(R\4HCL(7%VET3]'_$3^NA^A)8J+0V*X:&:3/G%3/!!-D+@2 R&A)8I1
+M9$KB=21)8CHLPQ-RPR1<7!"N0QUFU(FR%B]P(#13 Q@FED-D@+^086:R8Q[<
+M>9X*3!T$#!]D2R"]*&D906D@,ORJ7_PB[X(KF/Q? /UI'H(:V/QKWOIL?H!5
+ML<^8,_RJ7_PB[X(KF/Q?8($56($ICQ4/./Q<D?Q? /UI'H(:V/QKWOIL?H!5
+M$82 ._WH1^=C# (X8.SOE^QKK*DMY<;/+L?1GLY 3P4=^4--4WA4CM0M14E>
+M!&CO;,'W_$\9/"NA2RQD#>I,VXF1HFD'I3O6<7T.@N&H-P:\Q.O'7>40/SPN
+MP$M4CM1LX *\U )-\R1(*60BT )-\R2/^.L,K'QL4#"\HQ@$Y< )HVE-UFLV
+M@Q ><Z&R<1R21AOE2 9,0R,C_#,O#6; )4M4Q":'Y.HV";\&0>5('=AG_3_K
+M%.IVQAVF3WT83N?'7>40WU& *JEE7 -(Z1+)1C5%O2R(IVI55?=.S[ @8 .#
+MG5&BZ5(.ZU(ZY5(R<.<N%0,"-NV<6LPZ)>S'7>40WU& *JEE7 .#[IF4'FNS
+MUG*GYANOCAYT]AY.XQGL(2V%8S.</T,U\S,G0 <GW#<M\5J6'[&1?Q\> CDG
+M,9)SG50W@(KPHZ0#$>6M9O;P<WT'(P)4CM0=\E$(,0)TH -&(JDR( +H9\V4
+M*NS9# *\\E&4*E+Q!\[+WL9N_.QR'.WI?.PRP0<$X0-4CM3#F5%\0!!\0! ^
+M0.5(/9P9Q0<$P0<$P0-4CM3#F5%\0! \0.5(/9P9Y; NQ0<$X0-4CM3#F5%\
+M0!!\0! ^0.5(/9P9Q0<$P0<$P0<$X0-4CM3#F5%\0!!\0!!\0! \0.5(/9P9
+MQ0<$P0<$P0-4CM3#F5%\0! \0.5(/9P9I5,NQ0/#,^V<6LPW0.<%0>5(W2$M
+M, )TH -&(JD.V\T)P;&STS]'[#J8PQ-RPR2\8?;>,?ZJ1&WJ88DUH3$GX ,G
+MK/GPTS]'##U428XGP ,GK/GP R&A)8I+"EANH"QQ4RK1JX\ LE\T83H[+\#N
+M[KZ%PYV/)=6H:Q!',R4L@QW/:;CG5&&F0S62!1@'61IX!L$7!OP404[5@6K+
+M@G@;HSSJH2'7SV=YKT>ISB?!L>>LU%D 1N5(S3=F?ZNNT^H@(@,AL-R7HQQ5
+M52K1NT0',:<2T]:?(I-G5DBN0^5(7?E&TNH@$@,A\+OP,3S&Y.>%\35QI*2Q
+M2!VF-V04(P,A<+*6MC+2 [\&0>5(W5+CWQUETVNVI&/]41_S\NMU-! S(*,'
+MD>?(#?%GIASE&1R6U$)M_2DRV3I&TNH@(@,A (LQ$ )=*E7FPA-RPR2E$OGW
+MP;Z!&_I _8^49__)H9.:/P,A8#>1 B':B#C3[@1@PNU\EO=>8H;64AX4TC]'
+MS)V7(0+#XP./V, $O+=E(#=, CU4*0(\H-V# U>5531])D#^./RJ7_PB[X(K
+MF/S3'8(:R/SU;-TAJ('0+P6 ._V8@20GME2E0B[#PUVH1B%ZY!KZ>SV:Y1-Y
+M4 8&YM3Z7Q!ZE+NJ@UJZ^51M]/D),_RJ7_PB[X(KF/P\/M$$^,Y/Z(1.^(,^
+MZ(.UA"2&5&J[P2_Z7Q >1R&3)1MT]AZ!6#+EY$I:QB]\]C.__DA'IO\%$=E-
+M TV>8_'24IY(<BZF,Y%( CW2DND2PX:C;Z4=7"7?2*>\D_^6UED -ORJ7_PB
+M[X(KF/P\/M$$^,Y/Z(1.^(,^Z(/G@4QZVC][OAQN)AE3\L2N@[E2KRDB<?6]
+M=09:'V8HH)U=95XFEAER<&A5N321$KWCF5U+E)W%4G8<<<0#,?RJ7_PB[X(K
+MF/P\/M$$^,Y/Z(1.^(,^Z(,H@ H@ H@ "XNNB&(@<(( <(( <(T&E:_UMV
+M@ !V@ !V@ !>B0!;@ !;@ .CBNX@BM=@ !=@ !=@ #GB@ I@ I@ ":=QY8
+MJCQ4,Y'=H9M/A:0BU?$CM?HAW_HEY8(KF/S3'8(:R/SU;-TAJ('0+P4H@ H
+M@ H@ !HB0 B@ B@ B</Z)ONCK[[V._OZ1+@((( ((( ((@)D(D ((D ((
+MH'F?S\?=+.P>=5[&_G[)OL::VE)N_.QR'.WI#/3U*6M(DT5EX)VGIA++@G@1
+M1'W&UDIK]'3U0<#P\7J0MQ=8IQDL,@54XH]4CM2!?=;=ZAK!P<4%$>75!5L0
+M#'MVAHY?$XU%'4VJE>E;6B,$?(X .2!_SSO#.+@M!3RO/@<UWQ%ZIB_<T6>9
+MX3B*ER-5^9TN(RQ]@@:405^!6#*28_F=OR?]V30XYK*0 R+!X5.(5UVP!<&P
+M9V>(1Y$:@K0X6RWI<P)O< )D#T@H,:PJS*<#X01@ A_\PBX6 P(G\ 8G3%QP
+MHF7P0WI\I_\%87MW WGG@G6:L=R^=@)O<,)W:S&_KI["UR Z>S>0EZ3H"(O>
+M<0)O<,+_HTB=IKZ9<S0<4[7EV4;EG\0& 7J)XP)% #4B0.5(W2$M, )TH -O
+MP **<09L+ZDR\(B8L31-@QF0 R(V,QJHMBR(]UHBH!AG 'HB@*!P55D$\LX6
+M?,__E,&S<A[F;KWU8>]_!%F!QJ!RQD.I0SNZ;;A'!3G9Y3J7!W,?:2W6PR_G
+M='M"0HI+PUP[K$KZ*SX!)!ND-4W;R+:$ML."ND+H9\W6;,W'+NP;%0,=]5&4
+M*E+Q!\[+WL9N_.QR'.WIC)3O_(1.Z(0&#0(ICQ4NS\ZH[X'%'_*M7U(NN(+)
+MS^,378 '6!4P&,],T?P,]= -R- #O8-E ?W@G<]8,>V%/GQF,]8WK6(P0P8I
+M!@*("#F/80:/F!=YL)*(=QY<7!#6,?RJ7_PB[X(KF/P\/M$%>(!5 8/QS!3-
+MSU"?S\?33@6<I1R[9DG4>;W<H:2\8?:U>[.?CQ?'.9,$D?_=T6GJ"T\GBOH>
+M6/PAW_HEY8(KF/P\/M$%>(!5 8/QS!3-SU"?3_T, @(O#68H,6^9$7LR>A!7
+M8"$P_!SSEAD2O!X@"EHPW(F=IKY0AV3U"Q\G0 8G0/: I!^7"(DT&;$$$?GW
+M01!1?!+#A"3C,L0B\%$(,0)DP +SEAFQ%P,L,&^9$7LRP (NX (NH -T4)?_
+M2'EE'QN%)YV7_F;@>!"?GS#/06?O$8@E4QJDQW?^8R$P[!<ZY!H6<P)D<,)]
+MTQ(;0\";J#<=$L6[ :1TMI*(QQMF/_JH[X'%'_*M7U(NN(+)S^,378 '6!4P
+M&,],T?Q4 +C3WZA!-HC>Q5].Y-//9&(>8R[U(4QW:S'SEAFQQ\4%4;O-0P;Y
+ME3#"Z!?$6$O;#P+SEAFQQR!)-25GT& 1MK(-3, B-C=9%R;):(\H8!WSEAFQ
+MQR D"CEDY1.]UD:?_P9)BG@_K"R-7S+OTRQG_4PFYC&A5#8FT3Y39S.<W[OE
+M.6^9$7N0!6"Y&'75-9&U>[/=P<0$ 1INMB3R!?P40:/]41_0V6GJ"T_>,?RJ
+M7_PB[X(KF/P\/M$%>(!5 8/QS!3-SU"?3_T,<I$1G,0&8<D>D@<[%U:1%,6O
+MKH[^^CS,F[X9F9"QSEZC[QA^8EP^02YBTC\O\ASAPR]\9B%K1F34*9/+ ;W]
+M,9 &-_'P\?FETVGJ:\#H@1Y#BK.W\[P(87],G2^&"3F/<6Z=ANI5&3MU(&G1
+M$XA!SP;ADT7PP2_Z7Q 6<_/ 02WL IY!EV0*S(I\]C/.!V(-W+Z.X_ G89T,
+MXNY4W:;<D1=Y\![<E1G/PQF(^AK5UR'#K_K%+_(NN(+)S^,378 '6!4P&,],
+MT?Q4 +C37[K1!"2*5:8@-Z<[G5IWZQUH,!*E$5;]@A!1?!(C.==)A0.J5E5%
+MO2R(I_FDQW<RBVJ>GL0*IMG63,W"GLT<!:@?1:DB%7_@O.QM[,;/+L?1GL['
+M+A-\ (F=-@<Z@-\D+JO'[%)\0! ^0.5(/9P9Q0<$P0<$P6!DH -.'RF22N5(
+M/9P9Q0<$P0<$X0-4CM3#F5%\0!!\0!!\0! ,1@8ZX/21 JA4CM3#F5%\0!!\
+M0!!\0! ^0.5(/9P9Q0<$P0<$P0<$P0<$P6!DH -.'RD=1>5(/9P9Q0<$P0<$
+MP0<$P0<$$>4Z ,6FITJBZ5)\0!!\0!!\0! \0.5(/9P9Q0<$P0<$P0<$$>4Z
+M ,6FITH.ZU)\0!!\0! \0.5(/9P9Q0<$P0<$$>4Z ,6FITHZY5)\0! \0.5(
+M/9P9I5,NQ0/#,^V<6LPX0.<%0>5(W2$M, )DH -TH -&<LS=3.@_HZ2\8?;6
+M,?RJ7_PB[X(KF/P\/M$%>(!5 8/QS!3-SU#2;_-))K_EF9"G[;Z%Y]7_2'DC
+M',.4[O<_/3O6\?EOD*1C<'7P?@468BXU>1YR0F?O0090<_@M([.H5@;'.9,$
+MH:0?O;Y%8QWOH9ONWFDFT3ZG G,;\WQ&!?P400425"R!E=6QDQC4>;W<4;LW
+M^_EXH?E*VJ41-]?CR"NJ5E4%PSM17DL6 L.E0>5('=AG?8N36&B'=K>6'[&1
+M?Q\> CF[(0(M, )DP )1K@-O( *#G5%4CM1LH -0;'HZ ,6FITJBZ5)4CM1L
+MH -0;'HZ ,6FITH.ZU)4CM1LH -0;'HZ ,6FITHZY5)4CM1LH -0;'HZ ,6F
+MITHR<.<N)0-W#O2<6LPY0.?'7>40WP(C0 8L$.4Z8"1W3JG"GLT<):D?1:DB
+M%7_@O.QM[,;/+L?1GLY KSBJ!!N-4:&WT;M'"F!TX_"$EW:O?C=XB&I_QG$%
+MPUDAQV@W._[/<V2J//[[-J/R_CUC@'Q'9B'8,G5M= )F<,*\ 4CZ,:PJ_$M_
+M#[\*]B1AV$X=YB&0<Q)4/-?CZ%_G43 'C'@@1O:U'MAG;;AQY#%Q9$LH;6L=
+MYB&0\^HB\%$(,0)DH -O2N5(S08Z8 0ZP 0Z\ 8B\+NE<0)&<,)]TQ+7HV_+
+M2B'8ZSA!Z_024_ZP2,),<,)]TQ+7HV\P>:&O7K\S21"#S_9!9W],773'GA-4
+MCM1LX )CH ,&D0,Z<-Q5ON<ZX/0.H@-.'RF22N5(/9SX1^5(S08N, 8Z8! Y
+MH /'7>5[K@-.[R ZX/21 JA4CM3#B7]4CM1LX )CH ,&D0,Z<-Q5ON<ZX/0.
+MH@-.'RD=1>5(/9SX1^5(S08N, 8ZH$\SH /'7>5[K@-0;'HZ ,6FITJB">.U
+MS@8N, 8ZH$\SH /'7>5[K@-0;'HZ ,6FITH."^.US@8N, 8ZH$\SH /'7>5[
+MK@-0;'HZ ,6FITHZY5( 2.<34<S^];!4CM0=T@(C0 8Z\*94CM1LH -&H -,
+MH -&<LS=3.@_HZ2OQ3P,>UZJ5E77SV<_(P(,1@:/^/D)<XN3&$=L#P(B0.5(
+MS08N, :/N&=.%K0_3)DX (O6(0)17MJG/?VJ1"[6$5NRP?9%,_A!%P,R@'[6
+M7,W"GLT<5<8?1:DB%7_@O.QM[,;/+L?1GLY(^81.Z(3O_- -^- -R- "#?U2
+MD 4(D 4(D 4(D 4@D/)8X?+LG%(0W8 ,/= [6!;0#][YC!5/Z(1...WD)"74
+M:6I/QE;T53"\X\4O.?KI,3=9%S'T1A"77YZ?CQ>O91TO#6; )4M4]+M?_>ZW
+MP6#!H?/D[IR10B[6X4L;XR>&S?:8*_6:(A)7WUMGH/6_Q?M%&?9A'_:\8?8/
+M?#>0YV9^8MB_1YV+/]C='7_37=W771PPPI'0X5#IXS$7*AO'(6FTD3GRPC0S
+MR:EM5/X@-ND39VK PUC@+Y)T7C*=V&GJB[CT3[5V @*(*(J[F9#8/*PJ+ <B
+M8,#P(=W4;=W8_?EFR)YT?J=5$BBC[T9G<J2CCD6]9C/8//X#H0;L>2[@_XKJ
+M./]ZT4HSR:EAH)M/U5FR]L$+>1A^8CI&!>\#P;'E0><Z#OO4;=W8+?TVC[A(
+MMJ&=Z.[N>_!BC.9JSN9NCCG2;05/D 1$\ 5ION9M+OTVWR_8O-64'FL0$G#<
+M"6H#(=W4;=U20.?2?U@$D4.(UC4P5Q" ECG64AX'+\9HKN9L[N;/H^.P;P5/
+MD 1$\ 5ION9MGCFI1>>F4DAP55F8\8>%TQC20D5R4O:Q@:38_-)@!ERR-%P>
+M<Z&R<1R21AOE2 9,LY-TCM!8H ,Z#OO4;=W8C9;:G9E;A^9JSN9NCJG0"1EF
+M!B&A)8KPUD* -OYTODZ"2]+Z 6C23=W6C=W2;_-[MOENW#]'S)VU%>^=V&GJ
+MJ_>\0VXZ2>< QA-RPR143.DZ7TNBSQ-RPR011.<XFQPZ61 HX'W3I'D$$=E-
+M4Q!DV]+P*\;2;05/D 1$\ 5ION9MGCFI%?^!.GO:A,WX0Q ;"A^0J!#Q]P5I
+MON9M;A":0><Z#OM6\ 1)0 1?D.9KWN:9DUJ7>$OC3^<_/3L+XQH6T[[E02'2
+M3=W6C=W2GQ%=BLWJB-)+NXI<X]'(!TCDDJTV@\V?CQ=5V8EQ(V<W72HH "$X
+M3TT_3^<(C04ZH..PG^9KWN:U1VXZ&>?X5P18H ,Z#OM6\ 1)0 1?D.9KWN;0
+M+1/>#=[B3=[% 2,<R7/^>'59QRYH"TT'+\:N&(@#$02W2XAC\^M9BCG:R<4)
+M^_G4[QK.>MYL69<5LC3,U4S+V5*H*\:^$B1QPS(+(VF \3_K)B)[$L4GP8R/
+M6@18H ,Z#OO?'=[C7=XACM[0G1,;WN$#,05EL+[>L:+9OS,?4AK1&VY",>OP
+M*\97EW5:%/69/?6-4O557_58?P9:[V0?<B>/43IQ9&_'+NP;%0/;_%&4*E+Q
+M!\[+WL9N_.QR'.WI#/0YL78K 8OOEEUUH$[6L:*+6!K,!HYN#/@1NTYZTR%1
+MG"9( B/06=0SR:F?SUF=IKZ_^]5XP2Z7YD5>/).<"J3O!EL?$CL0UCR2U843
+M1.?KI#<M%<6O?F(.CQB(5O:QT=+P*\:_SL!'9F $X01@ A_\PF<_XX??> 9T
+M#@(BT (C\(CDXAT*;VL=%L6[4;O-D\1BC"2^=GV1$G2__DCSKQ?N'^EO@ !O
+M@ !O@ !@@@!T@ !T@ !.9.<RA[2PHJN(2:J##^?7SJ=IKXRZL;.F!&^<M/#
+M!:3L@5@ )(J[F9#8O-75SB[#JL(4H_Z% KZ52P<(0 <(0 <(H"'EN[ER@ !R
+M@ !R@ .S#L@( (M, *EC<U1?!+,^*A%@ 4ZH..P#P4<[N$H$.+YO=\D[N1=
+M[E)%@ 4ZH..P#P4<[N%H208Z0 ?;3><(C04ZH..P#P4<[N%HN=U KQ#QQ^-/
+M 6#*5_F6-3(R!<["N[H6=/TQJEE)VF%8QV+&#O1L1+62=5ODET)B<UEIT[,
+MZV0?@D7\$D?A)A3E^4QMALT+.WWEJ8X6@QE_2"'/9&(E(9LRZL;"'W\\_@10
+M(/TVOS"N83&_KI[,^*A%@ 4ZH..P#P5/ 7/#?3>'']?8 1)P 0'73+P(=U&
+MD 1,<-#2;_-)ED/WDS#]2N<W#QS4HA=)\ )/4%WI$ZM*ZB%;:"S8K#BJE$,^
+M02XZ5G7(]E1(@J38K&$:+R<B<'DP]XCD* *7)R2/^%HV@\VO!WD@D 0O\ 0S
+M347,^*A%@ 4ZP!NU+-U&D 1,4 1"(P)$((KZT0925E4DYL9)\ )/$ )P#MTR
+M(=U%@ 5%, 158-WQ#A_270184 1#4 76G3FI=1[(E$.(EI#8[(I?1,3!P1%'
+M;!%6^KNED?]TGK[KHO<_$ZOSEAFQ!S4Y=#]O0.>GMK!\Y49G<KW<81T 7[O-
+MD\1BC"2PU1_U 9V=IKZ_^QR?;X;L2>?->=/E"5=(E#(3.5DY!#6K<XQTKN.P
+MW^,__OEO8$>+([+_$1LA4XCT=N")09WE:=.DQW?.9"'*HH]<=@)D< )TSAN
+MA!(+XQH6\^N/=&3L@@))X )%X +I.! B\%'8/ )DH -T\(B1?Q\> CDG\?-T
+MCM!8H ,Z#OM%@ 5%, 158-W?RF&;49='PF%C@@).#MWJ)]UN7C(A)OV@;[A)
+MY>;HT6MMQ!$G,9.<*@,M4 /IF%17EW41 Q@QHY]E "*#Y-&H*\8@6;0^02[>
+MX6IR,XX\X9NA1Q#SAZ38O*+>+04^SE"?S\?'+NP;%0/%_E&4*E+Q!\[+WL9N
+M_.QR'.WI#/3('G\\+@4^SE"8RI']NJR%D^Z%)P)FH*^EC<W (08<<<23/G&Q
+MYD76<7595X>[B\VLUQ%"(]U&D 1,4 2_"Q_YWQV=IKYTGF2 %JL@,&^9$7O'
+M"1\U6A\^\3UTWL#MZV0._^KJV$;K-)UA5!_?> 9TGK[K\L-Y03). ";PP2\R
+M&\/9T2_8',4E'2F_SL!'QBZ1V!W,Z:]T+OTVG[[K<K+PA?Z(7O557_4I4RF4
+MDA<(0 <(0 <($)"EX1A^8EP^81)T'DM91QJ"Q8R/6@18H ,Z#OL]_N-H60:@
+M49>/Z7PAPO;8\9R8&>?X5P18H ,Z#OL]_N-H:2=U^9AVHDK16I=T#ATNZ>1=
+M[E)%@ 4ZH..PW^,_CI9Y 0=U^9C1ZE$^ )=*GA=PT*78G!?JU (^P'-EX.30
+M/1/2/05JK@1- 7% 2,^02YPHA)4JV-E0 =J\"8HH'F3/G%LB\VND_^O 3OI
+M<W595X>=OR>+.).<^D2K;DAO!!\/?#>0IW!J\"9T?F8'ZOB,HQQ553!&8OF=
+MO\)O0.=07.5M> (Z6VGN \.E(=U,\ 1.< 1*T 100.?2;_-)ED/WDS FX7U!
+M;!VO!WET+FOU<09J\"8HH'F%R")#,#=9%S&%54A"U2 71N=3)MU3H.9*T 10
+MD#GL.2!C<'7RZ1PP/),'+EOC#XM%HV-5-_YT7C&@N!NSEAC,^*A%@ 4ZH..P
+M/P5JK@1- 6U%QF9^7/2S01/X 1'H 1- 7% 2,^02YPHA)4:QV*<1)J\"8H
+MH'F3/G%LB\WXD_\#03=5[H\/N:/@3N?H^6<+UT;0(4#PP7!M)&M(0^<Z#OM3
+MH.9*T 10@,0M;2%#[(HM#;]B_'J0YS#U<09J\"8HH'EG=J $X01@ A_EI?\)
+M>W59%S%2-OH#(=U,\ 1.< 1*T 10<&SO3N=07.7^N(B=*+.\DZ)E"[]B#$A(
+M)MU3H.9*T 10$/^8L31-TYQE)RV9_AYT#F##(_EQ!"-BPG;2/05JK@1- 5_
+MB\W2S01/X 1'H 1- 634SSY\CM2MJ&/9C/8G/T'XC$7*AO'(6FT48YDP#2E
+M0;8V@\WY#XF=IKY2_<M!DG4 PG8V@\WL4>W,^*A%@ 4ZH..PSP1/X 1'H 1-
+M 6U%QDL0&Z96<W"GLT<=0/&_G[)OL::VE)N_.QR'.WIC)3#SQ4&7?PAW_HE
+MY8(T2-!#D/)O$<],T?Q4 /W@G<]8<=$6;=$@\(1.Z(3-3P70+P4P&,\RZ((K
+M..VC%[&1?Q\> CF[\1PYQ)' *;.\LX@L1,#P >X$D>Z%-_RJ7_PB[X(KF/P\
+M/M$$^,Y/Z(1.^(,^Z(.9DUH&C!XUBO@(\61L15]%+6)SDW414UA^]!M'FOUM
+M.H8Z3XXV$W& I!_#JL+Y\M-,1V<[1WL%+S&DL28#$02=IKX:<V3KZQA^8EP^
+M02XGL 4G_$0GT 4G'(FE+C+) ?PX009;P +SEAFQ-P=M601.O'/_2'G78?:9
+M\^X$T35T3A"UVSSS,F^9$7OP'O2FP30=<F301^<$,6^9$7NN(4!PHF7\LK^%
+M-&^9$7L,<CK";DG4*9) GQ!$L 4LX&=M"1* A/\9!F'-<S\"]&>Z^52X3N<$
+MH:0_K"SYE3"O%'Y/1P8<81(R>N)4($ ZY!HE(9NO93"<D;LM!&@U6A])C,TH
+M0&XZN67^I4K^"IPVVO@?L7>F1^?CXAHLEA',2!%FL 4L,/YST);_-D $D?W*
+MUK,ZW]()@Z3"7KO-,R]'!F_<,?[P'@1"9Z@G?F2J/.D3I_/GX4I:5E[LLC)T
+M3A#CSR!)94G4*9) GQ-& .AR<%"X#N[A]W1!QY!TWM(_4_X@AK>:Z/02$_F!
+M>_#8;!V?;R1PA=/6H:3,^*A, .AR<%"X#N[A]W1!QY!TWM*\,_A.OW-!M]3[
+MA[UT?FRI=6;,MAO6H:3,^*CFHE)R<%"X#N[A]W1!QY!TWM*E.#=9IW&4;FHE
+MIW=CB') GQ-N/@5EP(<7:FQ+O7_G8F;_TOE5+>Q*^L.DOG:;X6!ZL4_Q7DY<
+M[,8YU(Y#1C% XA>.D6KA)@=E!R-RXCXD=N+93U6(=QZN(43/]2FETC5T/CEG
+MK:3,*&I;P *@UY:!]WO4F3[9WZ:(YR%;J.]O0.<MS3LAQVC-@VB@9\!5M'>F
+M1^<$H:1.IGB%X7JW)R0D$P0$T?/#>>*_SL!'QBYP!2.YBWA2C;K8K'UNKV(>
+M@GD&!O23LP4L@+;4T9;_-D $D?W*UK,ZW]()@Z3"7KO-@VAH2QTD$P2FP30M
+M=62G-^V/NE$Q@ /&_G[)OL::VE)N_.QR'.WI#/3.YDI:UEKL3AV_6TX,NF!,
+M0^<$L>F>8_'2@D4_S70\E#H$41Z_D<38C+;4P2). ";PP2_L@NO_TOE5+>Q*
+M^L.DSF;-Z>YR<&AW:S/"7OX@EAYSDW7L@K8#D>Y(*NPG 4GW#<M\;O(:/&(
+M5?Z(^T[M6QYTWM*\TQV=IKZB@B0P@F@ AJ3"/ORJ7_PB[X(KF/P\/M$%>(!6
+MD<]80=#B'8(:^(1.Z(1/Z(1.*/T9P8R/"@6 +@<'A>O@'GY/%W0,2><M_3/E
+M#V+I,3=9%R;LSB+)/,/"GD/M:+CFDD/8,G4 Q.ZUI$QT3A >PS&6YAQ-XSD6
+M+RU8Q"_L$HG$!!MT3A# LQO9'X@@X 1@PNU\AIR1J'7"CK:9PYY5R1$G41HC
+M_#/9KTW"'OGWX2&0LQOX8V*Q)"WEB3\V(^SE\1L^@;;4P8R/&LTPXA/DDC=J
+M0.ES-W76,?RJ7_PB[X(KF/P\/M$$^,Y/Z(1.^(,^Z(-T?FRI!4]T4P9\5HIS
+MDW5WYR!%A?C"/FLM)P:R!$\LEA$LDLSOE$/M*)]!?>+#K_K%+_(NN(+)S^,3
+M38#O_(1.Z(0_Z(,^F#GO7K4J!AW%4G8< 3G+0>>0>%_:7QK9OS,?LI,/2P=;
+MP ).T)9%X,02,_[KI#=\XS>"@FKY(:,G7NAA@ <"]#$5 XJ[<7*J5+O-D\38
+M'+U.T%X^07I\M[ZN(V P@'[6;,U _Z@;=5/&_G[)OL::VE)N_.QR'.WIC)0_
+MZ(,^"(/QS!3-3P5/Z(1.&/0-+=!!./Q<D5(0[8#WG 1/Z(1.2-#B'8(:>-$6
+M;=$7;=$6S= "'80&G?)8\<Y/Z(1...WU"6+E^$XYU(YG=D8J[5/<81TO#6;
+M)4O3C"$%DS#(%XF%)W<$-V7>41*RZ=/D0@>9D?AF$"19!QG8,T>-^+OE5!V#
+MZ%T.ZJ^)YD9G<O &T2QG32XBNC]T=!E(U8:#LZ$T,FE^D5SNA1"Q)1F[8?F=
+MOR=*RHLG%B19EW.K^+O(Z.<=@8I?$T<><U13-TW]XUU5Z 8RYQKD(J+[0T>7
+M@50S.2[LDC5SX",;BD7JV$9*>AXB6S:]9D9R$_Z]MD19NV!^X1BI!GH&#!]T
+MD!D# 21^X1BI!GIRPF9?$T>HFR7+$R19!R#&AGR1R)&W,8Q1ET)QPS)(51IR
+M5Q])RAU]EAF<KJ<THCSZ.&/ 3Q%!,! \T;3EZ<5@8^D)2C=T+RB@^.I(!1^;
+MCXN'Y*-#3""WE!YSDW7LTO=>A![(%XGSTA*!.\,((7<$9Y@\@9^NT?>!];OE
+MY!HX6K4+QC2U9"$DEIUY'XG5M;PF@3EA/6/ 3Q&*HTKZ6Z1F$&&FQ[[RLCR%
+MA4)X4/B%L_!/E9 88N[G"1L]5[_P,?[)X;<@!@(O#6; )4O3C! X5"3MZUW\
+MU3ZG G-XJXGK%"AA;;( 9K:? [V$LQO9'X@@D%94;DKBA<(R1B-WX!<Z9.YD
+MY1/DLD0'T?=)GSY00!M':A%#L+2K>" VW48XQ!FTUVM<1<#F=4ML _<@@ 15
+M%9QVY(8>0AEGP#*.01]S0T5$LOV4KS'@R3)-)3!XPXGK=*'VMUDW[8_9?R"?
+MCQ<-3,#P 3V;0;A2QL0$ET7EZ<+ T=3Q#A_),W));! +OR>1W33-F4-VICKX
+MCSD:@FV,A0>%_RU^GB/H9\W5+.S9'&#H]5&4*E+Q!\[+WL9N_.QR'.WIC)0$
+M/00,+= 66($5:- ,+=#-3P5/Z(1...U"]M)@!ERR-%R9(0=KX!H^\DZVY%H_
+MS70;.I,$(0)!1U'G3@:/^(\R!S6RXS5((BA*PND7+SKOXAB*-9P'$6YR4':5
+M=2)91AWE\[7Q/[S-^4)R$$SE:4TU#UTD=A 4=>[SXEIJ-3M(@K-!<7^"5^6N
+M$;U#\KHD;9/P:Q#K,6GY!B*?CQ?P5(@A-T9\0^DZK_E%&D: Y&C@F)V\D_T4
+M$^7P#@)/T$+TX=9E<)SHH1Y]$4GH4>\(L1YPXEUEFJV6W_E[HJ2JI-.>008?
+M,R/SDB&E0_9/CSYEEQ<M('<"DHN#"T? 3Q%]'AXZ(OK,U!CBB%K*\<%&=1V4
+MKO/Q-"($;%[PA?Z)ONB&P@8(P 8(P 8(H!P(P 8(P 8(H!@(\ 8(\ 8(\,$(
+M, 8(, 8(D'#/=--R1OK(6(\^S&R[81VO!WD:\])@!ERR1$6_^]5XH1>7)B!U
+6JTKA=5]I *"4_\%4D\0&T1CB.!Q$ 1VO
+
+end
diff --git a/dmake/dbug/dbug/readme b/dmake/dbug/dbug/readme
new file mode 100644
index 000000000000..a69f34682276
--- /dev/null
+++ b/dmake/dbug/dbug/readme
@@ -0,0 +1,6 @@
+To unpack the DBUG manual page please issue the following sequence of
+commands:
+
+ uudecode dbug.uue
+ uncompress dbug.Z
+ mv dbug dbug.p
diff --git a/dmake/dbug/getwd.c b/dmake/dbug/getwd.c
new file mode 100644
index 000000000000..56e1a03ab7ca
--- /dev/null
+++ b/dmake/dbug/getwd.c
@@ -0,0 +1,6 @@
+char *
+getwd(pathname)
+char *pathname;
+{
+ return("delete this code if your getwd.c works correctly");
+}
diff --git a/dmake/dbug/malloc/_changes b/dmake/dbug/malloc/_changes
new file mode 100644
index 000000000000..888a47a8dfb5
--- /dev/null
+++ b/dmake/dbug/malloc/_changes
@@ -0,0 +1,9 @@
+I made the following changes to the malloc package as found in
+comp.sources.unix:
+
+ 1. created this file _changes.
+ 2. moved README to _readme (facilitates transfer to DOS and back to
+ unix)
+ 3. renamed testmalloc.c, malloc_chk.c, and malloc_chn.c to testmlc.c,
+ mlc_chk.c, and mlc_chn.c respectively. Again DOS has trouble with
+ long basenames in filenames.
diff --git a/dmake/dbug/malloc/_readme b/dmake/dbug/malloc/_readme
new file mode 100644
index 000000000000..b78b1fd6bbcd
--- /dev/null
+++ b/dmake/dbug/malloc/_readme
@@ -0,0 +1,133 @@
+# (c) Copyright 1990 Conor P. Cahill. (uunet!virtech!cpcahil)
+# You may copy, distribute, and use this software as long as this
+# copyright statement is not removed.
+
+This package is a collection of routines which are a drop-in replacement
+for the malloc(3), memory(3), string(3), and bstring(3) library functions.
+
+The purpose of these programs is to aid the development and/or debugging
+of programs using these functions by providing a high level of consistancy
+checking whenever a malloc pointer is used. Due to this increased
+level of consistancy checking, these functions have a considerably larger
+overhead than the standard functions, but the extra checking should be
+well worth it in a development environment.
+
+To use these functions all you need to do is compile the library and
+include it on your loader command line. You do not need to recompile
+your code, only a relink is necessary.
+
+Features of this library:
+
+ 1. The malloced area returned from each call to malloc is filled with
+ non-null bytes. This should catch any use of uninitialized malloc
+ area. The fill pattern for malloced area is 0x01.
+
+ 2. When free is called numerous validity checks are made on the
+ pointer it is passed. In addition, the data in the malloc block
+ beyound the size requested on the initial malloc is checked to
+ verify that it is still filled with the original fill characters.
+
+ This is usefull for catching things like:
+
+ ptr = malloc(5);
+ ptr[5] = '\0';
+
+ /*
+ * You should not that this will be caught when it is
+ * freed not when it is done
+ */
+
+ And finally, the freed block is filled with a different fill pattern
+ so that you can easily determine if you are still using free'd space.
+ The fill pattern for free'd areas is 0x02.
+
+ This is usefull for catching things like:
+
+ ptr = malloc(20);
+
+ bptr = ptr+10;
+
+ /* do something usefule with bptr */
+
+ free(ptr);
+
+ /*
+ * now try to do something useful with bptr, it should
+ * be trashed enough that it would cause real problems
+ * and when you went to debug the problem it would be
+ * filled with 0x02's and you would then know to look
+ * for something free'ing what bptr points to.
+ */
+
+
+ 3. Whenever a bstring(3)/string(3)/memory(3) function is called, it's
+ parameters are checked as follows:
+
+ If they point somewhere in the malloc arena
+ If the operation goes beyond requested malloc space
+ call malloc_warning()
+
+ This is usefull for catching things like:
+
+ ptr = malloc(5);
+ strcpy(ptr,"abcde");
+
+
+ 4. Malloc_warning() and malloc_fatal() are used when an error condition
+ is detected. If the error is severe, malloc_fatal is called.
+ Malloc_warning is used otherwise. The decision about what is fatal
+ and what is a warning was made somewhat arbitrarily.
+
+ Warning messages include:
+
+ Calling free with a bad pointer
+ Calling a bstring/string/memory (3) function which will go beyond
+ the end of a malloc block (Note that the library function is
+ not modified to refuse the operation. If malloc warnings are
+ in the default IGNORE case, the operation will continue and
+ at some point cause a real problem).
+
+ Fatal errors are:
+
+ Detectable corruption to the malloc chain.
+
+
+ 5. The operations to perform when an error is detected are specified at
+ run time by the use of environment variables.
+
+ MALLOC_WARN - specifies the warning error message handling
+ MALLOC_FATAL - specifies the fatal error handling
+
+
+ When one of these error conditions occur you will get an error
+ message and the handler will execute based upon what setting
+ is in the environment variables. Currently understood settings
+ are as follows:
+
+ 0 - continue operations
+ 1 - drop core and exit
+ 2 - just exit
+ 3 - drop core, but continue executing. Core files will
+ be placed into core.[PID].[counter] i.e: core.00123.001
+ 128 - dump malloc chain and continue
+ 129 - dump malloc chain, dump core, and exit
+ 130 - dump malloc chain, exit
+ 131 - dump malloc chain, dump core, continue processing
+
+
+ There is an additional environment variable MALLOC_ERRFILE which
+ is used to indicate the name of the file for error message output.
+
+ For example, to set up the session to generate a core file for
+ every malloc warning, to drop core and exit on a malloc fatal, and
+ to log all messages to the file "malloc_log" do the following:
+
+ MALLOC_WARN=131
+ MALLOC_FATAL=1
+ MALLOC_ERRFILE=malloc_log
+
+ export MALLOC_WARN MALLOC_FATAL MALLOC_ERRFILE
+
+ 6. The function malloc_dump() is available to dump the malloc chain whenever
+ you might want. It's only argument is a file descriptor to use to write
+ the data. Review the code if you need to know what data is printed.
diff --git a/dmake/dbug/malloc/calloc.c b/dmake/dbug/malloc/calloc.c
new file mode 100644
index 000000000000..6d1e0f84b626
--- /dev/null
+++ b/dmake/dbug/malloc/calloc.c
@@ -0,0 +1,91 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+#include <stdio.h>
+
+/*
+ * Function: calloc()
+ *
+ * Purpose: to allocate and nullify a data area
+ *
+ * Arguments: nelem - number of elements
+ * elsize - size of each element
+ *
+ * Returns: NULL - if malloc fails
+ * or pointer to allocated space
+ *
+ * Narrative: determine size of area to malloc
+ * malloc area.
+ * if malloc succeeds
+ * fill area with nulls
+ * return ptr to malloc'd region
+ */
+#ifndef lint
+static char rcs_header[] = "$Id: calloc.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $";
+#endif
+
+char *
+calloc(nelem,elsize)
+ unsigned int nelem;
+ unsigned int elsize;
+{
+ char * malloc();
+ char * memset();
+ char * ptr;
+ unsigned int size;
+
+ size = elsize * nelem;
+
+ if( (ptr = malloc(size)) != NULL)
+ {
+ (void) memset(ptr,'\0',(int)size);
+ }
+
+ return(ptr);
+}
+
+
+/*
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1 1997/09/22 14:51:10 hjs
+ * dmake 4.1 orginal sourcen
+ *
+ * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura
+ * dmake gold 4.1.00 initial import
+ *
+ * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura
+ * Dmake 4.1 Initial Import
+ *
+ * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura
+ * Initial import for final release of dmake 4.1
+ *
+ * Revision 1.1 1994/10/06 17:43:08 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1994/10/06 03:45:17 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1992/01/24 03:28:58 dvadura
+ * dmake Version 3.8, Initial revision
+ *
+ * Revision 1.6 90/05/11 00:13:07 cpcahil
+ * added copyright statment
+ *
+ * Revision 1.5 90/02/24 20:41:57 cpcahil
+ * lint changes.
+ *
+ * Revision 1.4 90/02/24 17:25:47 cpcahil
+ * changed $header to $id so full path isn't included.
+ *
+ * Revision 1.3 90/02/24 13:32:24 cpcahil
+ * added function header. moved log to end of file.
+ *
+ * Revision 1.2 90/02/22 23:08:26 cpcahil
+ * fixed rcs_header line
+ *
+ * Revision 1.1 90/02/22 23:07:38 cpcahil
+ * Initial revision
+ *
+ */
diff --git a/dmake/dbug/malloc/debug.h b/dmake/dbug/malloc/debug.h
new file mode 100644
index 000000000000..1a206d242936
--- /dev/null
+++ b/dmake/dbug/malloc/debug.h
@@ -0,0 +1,129 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+/************************************************************************/
+/* */
+/* this include sets up some macro functions which can be used while */
+/* debugging the program, and then left in the code, but turned of by */
+/* just not defining "DEBUG". This way your production version of */
+/* the program will not be filled with bunches of debugging junk */
+/* */
+/************************************************************************/
+/*
+ * $Id: debug.h,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $
+ */
+
+#ifdef DEBUG
+
+#if DEBUG == 1 /* if default level */
+#undef DEBUG
+#define DEBUG 100 /* use level 100 */
+#endif
+
+#include <stdio.h>
+
+#define DEBUG0(val,str)\
+ {\
+ if( DEBUG > val ) \
+ fprintf(stderr,"%s(%d): %s\n",\
+ __FILE__,__LINE__,str);\
+ }
+#define DEBUG1(val,str,a1)\
+ {\
+ char _debugbuf[100];\
+ if( DEBUG > val )\
+ {\
+ sprintf(_debugbuf,str,a1);\
+ fprintf(stderr,"%s(%d): %s\n",\
+ __FILE__,__LINE__,_debugbuf);\
+ }\
+ }
+
+#define DEBUG2(val,str,a1,a2)\
+ {\
+ char _debugbuf[100];\
+ if( DEBUG > val )\
+ {\
+ sprintf(_debugbuf,str,a1,a2);\
+ fprintf(stderr,"%s(%d): %s\n",\
+ __FILE__,__LINE__,_debugbuf);\
+ }\
+ }
+
+#define DEBUG3(val,str,a1,a2,a3)\
+ {\
+ char _debugbuf[100];\
+ if( DEBUG > val )\
+ {\
+ sprintf(_debugbuf,str,a1,a2,a3);\
+ fprintf(stderr,"%s(%d): %s\n",\
+ __FILE__,__LINE__,_debugbuf);\
+ }\
+ }
+
+#define DEBUG4(val,str,a1,a2,a3,a4)\
+ {\
+ char _debugbuf[100];\
+ if( DEBUG > val )\
+ {\
+ sprintf(_debugbuf,str,a1,a2,a3,a4);\
+ fprintf(stderr,"%s(%d): %s\n",\
+ __FILE__,__LINE__,_debugbuf);\
+ }\
+ }
+
+#define DEBUG5(val,str,a1,a2,a3,a4,a5)\
+ {\
+ char _debugbuf[100];\
+ if( DEBUG > val )\
+ {\
+ sprintf(_debugbuf,str,a1,a2,a3,a4,a5);\
+ fprintf(stderr,"%s(%d): %s\n",\
+ __FILE__,__LINE__,_debugbuf);\
+ }\
+ }
+
+#else
+
+#define DEBUG0(val,s)
+#define DEBUG1(val,s,a1)
+#define DEBUG2(val,s,a1,a2)
+#define DEBUG3(val,s,a1,a2,a3)
+#define DEBUG4(val,s,a1,a2,a3,a4)
+#define DEBUG5(val,s,a1,a2,a3,a4,a5)
+
+#endif /* DEBUG */
+
+
+/*
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1 1997/09/22 14:51:11 hjs
+ * dmake 4.1 orginal sourcen
+ *
+ * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura
+ * dmake gold 4.1.00 initial import
+ *
+ * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura
+ * Dmake 4.1 Initial Import
+ *
+ * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura
+ * Initial import for final release of dmake 4.1
+ *
+ * Revision 1.1 1994/10/06 17:43:09 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1994/10/06 03:45:18 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1992/01/24 03:28:59 dvadura
+ * dmake Version 3.8, Initial revision
+ *
+ * Revision 1.2 90/05/11 00:13:08 cpcahil
+ * added copyright statment
+ *
+ * Revision 1.1 90/02/23 07:09:01 cpcahil
+ * Initial revision
+ *
+ */
diff --git a/dmake/dbug/malloc/dump.c b/dmake/dbug/malloc/dump.c
new file mode 100644
index 000000000000..7ac79ccc884f
--- /dev/null
+++ b/dmake/dbug/malloc/dump.c
@@ -0,0 +1,142 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+#include <stdio.h>
+#include "malloc.h"
+#include "tostring.h"
+
+/*
+ * Function: malloc_dump()
+ *
+ * Purpose: to dump a printed copy of the malloc chain and
+ * associated data elements
+ *
+ * Arguments: fd - file descriptor to write data to
+ *
+ * Returns: nothing of any use
+ *
+ * Narrative: Just print out all the junk
+ *
+ * Notes: This function is implemented using low level calls because
+ * of the likelyhood that the malloc tree is damaged when it
+ * is called. (Lots of things in the c library use malloc and
+ * we don't want to get into a catch-22).
+ *
+ */
+
+#ifndef lint
+static
+char rcs_hdr[] = "$Id: dump.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $";
+#endif
+
+
+#define ERRSTR "I/O Error on malloc dump file descriptor\n"
+
+#define WRITEOUT(fd,str,len) if( write(fd,str,(unsigned)len) != len ) \
+ { \
+ (void) write(2,ERRSTR,\
+ (unsigned)strlen(ERRSTR));\
+ exit(120); \
+ }
+
+void
+malloc_dump(fd)
+ int fd;
+{
+ char buffer[512];
+ void exit();
+ int i;
+ extern char * malloc_data_end;
+ extern char * malloc_data_start;
+ extern struct mlist * malloc_end;
+ extern struct mlist malloc_start;
+ struct mlist * ptr;
+
+ WRITEOUT(fd,"MALLOC CHAIN:\n",14);
+ WRITEOUT(fd,"-------------------- START ----------------\n",44);
+
+ for(i=0; i < 80; i++)
+ {
+ buffer[i] = ' ';
+ }
+
+ for(ptr = &malloc_start; ptr; ptr = ptr->next)
+ {
+ (void) tostring(buffer, (int)ptr, 8, B_HEX, '0');
+ (void) tostring(buffer+9, (int)ptr->next, 8, B_HEX, '0');
+ (void) tostring(buffer+18, (int)ptr->prev, 8, B_HEX, '0');
+ (void) tostring(buffer+27, (int)ptr->flag, 10, B_HEX, '0');
+ (void) tostring(buffer+38, (int)ptr->s.size, 8, B_DEC, ' ');
+ (void) tostring(buffer+47, (int)ptr->s.size, 8, B_HEX, '0');
+ (void) tostring(buffer+57, (int)ptr->data, 8, B_HEX, '0');
+ buffer[46] = '(';
+ buffer[55] = ')';
+ buffer[65] = '\n';
+ WRITEOUT(fd,buffer,66);
+ }
+ WRITEOUT(fd,"-------------------- DONE -----------------\n",44);
+
+ WRITEOUT(fd,"Malloc start: ",19);
+ (void) tostring(buffer, (int) &malloc_start, 8, B_HEX, '0');
+ buffer[8] = '\n';
+ WRITEOUT(fd,buffer,9);
+
+ WRITEOUT(fd,"Malloc end: ", 19);
+ (void) tostring(buffer, (int) malloc_end, 8, B_HEX, '0');
+ buffer[8] = '\n';
+ WRITEOUT(fd,buffer,9);
+
+ WRITEOUT(fd,"Malloc data start: ", 19);
+ (void) tostring(buffer, (int) malloc_data_start, 8, B_HEX, '0');
+ buffer[8] = '\n';
+ WRITEOUT(fd,buffer,9);
+
+ WRITEOUT(fd,"Malloc data end: ", 19);
+ (void) tostring(buffer, (int) malloc_data_end, 8, B_HEX, '0');
+ buffer[8] = '\n';
+ WRITEOUT(fd,buffer,9);
+
+} /* malloc_dump(... */
+
+
+/*
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1 1997/09/22 14:51:11 hjs
+ * dmake 4.1 orginal sourcen
+ *
+ * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura
+ * dmake gold 4.1.00 initial import
+ *
+ * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura
+ * Dmake 4.1 Initial Import
+ *
+ * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura
+ * Initial import for final release of dmake 4.1
+ *
+ * Revision 1.1 1994/10/06 17:43:09 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1994/10/06 03:45:19 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1992/01/24 03:29:01 dvadura
+ * dmake Version 3.8, Initial revision
+ *
+ * Revision 1.5 90/08/29 21:22:37 cpcahil
+ * miscellaneous lint fixes
+ *
+ * Revision 1.4 90/05/11 00:13:08 cpcahil
+ * added copyright statment
+ *
+ * Revision 1.3 90/02/24 21:50:07 cpcahil
+ * lots of lint fixes
+ *
+ * Revision 1.2 90/02/24 17:27:48 cpcahil
+ * changed $header to $Id to remove full path from rcs id string
+ *
+ * Revision 1.1 90/02/22 23:17:43 cpcahil
+ * Initial revision
+ *
+ */
diff --git a/dmake/dbug/malloc/free.c b/dmake/dbug/malloc/free.c
new file mode 100644
index 000000000000..5eb139d6fcb8
--- /dev/null
+++ b/dmake/dbug/malloc/free.c
@@ -0,0 +1,206 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+#include <stdio.h>
+#include "malloc.h"
+#include "debug.h"
+
+/*
+ * Function: free()
+ *
+ * Purpose: to deallocate malloced data
+ *
+ * Arguments: ptr - pointer to data area to deallocate
+ *
+ * Returns: nothing of any value
+ *
+ * Narrative:
+ * verify pointer is within malloc region
+ * get mlist pointer from passed address
+ * verify magic number
+ * verify inuse flag
+ * verify pointer connections with surrounding segments
+ * turn off inuse flag
+ * verify no data overrun into non-malloced area at end of segment
+ * IF possible join segment with next segment
+ * IF possible join segment with previous segment
+ * Clear all data in segment (to make sure it isn't reused)
+ *
+ */
+#ifndef lint
+static
+char rcs_hdr[] = "$Id: free.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $";
+#endif
+
+void
+free(cptr)
+ char * cptr;
+{
+ char * func = "free";
+ int i;
+ extern int malloc_checking;
+ extern struct mlist * malloc_end;
+ extern int malloc_errno;
+ extern char * malloc_data_end;
+ extern char * malloc_data_start;
+ void malloc_join();
+ void malloc_memset();
+ struct mlist * oldptr;
+ struct mlist * ptr;
+
+ /*
+ * IF malloc chain checking is on, go do it.
+ */
+ if( malloc_checking )
+ {
+ (void) malloc_chain_check(1);
+ }
+
+ /*
+ * verify that cptr is within the malloc region...
+ */
+ if( cptr < malloc_data_start || cptr > malloc_data_end )
+ {
+ malloc_errno = M_CODE_BAD_PTR;
+ malloc_warning(func);
+ return;
+ }
+
+ /*
+ * convert pointer to mlist struct pointer. To do this we must
+ * move the pointer backwards the correct number of bytes...
+ */
+
+ ptr = (struct mlist *) (cptr - M_SIZE);
+
+ if( (ptr->flag&M_MAGIC) != M_MAGIC )
+ {
+ malloc_errno = M_CODE_BAD_MAGIC;
+ malloc_warning(func);
+ return;
+ }
+
+ if( ! (ptr->flag & M_INUSE) )
+ {
+ malloc_errno = M_CODE_NOT_INUSE;
+ malloc_warning(func);
+ return;
+ }
+
+ if( (ptr->prev && (ptr->prev->next != ptr) ) ||
+ (ptr->next && (ptr->next->prev != ptr) ) ||
+ ((ptr->next == NULL) && (ptr->prev == NULL)) )
+ {
+ malloc_errno = M_CODE_BAD_CONNECT;
+ malloc_warning(func);
+ return;
+ }
+
+ ptr->flag &= ~M_INUSE;
+
+ /*
+ * verify that the user did not overrun the requested number of bytes.
+ */
+ for(i=ptr->r_size; i < ptr->s.size; i++)
+ {
+ if( ptr->data[i] != M_FILL )
+ {
+ malloc_errno = M_CODE_OVERRUN;
+ malloc_warning(func);
+ break;
+ }
+ }
+
+ DEBUG3(10,"pointers: prev: 0x%.7x, ptr: 0x%.7x, next: 0x%.7x",
+ ptr->prev, ptr, ptr->next);
+
+ DEBUG3(10,"size: prev: %9d, ptr: %9d, next: %9d",
+ ptr->prev->s.size, ptr->s.size, ptr->next->s.size);
+
+ DEBUG3(10,"flags: prev: 0x%.7x, ptr: 0x%.7x, next: 0x%.7x",
+ ptr->prev->flag, ptr->flag, ptr->next->flag);
+
+ /*
+ * check to see if this block can be combined with the next and/or
+ * previous block. Since it may be joined with the previous block
+ * we will save a pointer to the previous block and test to verify
+ * if it is joined (it's next ptr will no longer point to ptr).
+ */
+ malloc_join(ptr,ptr->next,0,0);
+
+ oldptr = ptr->prev;
+
+ malloc_join(ptr->prev, ptr,0,0);
+
+ if( oldptr->next != ptr )
+ {
+ DEBUG0(10,"Oldptr was changed");
+ ptr = oldptr;
+ }
+
+ /*
+ * fill this block with '\02's to ensure that nobody is using a
+ * pointer to already freed data...
+ */
+ malloc_memset(ptr->data,M_FREE_FILL,(int)ptr->s.size);
+
+}
+
+/*
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1 1997/09/22 14:51:11 hjs
+ * dmake 4.1 orginal sourcen
+ *
+ * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura
+ * dmake gold 4.1.00 initial import
+ *
+ * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura
+ * Dmake 4.1 Initial Import
+ *
+ * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura
+ * Initial import for final release of dmake 4.1
+ *
+ * Revision 1.1 1994/10/06 17:43:10 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1994/10/06 03:45:19 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1992/01/24 03:29:02 dvadura
+ * dmake Version 3.8, Initial revision
+ *
+ * Revision 1.9 90/08/29 21:22:48 cpcahil
+ * miscellaneous lint fixes
+ *
+ * Revision 1.8 90/05/11 00:13:08 cpcahil
+ * added copyright statment
+ *
+ * Revision 1.7 90/02/25 11:00:18 cpcahil
+ * added support for malloc chain checking.
+ *
+ * Revision 1.6 90/02/24 21:50:18 cpcahil
+ * lots of lint fixes
+ *
+ * Revision 1.5 90/02/24 17:29:13 cpcahil
+ * changed $Header to $Id so full path wouldnt be included as part of rcs
+ * id string
+ *
+ * Revision 1.4 90/02/24 15:15:32 cpcahil
+ * 1. changed ALREADY_FREE errno to NOT_INUSE so that the same errno could
+ * be used by both free and realloc (since it was the same error).
+ * 2. fixed coding bug
+ *
+ * Revision 1.3 90/02/24 14:23:45 cpcahil
+ * fixed malloc_warning calls
+ *
+ * Revision 1.2 90/02/24 13:59:10 cpcahil
+ * added function header.
+ * Modified calls to malloc_warning/malloc_fatal to use new code error messages
+ * Added support for malloc_errno setting of error codes.
+ *
+ * Revision 1.1 90/02/22 23:17:43 cpcahil
+ * Initial revision
+ *
+ */
diff --git a/dmake/dbug/malloc/m_init.c b/dmake/dbug/malloc/m_init.c
new file mode 100644
index 000000000000..cef558319340
--- /dev/null
+++ b/dmake/dbug/malloc/m_init.c
@@ -0,0 +1,121 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+#include <stdio.h>
+#include "malloc.h"
+
+/*
+ * Function: malloc_init()
+ *
+ * Purpose: to initialize the pointers and variables use by the
+ * malloc() debugging library
+ *
+ * Arguments: none
+ *
+ * Returns: nothing of any value
+ *
+ * Narrative: Just initialize all the needed variables. Use mallopt
+ * to set options taken from the environment.
+ *
+ */
+#ifndef lint
+static
+char rcs_hdr[] = "$Id: m_init.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $";
+#endif
+
+void
+malloc_init()
+{
+ char * cptr;
+ char * getenv();
+ union malloptarg m;
+ extern char * malloc_data_end;
+ extern char * malloc_data_start;
+ extern struct mlist * malloc_end;
+ extern struct mlist malloc_start;
+ char * sbrk();
+
+ /*
+ * If already initialized...
+ */
+ if( malloc_data_start != (char *) 0)
+ {
+ return;
+ }
+
+
+ malloc_data_start = sbrk(0);
+ malloc_data_end = malloc_data_start;
+ malloc_start.s.size = 0;
+ malloc_end = &malloc_start;
+
+ if( (cptr=getenv("MALLOC_WARN")) != NULL )
+ {
+ m.i = atoi(cptr);
+ (void) mallopt(MALLOC_WARN,m);
+ }
+
+ if( (cptr=getenv("MALLOC_FATAL")) != NULL)
+ {
+ m.i = atoi(cptr);
+ (void) mallopt(MALLOC_FATAL,m);
+ }
+
+ if( (cptr=getenv("MALLOC_CKCHAIN")) != NULL)
+ {
+ m.i = atoi(cptr);
+ (void) mallopt(MALLOC_CKCHAIN,m);
+ }
+
+ if( (cptr=getenv("MALLOC_ERRFILE")) != NULL)
+ {
+ m.str = cptr;
+ (void) mallopt(MALLOC_ERRFILE,m);
+ }
+
+}
+
+/*
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1 1997/09/22 14:51:11 hjs
+ * dmake 4.1 orginal sourcen
+ *
+ * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura
+ * dmake gold 4.1.00 initial import
+ *
+ * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura
+ * Dmake 4.1 Initial Import
+ *
+ * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura
+ * Initial import for final release of dmake 4.1
+ *
+ * Revision 1.1 1994/10/06 17:43:11 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1994/10/06 03:45:20 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1992/01/24 03:29:03 dvadura
+ * dmake Version 3.8, Initial revision
+ *
+ * Revision 1.6 90/08/29 22:23:21 cpcahil
+ * fixed mallopt to use a union as an argument.
+ *
+ * Revision 1.5 90/08/29 21:22:50 cpcahil
+ * miscellaneous lint fixes
+ *
+ * Revision 1.4 90/05/11 15:53:35 cpcahil
+ * fixed bug in initialization code.
+ *
+ * Revision 1.3 90/05/11 00:13:08 cpcahil
+ * added copyright statment
+ *
+ * Revision 1.2 90/02/24 21:50:20 cpcahil
+ * lots of lint fixes
+ *
+ * Revision 1.1 90/02/24 17:10:53 cpcahil
+ * Initial revision
+ *
+ */
diff --git a/dmake/dbug/malloc/m_perror.c b/dmake/dbug/malloc/m_perror.c
new file mode 100644
index 000000000000..ad582acea37c
--- /dev/null
+++ b/dmake/dbug/malloc/m_perror.c
@@ -0,0 +1,111 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+
+#ifndef lint
+static
+char rcsid[] = "$Id: m_perror.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $";
+#endif
+
+/*
+ * malloc errno error strings...
+ */
+
+char *malloc_err_strings[] =
+{
+ "No errors",
+ "Malloc chain is corrupted, pointers out of order",
+ "Malloc chain is corrupted, end before end pointer",
+ "Pointer is not within malloc area",
+ "Malloc region does not have valid magic number in header",
+ "Pointers between this segment and ajoining segments are invalid",
+ "Data has overrun beyond requested number of bytes",
+ "Data in free'd area has been modified",
+ "Data are is not in use (can't be freed or realloced)",
+ "Unable to get additional memory from the system",
+ "Pointer within malloc region, but outside of malloc data bounds",
+ (char *) 0
+};
+
+/*
+ * Function: malloc_perror()
+ *
+ * Purpose: to print malloc_errno error message
+ *
+ * Arguments: str - string to print with error message
+ *
+ * Returns: nothing of any value
+ *
+ * Narrative:
+ */
+void
+malloc_perror(str)
+ char * str;
+{
+ extern int malloc_errno;
+ register char * s;
+ register char * t;
+
+ if( str && *str)
+ {
+ for(s=str; *s; s++)
+ {
+ /* do nothing */;
+ }
+
+ (void) write(2,str,(unsigned)(s-str));
+ (void) write(2,": ",(unsigned)2);
+ }
+
+ t = malloc_err_strings[malloc_errno];
+
+ for(s=t; *s; s++)
+ {
+ /* do nothing */;
+ }
+
+ (void) write(2,t,(unsigned)(s-t));
+
+ (void) write(2,"\n",(unsigned)1);
+}
+
+/*
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1 1997/09/22 14:51:11 hjs
+ * dmake 4.1 orginal sourcen
+ *
+ * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura
+ * dmake gold 4.1.00 initial import
+ *
+ * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura
+ * Dmake 4.1 Initial Import
+ *
+ * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura
+ * Initial import for final release of dmake 4.1
+ *
+ * Revision 1.1 1994/10/06 17:43:12 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1994/10/06 03:45:21 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1992/01/24 03:29:04 dvadura
+ * dmake Version 3.8, Initial revision
+ *
+ * Revision 1.5 90/08/29 21:25:08 cpcahil
+ * added additional error message that was missing (and
+ * caused a core dump)
+ *
+ * Revision 1.4 90/05/11 00:13:08 cpcahil
+ * added copyright statment
+ *
+ * Revision 1.3 90/02/24 21:50:21 cpcahil
+ * lots of lint fixes
+ *
+ * Revision 1.2 90/02/24 17:39:55 cpcahil
+ * 1. added function header
+ * 2. added rcs id and log strings.
+ *
+ */
diff --git a/dmake/dbug/malloc/makefile b/dmake/dbug/malloc/makefile
new file mode 100644
index 000000000000..88395c7b8f6c
--- /dev/null
+++ b/dmake/dbug/malloc/makefile
@@ -0,0 +1,77 @@
+#
+# (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+# You may copy, distribute, and use this software as long as this
+# copyright statement is not removed.
+#
+#
+# This is the Makefile for the malloc debugging library
+#
+# $Id: makefile,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $
+#
+CC=cc
+# for System V systems use this CFLAGS
+#CFLAGS=-g -DSYS5
+# else for BSD use:
+#CFLAGS=-g
+LINT=lint
+SHARCMD=shar -o mallocshar -l50 -x -a -n Malloclib
+SHELL=/bin/sh
+
+LIB=libmalloc.a
+
+SRCS= malloc.c \
+ free.c \
+ realloc.c \
+ calloc.c \
+ string.c \
+ mlc_chk.c \
+ mlc_chn.c \
+ memory.c \
+ tostring.c \
+ m_perror.c \
+ m_init.c \
+ mallopt.c \
+ dump.c
+
+OBJS= malloc.o \
+ free.o \
+ realloc.o \
+ calloc.o \
+ string.o \
+ mlc_chk.o \
+ mlc_chn.o \
+ memory.o \
+ tostring.o \
+ m_perror.o \
+ m_init.o \
+ mallopt.o \
+ dump.o
+
+TESTS=testmlc testmem
+
+all: $(LIB) $(TESTS)
+
+clean:
+ rm -f $(TESTS) pgm $(LIB) *.o *.ln
+
+sharfile:
+ $(SHARCMD) Makefile README patchlevel *.[ch3]
+
+$(LIB): $(OBJS)
+ ar ru $(LIB) $(OBJS)
+ -if test -s /bin/ranlib; then /bin/ranlib $(LIB); else exit 0; fi
+ -if test -s /usr/bin/ranlib; then /usr/bin/ranlib $(LIB); else exit 0; fi
+
+testmlc: $(LIB) testmlc.o
+ $(CC) -o $@ testmlc.o $(LIB)
+
+testmem: $(LIB) testmem.o
+ $(CC) -o $@ testmem.o $(LIB)
+
+lint:
+ $(LINT) $(CFLAGS) $(SRCS) testmlc.c testmem.c
+
+
+$(OBJS): malloc.h
+
+tostring.o malloc.o dump.o: tostring.h
diff --git a/dmake/dbug/malloc/malloc.3 b/dmake/dbug/malloc/malloc.3
new file mode 100644
index 000000000000..f5e1d2dc0dab
--- /dev/null
+++ b/dmake/dbug/malloc/malloc.3
@@ -0,0 +1,223 @@
+.TH MALLOC 3 "" "" "1.0"
+.ds ]T
+.\"/*
+.\" * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+.\" * You may copy, distribute, and use this software as long as this
+.\" * copyright statement is not removed.
+.\" */
+.\" $Id: malloc.3,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $
+.SH NAME
+malloc \t- debugging malloc library
+.SH SYNOPSIS
+.ft B
+.nf
+#include <malloc.h>
+
+char * calloc(nelem,elsize);
+void free(ptr);
+char * malloc(size);
+int malloc_chain_check(flag);
+void malloc_dump(fd);
+int mallopt(cmd,val)
+char * realloc(ptr,size);
+
+int cmd,fd,flag;
+unsigned elsize,nelem,size;
+char * ptr;
+union malloptarg val;
+
+.fi
+.ft R
+.SH DESCRIPTION
+This malloc library is a replacement for the standard library to be used
+during software development/debugging. See the standard malloc(3) pages
+for more information on the use of the following functions:
+.nf
+.in +.5i
+calloc(), free(), malloc(), realloc()
+.in -.5i
+.fi
+.sp
+This library differs from the standard malloc library in the
+following ways:
+.P
+1. Each malloc segment contains a magic number so that free can
+verify that the pointer passed points to a valid malloc segment.
+.P
+2. Each malloc segment is filled with a non-zero pattern so that code that
+depends upon malloc segments being null will fail.
+.P
+3. The size of each segment will be at least 1 byte larger than requested
+and the extra bytes will be filled with a non-zero pattern. When free is
+called, it will verify that you did not go beyond the number of bytes
+you asked for.
+.P
+4. When a segment is freed, it will be filled with a different non-zero pattern
+to ensure that the program doesn't depend upon the use of already freed data.
+.P
+5. Whenever any of the string or memory functions (str*, b*, mem*) are
+called with a pointer that is within the malloc arena, the operation is
+checked to verify that it does not overrun the malloced segment. A failure
+of this check is considered a "warning level error" (described later) and
+is handled accordingly.
+.P
+7. Run time checking can include verification of the malloc chain at each
+and every call to one of the malloc functions or manually by calling the
+malloc_chain_check function.
+.P
+6. When a problem is found, the action taken is specified at runtime by
+environment variables or at compile time by the use of the mallopt()
+function.
+.P
+There are two arbitrary levels of errors, warning and fatal, that this
+library will detect. They are broken down as follows:
+.P
+.nf
+.in +.25i
+Warning messages include:
+.sp
+.in +.5i
+.ti -.25i
+Calling free with a bad pointer
+.br
+.ti -.25i
+Calling a bstring/string/memory (3) function which will go beyond
+the end of a malloc block. Note that the library function is
+not modified to refuse the operation.
+.sp
+.in -.5i
+Fatal errors are:
+.in +.5i
+.ti -.25i
+Detectable corruption to the malloc chain.
+.in -.5i
+.in -.25i
+.P
+The error handling for each level (warning or fatal) are specified using
+environment variables or mallopt(). The coding for the error handling is
+as follows:
+.sp
+.nf
+.in +.5i
+.ti -.25i
+ 0 - continue operations
+.ti -.25i
+ 1 - drop core and exit
+.ti -.25i
+ 2 - just exit
+.ti -.25i
+ 3 - drop core, but continue executing. Core files will
+be placed into core.[PID].[counter] i.e: core.00123.001
+.ti -.25i
+128 - dump malloc chain and continue
+.ti -.25i
+129 - dump malloc chain, dump core, and exit
+.ti -.25i
+130 - dump malloc chain, exit
+.ti -.25i
+131 - dump malloc chain, dump core, continue processing
+.in -.5i
+.P
+In addition error messages can be placed into an error file.
+.P
+\fBmalloc_opt\fP() is used to set the malloc debugging options. The
+following options can be set:
+.br
+.sp
+.in +.5i
+MALLOC_WARN - set the error handling for warning level errors. \fBval.i\fP is
+an integer that can contain any one of the following values:
+.sp
+.in +.5i
+M_HANDLE_IGNORE - ignore error
+.br
+M_HANDLE_ABORT - drop core and exit
+.br
+M_HANDLE_EXIT - just exit (no core drop)
+.br
+M_HANDLE_CORE - drop core, but keep on going
+.br
+.in -.5i
+.sp
+In addition, M_HANDLE_DUMP may be or'd in to cause a dump of the current
+malloc chain.
+.br
+.sp
+MALLOC_FATAL - set the error handling for fatal level errors. \fBval.i\fP is
+equivalent to \fBval.i\fP for MALLOC_WARN.
+.br
+.sp
+MALLOC_ERRFILE - set the destination for malloc error messages. \fBval.str\fP
+is a pointer to a character string containing the name of the file to be used
+for error messages.
+.br
+.sp
+MALLOC_CKCHAIN - set the malloc chain checking flag. If \fBval.i\fP is
+non-zero, chain checking at every call to malloc is turned on.
+.br
+.sp
+For example, to set up the session to generate a core file for
+every malloc warning, to drop core and exit on a malloc fatal, and
+to log all messages to the file "malloc_log" do the following:
+.sp
+.nf
+.in +.5i
+#include <malloc.h>
+malloc_opt(MALLOC_WARN,131);
+malloc_opt(MALLOC_FATAL,1);
+malloc_opt(MALLOC_ERRFILE,"malloc_log");
+.in -.5i
+.fi
+.in -.5i
+.sp
+\fBmalloc_opt\fP() can be used to set/alter the debugging options at any
+time.
+.P
+\fBmalloc_dump\fP() will dump a table of the malloc arena showing all
+allocated/freed segments and the first few bytes of data in each segment.
+\fBfd\fP is the file descriptor to write the data to.
+.P
+\fBmalloc_chain_check\fP() will check the status of the malloc arena.
+If \fBflag\fP is non-zero, an error found in the chain will cause a
+fatal error. \fBmalloc_chain_check\fP() returns zero when there are no
+problems found in the malloc chain, non-zero otherwise.
+.SH "ENVIRONMENT VARIABLES"
+Environment variables can be used to control error handling, error logging
+and malloc chain checking at run time. The following environment variables
+are used:
+.P
+MALLOC_WARN - specifies the error handling for warning errors
+.br
+MALLOC_FATAL - specifies the error handling for fatal errors
+.br
+MALLOC_ERRFILE - specifies the error log file for error messages.
+.br
+MALLOC_CKCHAIN - if 1, turns on malloc chain checking at every call to any
+of the malloc functions.
+.P
+For example, to set up the session to generate a core file for
+every malloc warning, to drop core and exit on a malloc fatal, and
+to log all messages to the file "malloc_log" do the following:
+.sp
+.nf
+.in +.5i
+MALLOC_WARN=131
+MALLOC_FATAL=1
+MALLOC_ERRFILE=malloc_log
+
+export MALLOC_WARN MALLOC_FATAL MALLOC_ERRFILE
+.in -.5i
+.fi
+.SH WARNINGS
+This malloc library and it's associated string and memory functions are
+much less efficient than the standard functions due in part to the extra
+error checking. You do not want to use this library when generating a
+production (i.e. releasable) version of your software. It should only
+be used during development and testing.
+.SH SEE ALSO
+stat(2)
+.SH AUTHOR
+Conor P. Cahill
+Virtual Technologies Incorporated
+.sp
+uunet!virtech!cpcahil
diff --git a/dmake/dbug/malloc/malloc.c b/dmake/dbug/malloc/malloc.c
new file mode 100644
index 000000000000..e2f060f1d0ac
--- /dev/null
+++ b/dmake/dbug/malloc/malloc.c
@@ -0,0 +1,672 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+#include <stdio.h>
+#include <fcntl.h>
+#include "malloc.h"
+#include "tostring.h"
+
+/*
+ * Function: malloc()
+ *
+ * Purpose: memory allocator
+ *
+ * Arguments: size - size of data area needed
+ *
+ * Returns: pointer to allocated area, or NULL if unable
+ * to allocate addtional data.
+ *
+ * Narrative:
+ *
+ */
+#ifndef lint
+static
+char rcs_hdr[] = "$Id: malloc.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $";
+#endif
+
+extern int malloc_checking;
+char * malloc_data_start;
+char * malloc_data_end;
+struct mlist * malloc_end;
+int malloc_errfd = 2;
+int malloc_errno;
+int malloc_fatal_level = M_HANDLE_CORE;
+struct mlist malloc_start;
+int malloc_warn_level;
+void malloc_memset();
+
+char *
+malloc(size)
+ unsigned int size;
+{
+ char * func = "malloc";
+ char * getenv();
+ void malloc_fatal();
+ void malloc_init();
+ void malloc_split();
+ void malloc_warning();
+ unsigned int need;
+ struct mlist * oldptr;
+ struct mlist * ptr;
+ char * sbrk();
+
+ /*
+ * If this is the first call to malloc...
+ */
+ if( malloc_data_start == (char *) 0 )
+ {
+ malloc_init();
+ }
+
+ /*
+ * If malloc chain checking is on, go do it.
+ */
+ if( malloc_checking )
+ {
+ (void) malloc_chain_check(1);
+ }
+
+ /*
+ * always make sure there is at least on extra byte in the malloc
+ * area so that we can verify that the user does not overrun the
+ * data area.
+ */
+ size++;
+
+ /*
+ * Now look for a free area of memory of size bytes...
+ */
+ oldptr = NULL;
+ for(ptr = &malloc_start; ; ptr = ptr->next)
+ {
+ /*
+ * Since the malloc chain is a forward only chain, any
+ * pointer that we get should always be positioned in
+ * memory following the previous pointer. If this is not
+ * so, we must have a corrupted chain.
+ */
+ if( ptr )
+ {
+ if( ptr<oldptr )
+ {
+ malloc_errno = M_CODE_CHAIN_BROKE;
+ malloc_fatal(func);
+ return(NULL);
+ }
+ oldptr = ptr;
+ }
+ else if( oldptr != malloc_end )
+ {
+ /*
+ * This should never happen. If it does, then
+ * we got a real problem.
+ */
+ malloc_errno = M_CODE_NO_END;
+ malloc_fatal(func);
+ return(NULL);
+ }
+
+
+ /*
+ * if this element is already in use...
+ */
+ if( ptr && ((ptr->flag & M_INUSE) != 0) )
+ {
+ continue;
+ }
+
+ /*
+ * if there isn't room for this block..
+ */
+ if( ptr && (ptr->s.size < size) )
+ {
+ continue;
+ }
+
+ /*
+ * If ptr is null, we have run out of memory and must sbrk more
+ */
+ if( ptr == NULL )
+ {
+ need = (size + M_SIZE) * (size > 10*1024 ? 1:2);
+ if( need < M_BLOCKSIZE )
+ {
+ need = M_BLOCKSIZE;
+ }
+ else if( need & (M_BLOCKSIZE-1) )
+ {
+ need &= ~(M_BLOCKSIZE-1);
+ need += M_BLOCKSIZE;
+ }
+ ptr = (struct mlist *) sbrk((int)need);
+ if( ptr == (struct mlist *) -1 )
+ {
+ malloc_errno = M_CODE_NOMORE_MEM;
+ malloc_fatal(func);
+ }
+ malloc_data_end = sbrk((int)0);
+
+ ptr->prev = oldptr;
+ ptr->next = (struct mlist *) 0;
+ ptr->s.size = need - M_SIZE;
+ ptr->flag = M_MAGIC;
+
+ oldptr->next = ptr;
+ malloc_end = ptr;
+
+
+ } /* if( ptr ==... */
+
+ /*
+ * Now ptr points to a memory location that can store
+ * this data, so lets go to work.
+ */
+
+ ptr->r_size = size; /* save requested size */
+ ptr->flag |= M_INUSE;
+
+ /*
+ * split off unneeded data area in this block, if possible...
+ */
+ malloc_split(ptr);
+
+ /*
+ * re-adjust the requested size so that it is what the user
+ * actually requested...
+ */
+
+ ptr->r_size--;
+
+ /*
+ * just to make sure that noone is misusing malloced
+ * memory without initializing it, lets set it to
+ * all '\01's. We call local_memset() because memset()
+ * may be checking for malloc'd ptrs and this isn't
+ * a malloc'd ptr yet.
+ */
+ malloc_memset(ptr->data,M_FILL,(int)ptr->s.size);
+
+ return( ptr->data);
+
+ } /* for(... */
+
+} /* malloc(... */
+
+/*
+ * Function: malloc_split()
+ *
+ * Purpose: to split a malloc segment if there is enough room at the
+ * end of the segment that isn't being used
+ *
+ * Arguments: ptr - pointer to segment to split
+ *
+ * Returns: nothing of any use.
+ *
+ * Narrative:
+ * get the needed size of the module
+ * round the size up to appropriat boundry
+ * calculate amount of left over space
+ * if there is enough left over space
+ * create new malloc block out of remainder
+ * if next block is free
+ * join the two blocks together
+ * fill new empty block with free space filler
+ * re-adjust pointers and size of current malloc block
+ *
+ *
+ *
+ * Mod History:
+ * 90/01/27 cpcahil Initial revision.
+ */
+void
+malloc_split(ptr)
+ struct mlist * ptr;
+{
+ extern struct mlist * malloc_end;
+ void malloc_join();
+ int rest;
+ int size;
+ struct mlist * tptr;
+
+ size = ptr->r_size;
+
+ /*
+ * roundup size to the appropriate boundry
+ */
+
+ M_ROUNDUP(size);
+
+ /*
+ * figure out how much room is left in the array.
+ * if there is enough room, create a new mlist
+ * structure there.
+ */
+
+ if( ptr->s.size > size )
+ {
+ rest = ptr->s.size - size;
+ }
+ else
+ {
+ rest = 0;
+ }
+
+ if( rest > (M_SIZE+M_RND) )
+ {
+ tptr = (struct mlist *) (ptr->data+size);
+ tptr->prev = ptr;
+ tptr->next = ptr->next;
+ tptr->flag = M_MAGIC;
+ tptr->s.size = rest - M_SIZE;
+
+ /*
+ * If possible, join this segment with the next one
+ */
+
+ malloc_join(tptr, tptr->next,0,0);
+
+ if( tptr->next )
+ {
+ tptr->next->prev = tptr;
+ }
+
+ malloc_memset(tptr->data,M_FREE_FILL, (int)tptr->s.size);
+
+ ptr->next = tptr;
+ ptr->s.size = size;
+
+ if( malloc_end == ptr )
+ {
+ malloc_end = tptr;
+ }
+ }
+
+} /* malloc_split(... */
+
+/*
+ * Function: malloc_join()
+ *
+ * Purpose: to join two malloc segments together (if possible)
+ *
+ * Arguments: ptr - pointer to segment to join to.
+ * nextptr - pointer to next segment to join to ptr.
+ *
+ * Returns: nothing of any values.
+ *
+ * Narrative:
+ *
+ * Mod History:
+ * 90/01/27 cpcahil Initial revision.
+ */
+void
+malloc_join(ptr,nextptr, inuse_override, fill_flag)
+ struct mlist * ptr;
+ struct mlist * nextptr;
+ int inuse_override;
+ int fill_flag;
+{
+ unsigned int newsize;
+
+ if( ptr && ! (inuse_override || (ptr->flag & M_INUSE)) &&
+ nextptr && ! (nextptr->flag & M_INUSE) &&
+ ((ptr->data+ptr->s.size) == (char *) nextptr) )
+ {
+ if( malloc_end == nextptr )
+ {
+ malloc_end = ptr;
+ }
+ ptr->next = nextptr->next;
+ newsize = nextptr->s.size + M_SIZE;
+
+ /*
+ * if we are to fill and this segment is in use,
+ * fill in with M_FILL newly added space...
+ */
+
+ if(fill_flag && (ptr->flag & M_INUSE) )
+ {
+ malloc_memset(ptr->data+ptr->s.size,
+ M_FILL, (int)(nextptr->s.size + M_SIZE));
+ }
+
+ ptr->s.size += newsize;
+ if( ptr->next )
+ {
+ ptr->next->prev = ptr;
+ }
+ }
+
+} /* malloc_join(... */
+
+
+/*
+ * The following mess is just to ensure that the versions of these functions in
+ * the current library are included (to make sure that we don't accidentaly get
+ * the libc versions. (This is the lazy man's -u ld directive)
+ */
+
+void free();
+int strcmp();
+int memcmp();
+char * realloc();
+
+void (*malloc_void_funcs[])() =
+{
+ free,
+};
+
+int (*malloc_int_funcs[])() =
+{
+ strcmp,
+ memcmp,
+};
+
+char * (*malloc_char_star_funcs[])() =
+{
+ realloc,
+};
+
+/*
+ * This is malloc's own memset which is used without checking the parameters.
+ */
+
+void
+malloc_memset(ptr,byte,len)
+ char * ptr;
+ char byte;
+ int len;
+{
+
+ while(len-- > 0)
+ {
+ *ptr++ = byte;
+ }
+
+} /* malloc_memset(... */
+
+/*
+ * Function: malloc_fatal()
+ *
+ * Purpose: to display fatal error message and take approrpriate action
+ *
+ * Arguments: funcname - name of function calling this routine
+ *
+ * Returns: nothing of any value
+ *
+ * Narrative:
+ *
+ * Notes: This routine does not make use of any libc functions to build
+ * and/or disply the error message. This is due to the fact that
+ * we are probably at a point where malloc is having a real problem
+ * and we don't want to call any function that may use malloc.
+ */
+void
+malloc_fatal(funcname)
+ char * funcname;
+{
+ char errbuf[128];
+ void exit();
+ void malloc_err_handler();
+ extern char * malloc_err_strings[];
+ extern int malloc_errno;
+ extern int malloc_fatal_level;
+ char * s;
+ char * t;
+
+ s = errbuf;
+ t = "Fatal error: ";
+ while( *s = *t++)
+ {
+ s++;
+ }
+ t = funcname;
+ while( *s = *t++)
+ {
+ s++;
+ }
+
+ t = "(): ";
+ while( *s = *t++)
+ {
+ s++;
+ }
+
+ t = malloc_err_strings[malloc_errno];
+ while( *s = *t++)
+ {
+ s++;
+ }
+
+ *(s++) = '\n';
+
+ if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))
+ {
+ (void) write(2,"I/O error to error file\n",(unsigned)24);
+ exit(110);
+ }
+ malloc_err_handler(malloc_fatal_level);
+
+} /* malloc_fatal(... */
+
+/*
+ * Function: malloc_warning()
+ *
+ * Purpose: to display warning error message and take approrpriate action
+ *
+ * Arguments: funcname - name of function calling this routine
+ *
+ * Returns: nothing of any value
+ *
+ * Narrative:
+ *
+ * Notes: This routine does not make use of any libc functions to build
+ * and/or disply the error message. This is due to the fact that
+ * we are probably at a point where malloc is having a real problem
+ * and we don't want to call any function that may use malloc.
+ */
+void
+malloc_warning(funcname)
+ char * funcname;
+{
+ char errbuf[128];
+ void exit();
+ void malloc_err_handler();
+ extern char * malloc_err_strings[];
+ extern int malloc_errno;
+ extern int malloc_warn_level;
+ char * s;
+ char * t;
+
+ s = errbuf;
+ t = "Warning: ";
+ while( *s = *t++)
+ {
+ s++;
+ }
+ t = funcname;
+ while( *s = *t++)
+ {
+ s++;
+ }
+
+ t = "(): ";
+ while( *s = *t++)
+ {
+ s++;
+ }
+
+ t = malloc_err_strings[malloc_errno];
+ while( *s = *t++)
+ {
+ s++;
+ }
+
+ *(s++) = '\n';
+
+ if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))
+ {
+ (void) write(2,"I/O error to error file\n",(unsigned)24);
+ exit(110);
+ }
+
+ malloc_err_handler(malloc_warn_level);
+
+} /* malloc_warning(... */
+
+/*
+ * Function: malloc_err_handler()
+ *
+ * Purpose: to take the appropriate action for warning and/or fatal
+ * error conditions.
+ *
+ * Arguments: level - error handling level
+ *
+ * Returns: nothing of any value
+ *
+ * Narrative:
+ *
+ * Notes: This routine does not make use of any libc functions to build
+ * and/or disply the error message. This is due to the fact that
+ * we are probably at a point where malloc is having a real problem
+ * and we don't want to call any function that may use malloc.
+ */
+void
+malloc_err_handler(level)
+{
+ void exit();
+ void malloc_dump();
+ extern int malloc_errfd;
+
+ if( level & M_HANDLE_DUMP )
+ {
+ malloc_dump(malloc_errfd);
+ }
+
+ switch( level & ~M_HANDLE_DUMP )
+ {
+ /*
+ * If we are to drop a core file and exit
+ */
+ case M_HANDLE_ABORT:
+ (void) abort();
+ break;
+
+ /*
+ * If we are to exit..
+ */
+ case M_HANDLE_EXIT:
+ exit(200);
+ break;
+
+#ifndef __MSDOS__
+ /*
+ * If we are to dump a core, but keep going on our merry way
+ */
+ case M_HANDLE_CORE:
+ {
+ int pid;
+
+ /*
+ * fork so child can abort (and dump core)
+ */
+ if( (pid = fork()) == 0 )
+ {
+ (void) write(2,"Child dumping core\n",
+ (unsigned)9);
+ (void) abort();
+ }
+
+ /*
+ * wait for child to finish dumping core
+ */
+ while( wait((int *)0) != pid)
+ {
+ }
+
+ /*
+ * Move core file to core.pid.cnt so
+ * multiple cores don't overwrite each
+ * other.
+ */
+ if( access("core",0) == 0 )
+ {
+ static int corecnt;
+ char filenam[32];
+ filenam[0] = 'c';
+ filenam[1] = 'o';
+ filenam[2] = 'r';
+ filenam[3] = 'e';
+ filenam[4] = '.';
+ (void)tostring(filenam+5,getpid(),
+ 5, B_DEC, '0');
+ filenam[10] = '.';
+ (void)tostring(filenam+11,corecnt++,
+ 3, B_DEC, '0');
+ filenam[14] = '\0';
+ (void) unlink(filenam);
+ if( link("core",filenam) == 0)
+ {
+ (void) unlink("core");
+ }
+ }
+ }
+#endif
+
+
+ /*
+ * If we are to just ignore the error and keep on processing
+ */
+ case M_HANDLE_IGNORE:
+ break;
+
+ } /* switch(... */
+
+} /* malloc_err_handler(... */
+
+/*
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1 1997/09/22 14:51:11 hjs
+ * dmake 4.1 orginal sourcen
+ *
+ * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura
+ * dmake gold 4.1.00 initial import
+ *
+ * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura
+ * Dmake 4.1 Initial Import
+ *
+ * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura
+ * Initial import for final release of dmake 4.1
+ *
+ * Revision 1.1 1994/10/06 17:43:12 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1994/10/06 03:45:22 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1992/01/24 03:29:05 dvadura
+ * dmake Version 3.8, Initial revision
+ *
+ * Revision 1.6 90/05/11 00:13:09 cpcahil
+ * added copyright statment
+ *
+ * Revision 1.5 90/02/25 11:01:18 cpcahil
+ * added support for malloc chain checking.
+ *
+ * Revision 1.4 90/02/24 21:50:21 cpcahil
+ * lots of lint fixes
+ *
+ * Revision 1.3 90/02/24 14:51:18 cpcahil
+ * 1. changed malloc_fatal and malloc_warn to use malloc_errno and be passed
+ * the function name as a parameter.
+ * 2. Added several function headers.
+ * 3. Changed uses of malloc_fatal/warning to conform to new usage.
+ *
+ * Revision 1.2 90/02/23 18:05:23 cpcahil
+ * fixed open of error log to use append mode.
+ *
+ * Revision 1.1 90/02/22 23:17:43 cpcahil
+ * Initial revision
+ *
+ */
diff --git a/dmake/dbug/malloc/malloc.h b/dmake/dbug/malloc/malloc.h
new file mode 100644
index 000000000000..0f34d49e1b72
--- /dev/null
+++ b/dmake/dbug/malloc/malloc.h
@@ -0,0 +1,121 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+/*
+ * $Id: malloc.h,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $
+ */
+struct mlist
+{
+ struct mlist * next; /* next entry in chain */
+ struct mlist * prev; /* prev entry in chain */
+ int flag; /* inuse flag */
+ unsigned int r_size; /* requested size */
+ union
+ {
+ unsigned int size; /* actual size */
+ double unused_just_for_alignment;
+ } s;
+ char data[4];
+};
+
+#define M_SIZE ((int)(char *)((struct mlist *)0)->data)
+#define M_RND 0x08
+
+#define M_INUSE 0x01
+#define M_MAGIC 0x03156100
+
+#define M_BLOCKSIZE (1024*8)
+
+#define M_FILL '\01'
+#define M_FREE_FILL '\02'
+
+#define M_ROUNDUP(size) {\
+ if( size & (M_RND-1) ) \
+ { \
+ size &= ~(M_RND-1); \
+ size += M_RND; \
+ } \
+ }
+
+/*
+ * Malloc warning/fatal error handler defines...
+ */
+#define M_HANDLE_DUMP 0x80 /* 128 */
+#define M_HANDLE_IGNORE 0
+#define M_HANDLE_ABORT 1
+#define M_HANDLE_EXIT 2
+#define M_HANDLE_CORE 3
+
+/*
+ * Mallopt commands and defaults
+ */
+
+#define MALLOC_WARN 1 /* set malloc warning handling */
+#define MALLOC_FATAL 2 /* set malloc fatal handling */
+#define MALLOC_ERRFILE 3 /* specify malloc error file */
+#define MALLOC_CKCHAIN 4 /* turn on chain checking */
+union malloptarg
+{
+ int i;
+ char * str;
+};
+
+/*
+ * Malloc warning/fatal error codes
+ */
+
+#define M_CODE_CHAIN_BROKE 1 /* malloc chain is broken */
+#define M_CODE_NO_END 2 /* chain end != endptr */
+#define M_CODE_BAD_PTR 3 /* pointer not in malloc area */
+#define M_CODE_BAD_MAGIC 4 /* bad magic number in header */
+#define M_CODE_BAD_CONNECT 5 /* chain poingers corrupt */
+#define M_CODE_OVERRUN 6 /* data overrun in malloc seg */
+#define M_CODE_REUSE 7 /* reuse of freed area */
+#define M_CODE_NOT_INUSE 8 /* pointer is not in use */
+#define M_CODE_NOMORE_MEM 9 /* no more memory available */
+#define M_CODE_OUTOF_BOUNDS 10 /* gone beyound bounds */
+
+void malloc_warning();
+void malloc_fatal();
+void malloc_check_data();
+void malloc_check_str();
+void malloc_verify();
+
+/*
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1 1997/09/22 14:51:11 hjs
+ * dmake 4.1 orginal sourcen
+ *
+ * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura
+ * dmake gold 4.1.00 initial import
+ *
+ * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura
+ * Dmake 4.1 Initial Import
+ *
+ * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura
+ * Initial import for final release of dmake 4.1
+ *
+ * Revision 1.1 1994/10/06 17:43:13 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1994/10/06 03:45:22 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1992/01/24 03:29:06 dvadura
+ * dmake Version 3.8, Initial revision
+ *
+ * Revision 1.4 90/08/29 22:23:38 cpcahil
+ * fixed mallopt to use a union as an argument.
+ *
+ * Revision 1.3 90/05/11 11:04:10 cpcahil
+ * took out some extraneous lines
+ *
+ * Revision 1.2 90/05/11 00:13:09 cpcahil
+ * added copyright statment
+ *
+ * Revision 1.1 90/02/23 07:09:03 cpcahil
+ * Initial revision
+ *
+ */
diff --git a/dmake/dbug/malloc/mallopt.c b/dmake/dbug/malloc/mallopt.c
new file mode 100644
index 000000000000..a3151d4730ac
--- /dev/null
+++ b/dmake/dbug/malloc/mallopt.c
@@ -0,0 +1,143 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+#include <stdio.h>
+#include <fcntl.h>
+#include "malloc.h"
+
+/*
+ * Function: mallopt()
+ *
+ * Purpose: to set options for the malloc debugging library
+ *
+ * Arguments: none
+ *
+ * Returns: nothing of any value
+ *
+ * Narrative:
+ *
+ */
+
+#ifndef lint
+static
+char rcs_hdr[] = "$Id: mallopt.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $";
+#endif
+
+int
+mallopt(cmd,value)
+ int cmd;
+ union malloptarg value;
+{
+ int i;
+ extern int malloc_checking;
+ extern char * malloc_data_start;
+ extern int malloc_errfd;
+ extern int malloc_fatal_level;
+ void malloc_init();
+ extern int malloc_warn_level;
+ register char * s;
+
+ /*
+ * If not initialized...
+ */
+ if( malloc_data_start == (char *) 0)
+ {
+ malloc_init();
+ }
+
+
+ switch(cmd)
+ {
+ case MALLOC_WARN:
+ malloc_warn_level = value.i;
+ break;
+
+ case MALLOC_FATAL:
+ malloc_fatal_level = value.i;
+ break;
+
+ case MALLOC_CKCHAIN:
+ malloc_checking = value.i;
+ break;
+
+ case MALLOC_ERRFILE:
+
+ i = open(value.str,O_CREAT|O_APPEND|O_WRONLY,0666);
+ if( i == -1 )
+ {
+ (void) write(2,
+ "Unable to open malloc error file: ",
+ (unsigned) 34);
+ for(s=value.str; *s; s++)
+ {
+ /* do nothing */;
+ }
+ (void) write(2,value.str,
+ (unsigned)(s-value.str));
+ (void) write(2,"\n",(unsigned)1);
+ }
+ else
+ {
+ if( malloc_errfd != 2 )
+ {
+ (void) close(malloc_errfd);
+ }
+ malloc_errfd = i;
+ }
+
+ break;
+
+ default:
+ return(1);
+ }
+
+ return(0);
+}
+
+/*
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1 1997/09/22 14:51:11 hjs
+ * dmake 4.1 orginal sourcen
+ *
+ * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura
+ * dmake gold 4.1.00 initial import
+ *
+ * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura
+ * Dmake 4.1 Initial Import
+ *
+ * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura
+ * Initial import for final release of dmake 4.1
+ *
+ * Revision 1.1 1994/10/06 17:43:14 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1994/10/06 03:45:23 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1992/01/24 03:29:07 dvadura
+ * dmake Version 3.8, Initial revision
+ *
+ * Revision 1.6 90/08/29 22:23:36 cpcahil
+ * fixed mallopt to use a union as an argument.
+ *
+ * Revision 1.5 90/08/29 21:22:51 cpcahil
+ * miscellaneous lint fixes
+ *
+ * Revision 1.4 90/05/11 00:13:10 cpcahil
+ * added copyright statment
+ *
+ * Revision 1.3 90/02/25 11:03:26 cpcahil
+ * changed to return int so that it agrees with l libmalloc.a's mallopt()
+ *
+ * Revision 1.2 90/02/25 11:01:21 cpcahil
+ * added support for malloc chain checking.
+ *
+ * Revision 1.1 90/02/24 21:50:24 cpcahil
+ * Initial revision
+ *
+ * Revision 1.1 90/02/24 17:10:53 cpcahil
+ * Initial revision
+ *
+ */
diff --git a/dmake/dbug/malloc/memory.c b/dmake/dbug/malloc/memory.c
new file mode 100644
index 000000000000..986007b1b77f
--- /dev/null
+++ b/dmake/dbug/malloc/memory.c
@@ -0,0 +1,243 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+
+#ifndef lint
+static
+char rcs_hdr[] = "$Id: memory.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $";
+#endif
+
+void malloc_check_data();
+
+char *
+memccpy(ptr1, ptr2, ch, len)
+ register char * ptr1;
+ register char * ptr2;
+ int len;
+ int ch;
+{
+ int check;
+ register int i;
+ char * rtn;
+
+ /*
+ * I know that the assignment could be done in the following, but
+ * I wanted to perform a check before any assignment, so first I
+ * determine the length, check the pointers and then do the assignment.
+ */
+ for( i=0; (i < len) && (ptr2[i] != ch); i++)
+ {
+ }
+ if( ptr2[i] == ch )
+ {
+ check = i+1;
+ }
+ else
+ {
+ check = len;
+ }
+
+ malloc_check_data("memccpy", ptr1, check);
+ malloc_check_data("memccpy", ptr2, check);
+
+ /*
+ * if we found the character...
+ */
+
+ if( i < len )
+ {
+ rtn = ptr1+i+1;
+ i++;
+ }
+ else
+ {
+ rtn = (char *) 0;
+ }
+
+ while( i-- )
+ {
+ *(ptr1++) = *(ptr2++);
+ }
+
+ return(rtn);
+}
+
+char *
+memchr(ptr1,ch,len)
+ register char * ptr1;
+ register int ch;
+ int len;
+{
+ int i;
+
+ for( i=0; (i < len) && (ptr1[i] != (char) ch); i++)
+ {
+ }
+
+ malloc_check_data("memchr", ptr1, i);
+
+ if( i < len )
+ {
+ return( ptr1+i );
+ }
+ else
+ {
+ return( (char *) 0);
+ }
+}
+
+char *
+memcpy(ptr1, ptr2, len)
+ register char * ptr1;
+ register char * ptr2;
+ register int len;
+{
+ char * rtn = ptr1;
+
+ malloc_check_data("memcpy", ptr1, len);
+ malloc_check_data("memcpy", ptr2, len);
+
+ /*
+ * while the normal memcpy does not guarrantee that it will
+ * handle overlapping memory correctly, we will try...
+ */
+ if( ptr1 > ptr2 && ptr1 < (ptr2+len))
+ {
+ ptr1 += (len-1);
+ ptr2 += (len-1);
+ while( len-- > 0 )
+ {
+ *(ptr1--) = *(ptr2--);
+ }
+ }
+ else
+ {
+ while( len-- > 0 )
+ {
+ *(ptr1++) = *(ptr2++);
+ }
+ }
+
+ return(rtn);
+}
+
+int
+memcmp(ptr1, ptr2, len)
+ register char * ptr1;
+ register char * ptr2;
+ register int len;
+{
+ malloc_check_data("memcpy", ptr1, len);
+ malloc_check_data("memcpy", ptr2, len);
+
+ while( --len >= 0 && (*ptr1 == *ptr2) )
+ {
+ ptr1++;
+ ptr2++;
+ }
+
+ /*
+ * If stopped by len, return zero
+ */
+ if( len < 0 )
+ {
+ return(0);
+ }
+
+ return( *ptr1 - *ptr2 );
+}
+
+char *
+memset(ptr1, ch, len)
+ register char * ptr1;
+ register int ch;
+ register int len;
+{
+ char * rtn = ptr1;
+
+ malloc_check_data("memcpy", ptr1, len);
+
+ while( len-- )
+ {
+ *(ptr1++) = ch;
+ }
+
+ return(rtn);
+}
+
+char *
+bcopy(ptr2,ptr1,len)
+ char * ptr2;
+ char * ptr1;
+ int len;
+{
+ return(memcpy(ptr1,ptr2,len));
+}
+
+char *
+bzero(ptr1,len)
+ char * ptr1;
+ int len;
+{
+ return(memset(ptr1,'\0',len));
+}
+
+int
+bcmp(ptr2, ptr1, len)
+ char * ptr1;
+ char * ptr2;
+ int len;
+{
+ return( memcmp(ptr1,ptr2,len) );
+}
+
+/*
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1 1997/09/22 14:51:11 hjs
+ * dmake 4.1 orginal sourcen
+ *
+ * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura
+ * dmake gold 4.1.00 initial import
+ *
+ * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura
+ * Dmake 4.1 Initial Import
+ *
+ * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura
+ * Initial import for final release of dmake 4.1
+ *
+ * Revision 1.1 1994/10/06 17:43:14 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1994/10/06 03:45:23 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1992/01/24 03:29:08 dvadura
+ * dmake Version 3.8, Initial revision
+ *
+ * Revision 1.7 90/08/29 21:27:58 cpcahil
+ * fixed value of check in memccpy when character was not found.
+ *
+ * Revision 1.6 90/07/16 20:06:26 cpcahil
+ * fixed several minor bugs found with Henry Spencer's string/mem tester
+ * program.
+ *
+ *
+ * Revision 1.5 90/05/11 15:39:36 cpcahil
+ * fixed bug in memccpy().
+ *
+ * Revision 1.4 90/05/11 00:13:10 cpcahil
+ * added copyright statment
+ *
+ * Revision 1.3 90/02/24 21:50:29 cpcahil
+ * lots of lint fixes
+ *
+ * Revision 1.2 90/02/24 17:29:41 cpcahil
+ * changed $Header to $Id so full path wouldnt be included as part of rcs
+ * id string
+ *
+ * Revision 1.1 90/02/22 23:17:43 cpcahil
+ * Initial revision
+ *
+ */
diff --git a/dmake/dbug/malloc/mlc_chk.c b/dmake/dbug/malloc/mlc_chk.c
new file mode 100644
index 000000000000..077e675240bf
--- /dev/null
+++ b/dmake/dbug/malloc/mlc_chk.c
@@ -0,0 +1,297 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+
+#include <stdio.h>
+#include "malloc.h"
+#include "debug.h"
+
+#ifndef lint
+static
+char rcs_hdr[] = "$Id: mlc_chk.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $";
+#endif
+
+extern struct mlist malloc_start;
+extern struct mlist * malloc_end;
+extern char * malloc_data_start;
+extern char * malloc_data_end;
+
+/*
+ * Function: malloc_in_arena()
+ *
+ * Purpose: to verify address is within malloc arena.
+ *
+ * Arguments: ptr - pointer to verify
+ *
+ * Returns: TRUE - if pointer is within malloc area
+ * FALSE - otherwise
+ *
+ * Narrative:
+ * IF pointer is >= malloc area start AND <= malloc area end
+ * return TRUE
+ * ELSE
+ * return FALSE
+ *
+ * Mod History:
+ * 90/01/24 cpcahil Initial revision.
+ */
+int
+malloc_in_arena(ptr)
+ char * ptr;
+{
+ extern char * malloc_data_start;
+ extern char * malloc_data_end;
+ int rtn = 0;
+
+ if( ptr >= malloc_data_start && ptr <= malloc_data_end )
+ {
+ rtn = 1;
+ }
+
+ return(rtn);
+}
+
+/*
+ * Function: malloc_check_str()
+ *
+ * Arguments: func - name of function calling this routine
+ * str - pointer to area to check
+ *
+ * Purpose: to verify that if str is within the malloc arena, the data
+ * it points to does not extend beyond the applicable region.
+ *
+ * Returns: Nothing of any use (function is void).
+ *
+ * Narrative:
+ * IF pointer is within malloc arena
+ * determin length of string
+ * call malloc_verify() to verify data is withing applicable region
+ * return
+ *
+ * Mod History:
+ * 90/01/24 cpcahil Initial revision.
+ * 90/01/29 cpcahil Added code to ignore recursive calls.
+ */
+void
+malloc_check_str(func,str)
+ char * func;
+ char * str;
+{
+ static int layers;
+ register char * s;
+
+ if( (layers++ == 0) && malloc_in_arena(str) )
+ {
+ for( s=str; *s; s++)
+ {
+ }
+
+ malloc_verify(func,str,s-str+1);
+ }
+
+ layers--;
+}
+
+/*
+ * Function: malloc_check_strn()
+ *
+ * Arguments: func - name of function calling this routine
+ * str - pointer to area to check
+ * len - max length of string
+ *
+ * Purpose: to verify that if str is within the malloc arena, the data
+ * it points to does not extend beyond the applicable region.
+ *
+ * Returns: Nothing of any use (function is void).
+ *
+ * Narrative:
+ * IF pointer is within malloc arena
+ * determin length of string
+ * call malloc_verify() to verify data is withing applicable region
+ * return
+ *
+ * Mod History:
+ * 90/01/24 cpcahil Initial revision.
+ * 90/01/29 cpcahil Added code to ignore recursive calls.
+ * 90/08/29 cpcahil added length (for strn* functions)
+ */
+void
+malloc_check_strn(func,str,len)
+ char * func;
+ char * str;
+ int len;
+{
+ register int i;
+ static int layers;
+ register char * s;
+
+ if( (layers++ == 0) && malloc_in_arena(str) )
+ {
+ for( s=str,i=0; (i < len) && *s; s++)
+ {
+ }
+
+ malloc_verify(func,str,s-str+1);
+ }
+
+ layers--;
+}
+
+/*
+ * Function: malloc_check_data()
+ *
+ * Arguments: func - name of function calling this routine
+ * ptr - pointer to area to check
+ * len - length to verify
+ *
+ * Purpose: to verify that if ptr is within the malloc arena, the data
+ * it points to does not extend beyond the applicable region.
+ *
+ * Returns: Nothing of any use (function is void).
+ *
+ * Narrative:
+ * IF pointer is within malloc arena
+ * call malloc_verify() to verify data is withing applicable region
+ * return
+ *
+ * Mod History:
+ * 90/01/24 cpcahil Initial revision.
+ * 90/01/29 cpcahil Added code to ignore recursive calls.
+ */
+void
+malloc_check_data(func,ptr,len)
+ char * func;
+ char * ptr;
+ int len;
+{
+ static int layers;
+
+ if( layers++ == 0 )
+ {
+ DEBUG3(40,"malloc_check_data(%s,0x%x,%d) called...",
+ func,ptr,len);
+ if( malloc_in_arena(ptr) )
+ {
+ DEBUG0(10,"pointer in malloc arena, verifying...");
+ malloc_verify(func,ptr,len);
+ }
+ }
+
+ layers--;
+}
+
+/*
+ * Function: malloc_verify()
+ *
+ * Arguments: func - name of function calling the malloc check routines
+ * ptr - pointer to area to check
+ * len - length to verify
+ *
+ * Purpose: to verify that the data ptr points to does not extend beyond
+ * the applicable malloc region. This function is only called
+ * if it has been determined that ptr points into the malloc arena.
+ *
+ * Returns: Nothing of any use (function is void).
+ *
+ * Narrative:
+ *
+ * Mod History:
+ * 90/01/24 cpcahil Initial revision.
+ */
+void
+malloc_verify(func,ptr,len)
+ char * func;
+ char * ptr;
+ int len;
+{
+ extern struct mlist * malloc_end;
+ extern int malloc_errno;
+ extern struct mlist malloc_start;
+ struct mlist * mptr;
+
+ DEBUG3(40,"malloc_verify(%s,0x%x,%d) called...", func,ptr,len);
+ /*
+ * Find the malloc block that includes this pointer
+ */
+ mptr = &malloc_start;
+ while( mptr &&
+ ! (((char *)mptr < ptr) && ((mptr->data+mptr->s.size) > ptr) ) )
+ {
+ mptr = mptr->next;
+ }
+
+ /*
+ * if ptr was not in a malloc block, it must be part of
+ * some direct sbrk() stuff, so just return.
+ */
+ if( ! mptr )
+ {
+ DEBUG1(10,"ptr (0x%x) not found in malloc search", ptr);
+ return;
+ }
+
+ /*
+ * Now we have a valid malloc block that contains the indicated
+ * pointer. We must verify that it is withing the requested block
+ * size (as opposed to the real block size which is rounded up to
+ * allow for correct alignment).
+ */
+
+ DEBUG4(60,"Checking 0x%x-0x%x, 0x%x-0x%x",
+ ptr, ptr+len, mptr->data, mptr->data+mptr->r_size);
+
+ if( (ptr < mptr->data) || ((ptr+len) > (mptr->data+mptr->r_size)) )
+ {
+ DEBUG4(0,"pointer not within region 0x%x-0x%x, 0x%x-0x%x",
+ ptr, ptr+len, mptr->data, mptr->data+mptr->r_size);
+
+ malloc_errno = M_CODE_OUTOF_BOUNDS;
+ malloc_warning(func);
+ }
+
+ return;
+}
+
+/*
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1 1997/09/22 14:51:11 hjs
+ * dmake 4.1 orginal sourcen
+ *
+ * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura
+ * dmake gold 4.1.00 initial import
+ *
+ * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura
+ * Dmake 4.1 Initial Import
+ *
+ * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura
+ * Initial import for final release of dmake 4.1
+ *
+ * Revision 1.1 1994/10/06 17:43:15 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1994/10/06 03:45:24 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1992/01/24 03:29:09 dvadura
+ * dmake Version 3.8, Initial revision
+ *
+ * Revision 1.5 90/08/29 22:23:48 cpcahil
+ * added new function to check on strings up to a specified length
+ * and used it within several strn* functions.
+ *
+ * Revision 1.4 90/05/11 00:13:09 cpcahil
+ * added copyright statment
+ *
+ * Revision 1.3 90/02/24 21:50:22 cpcahil
+ * lots of lint fixes
+ *
+ * Revision 1.2 90/02/24 17:29:38 cpcahil
+ * changed $Header to $Id so full path wouldnt be included as part of rcs
+ * id string
+ *
+ * Revision 1.1 90/02/24 14:57:03 cpcahil
+ * Initial revision
+ *
+ */
diff --git a/dmake/dbug/malloc/mlc_chn.c b/dmake/dbug/malloc/mlc_chn.c
new file mode 100644
index 000000000000..3f24333611f9
--- /dev/null
+++ b/dmake/dbug/malloc/mlc_chn.c
@@ -0,0 +1,188 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+#include <stdio.h>
+#include <fcntl.h>
+#include "malloc.h"
+
+/*
+ * Function: malloc_chain_check()
+ *
+ * Purpose: to verify malloc chain is intact
+ *
+ * Arguments: todo - 0 - just check and return status
+ * 1 - call malloc_warn if error detected
+ *
+ * Returns: 0 - malloc chain intact & no overflows
+ * other - problems detected in malloc chain
+ *
+ * Narrative:
+ *
+ * Notes: If todo is non-zero the malloc_warn function, when called
+ * may not return (i.e. it may exit)
+ *
+ */
+#ifndef lint
+static
+char rcs_hdr[] = "$Id: mlc_chn.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $";
+#endif
+
+
+int
+malloc_chain_check(todo)
+ int todo;
+{
+ char * func = "malloc_chain_check";
+ int i;
+ extern char * malloc_data_start;
+ extern char * malloc_data_end;
+ extern struct mlist * malloc_end;
+ extern int malloc_errno;
+ extern struct mlist malloc_start;
+ struct mlist * oldptr;
+ struct mlist * ptr;
+ int rtn = 0;
+
+ oldptr = &malloc_start;
+ for(ptr = malloc_start.next; ; ptr = ptr->next)
+ {
+ /*
+ * Since the malloc chain is a forward only chain, any
+ * pointer that we get should always be positioned in
+ * memory following the previous pointer. If this is not
+ * so, we must have a corrupted chain.
+ */
+ if( ptr )
+ {
+ if(ptr < oldptr )
+ {
+ malloc_errno = M_CODE_CHAIN_BROKE;
+ if( todo )
+ {
+ malloc_fatal(func);
+ }
+ rtn++;
+ break;
+ }
+ oldptr = ptr;
+ }
+ else
+ {
+ if( oldptr != malloc_end )
+ {
+ /*
+ * This should never happen. If it does, then
+ * we got a real problem.
+ */
+ malloc_errno = M_CODE_NO_END;
+ if( todo )
+ {
+ malloc_fatal(func);
+ }
+ rtn++;
+ }
+ break;
+ }
+
+ /*
+ * verify that ptr is within the malloc region...
+ * since we started within the malloc chain this should never
+ * happen.
+ */
+
+ if( ((char *)ptr < malloc_data_start) ||
+ ((char *)ptr > malloc_data_end) )
+ {
+ malloc_errno = M_CODE_BAD_PTR;
+ if( todo )
+ {
+ malloc_fatal(func);
+ }
+ rtn++;
+ break;
+ }
+
+ /*
+ * verify magic flag is set
+ */
+
+ if( (ptr->flag&M_MAGIC) != M_MAGIC )
+ {
+ malloc_errno = M_CODE_BAD_MAGIC;
+ if( todo )
+ {
+ malloc_warning(func);
+ }
+ rtn++;
+ continue;
+ }
+
+ /*
+ * verify segments are correctly linked together
+ */
+
+ if( (ptr->prev && (ptr->prev->next != ptr) ) ||
+ (ptr->next && (ptr->next->prev != ptr) ) ||
+ ((ptr->next == NULL) && (ptr->prev == NULL)) )
+ {
+ malloc_errno = M_CODE_BAD_CONNECT;
+ if( todo )
+ {
+ malloc_warning(func);
+ }
+ rtn++;
+ continue;
+ }
+
+ /*
+ * If this segment is allocated
+ */
+
+ if( (ptr->flag & M_INUSE) != 0 )
+ {
+ /*
+ * verify no overflow of data area
+ */
+
+ for(i=ptr->r_size; i < ptr->s.size; i++)
+ {
+ if( ptr->data[i] != M_FILL )
+ {
+ malloc_errno = M_CODE_OVERRUN;
+ if( todo )
+ {
+ malloc_warning(func);
+ }
+ rtn++;
+ break;
+ }
+ }
+ }
+ else /* it's not allocated so */
+ {
+ /*
+ * verify no reuse of freed data blocks
+ */
+
+ for(i=0; i < ptr->s.size; i++)
+ {
+ if( ptr->data[i] != M_FREE_FILL )
+ {
+ malloc_errno = M_CODE_REUSE;
+ if( todo )
+ {
+ malloc_warning(func);
+ }
+ rtn++;
+ break;
+ }
+ }
+ }
+
+ } /* for(... */
+
+ return(rtn);
+
+} /* malloc_chain_check(... */
diff --git a/dmake/dbug/malloc/patchlev b/dmake/dbug/malloc/patchlev
new file mode 100644
index 000000000000..00750edc07d6
--- /dev/null
+++ b/dmake/dbug/malloc/patchlev
@@ -0,0 +1 @@
+3
diff --git a/dmake/dbug/malloc/realloc.c b/dmake/dbug/malloc/realloc.c
new file mode 100644
index 000000000000..43bc20fa7841
--- /dev/null
+++ b/dmake/dbug/malloc/realloc.c
@@ -0,0 +1,233 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+#include <stdio.h>
+#include "malloc.h"
+
+/*
+ * Function: realloc()
+ *
+ * Purpose: to re-allocate a data area.
+ *
+ * Arguments: cptr - pointer to area to reallocate
+ * size - size to change area to
+ *
+ * Returns: pointer to new area (may be same area)
+ *
+ * Narrative: verify pointer is within malloc region
+ * obtain mlist pointer from cptr
+ * verify magic number is correct
+ * verify inuse flag is set
+ * verify connection to adjoining segments is correct
+ * save requested size
+ * round-up size to appropriate boundry
+ * IF size is bigger than what is in this segment
+ * try to join next segment to this segment
+ * IF size is less than what is is this segment
+ * determine leftover amount of space
+ * ELSE
+ * allocate new segment of size bites
+ * IF allocation failed
+ * return NULL
+ * copy previous data to new segment
+ * free previous segment
+ * return new pointer
+ * split of extra space in this segment (if any)
+ * clear bytes beyound what they had before
+ * return pointer to data
+ */
+#ifndef lint
+static
+char rcs_hdr[] = "$Id: realloc.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $";
+#endif
+
+char *
+realloc(cptr,size)
+ char * cptr;
+ unsigned int size;
+{
+ void free();
+ char * func = "realloc";
+ int i;
+ char * malloc();
+ extern int malloc_checking;
+ extern struct mlist * malloc_end;
+ extern int malloc_errno;
+ extern char * malloc_data_end;
+ extern char * malloc_data_start;
+ void malloc_join();
+ void malloc_memset();
+ void malloc_split();
+ char * memcpy();
+ char * new_cptr;
+ struct mlist * ptr;
+ int r_size;
+
+ /*
+ * IF malloc chain checking is on, go do it.
+ */
+ if( malloc_checking )
+ {
+ (void) malloc_chain_check(1);
+ }
+
+ /*
+ * verify that cptr is within the malloc region...
+ */
+ if( cptr < malloc_data_start || cptr > malloc_data_end )
+ {
+ malloc_errno = M_CODE_BAD_PTR;
+ malloc_warning(func);
+ return (NULL);
+ }
+
+ /*
+ * convert pointer to mlist struct pointer. To do this we must
+ * move the pointer backwards the correct number of bytes...
+ */
+
+ ptr = (struct mlist *) (cptr - M_SIZE);
+
+ if( (ptr->flag&M_MAGIC) != M_MAGIC )
+ {
+ malloc_errno = M_CODE_BAD_MAGIC;
+ malloc_warning(func);
+ return(NULL);
+ }
+
+ if( ! (ptr->flag & M_INUSE) )
+ {
+ malloc_errno = M_CODE_NOT_INUSE ;
+ malloc_warning(func);
+ return(NULL);
+ }
+
+ if( (ptr->prev && (ptr->prev->next != ptr) ) ||
+ (ptr->next && (ptr->next->prev != ptr) ) ||
+ ((ptr->next == NULL) && (ptr->prev == NULL)) )
+ {
+ malloc_errno = M_CODE_BAD_CONNECT;
+ malloc_warning(func);
+ return(NULL);
+ }
+
+ r_size = ++size;
+
+ M_ROUNDUP(size);
+
+ if( size > ptr->s.size )
+ {
+ malloc_join(ptr,ptr->next,1,1);
+ }
+
+ if( size > ptr->s.size )
+ {
+ /*
+ * else we can't combine it, so lets allocate a new chunk,
+ * copy the data and free the old chunk...
+ */
+ new_cptr = malloc(size);
+
+ if( new_cptr == (char *) 0)
+ {
+ return(new_cptr);
+ }
+
+ if( r_size < ptr->r_size )
+ {
+ i = r_size;
+ }
+ else
+ {
+ i = ptr->r_size;
+ }
+ (void)memcpy(new_cptr,ptr->data,i);
+ free(cptr);
+ return(new_cptr);
+
+ } /* else... */
+
+ /*
+ * save amount of real data in new segment (this will be used in the
+ * memset later) and then save requested size of this segment.
+ */
+
+ if( ptr->r_size < r_size )
+ {
+ i = ptr->r_size;
+ }
+ else
+ {
+ i = r_size;
+ }
+
+ ptr->r_size = r_size;
+
+ /*
+ * split off extra free space at end of this segment, if possible...
+ */
+
+ malloc_split(ptr);
+
+ malloc_memset( ptr->data+i, M_FILL, (int) (ptr->s.size - i));
+
+ return(ptr->data);
+
+} /* realloc(... */
+
+
+/*
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1 1997/09/22 14:51:11 hjs
+ * dmake 4.1 orginal sourcen
+ *
+ * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura
+ * dmake gold 4.1.00 initial import
+ *
+ * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura
+ * Dmake 4.1 Initial Import
+ *
+ * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura
+ * Initial import for final release of dmake 4.1
+ *
+ * Revision 1.1 1994/10/06 17:43:17 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1994/10/06 03:45:26 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1992/01/24 03:29:11 dvadura
+ * dmake Version 3.8, Initial revision
+ *
+ * Revision 1.8 90/08/29 21:22:52 cpcahil
+ * miscellaneous lint fixes
+ *
+ * Revision 1.7 90/05/11 00:13:10 cpcahil
+ * added copyright statment
+ *
+ * Revision 1.6 90/02/25 11:01:20 cpcahil
+ * added support for malloc chain checking.
+ *
+ * Revision 1.5 90/02/24 21:50:31 cpcahil
+ * lots of lint fixes
+ *
+ * Revision 1.4 90/02/24 17:29:39 cpcahil
+ * changed $Header to $Id so full path wouldnt be included as part of rcs
+ * id string
+ *
+ * Revision 1.3 90/02/24 17:20:00 cpcahil
+ * attempt to get rid of full path in rcs header.
+ *
+ * Revision 1.2 90/02/24 15:14:20 cpcahil
+ * 1. added function header
+ * 2. changed calls to malloc_warning to conform to new usage
+ * 3. added setting of malloc_errno
+ * 4. broke up bad pointer determination so that errno's would be more
+ * descriptive
+ *
+ * Revision 1.1 90/02/22 23:17:43 cpcahil
+ * Initial revision
+ *
+ */
diff --git a/dmake/dbug/malloc/string.c b/dmake/dbug/malloc/string.c
new file mode 100644
index 000000000000..8ca3a1eee167
--- /dev/null
+++ b/dmake/dbug/malloc/string.c
@@ -0,0 +1,581 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "malloc.h"
+
+#ifndef lint
+static
+char rcs_hdr[] = "$Id: string.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $";
+#endif
+
+int malloc_checking = 0;
+
+char *
+strcat(str1,str2)
+ register char * str1;
+ register char * str2;
+{
+ char * rtn;
+ int len;
+
+ /*
+ * check pointers agains malloc region. The malloc* functions
+ * will properly handle the case where a pointer does not
+ * point into malloc space.
+ */
+ malloc_checking = 1;
+
+ len = strlen(str2);
+ malloc_check_str("strcat", str2);
+
+ len += strlen(str1) + 1;
+ malloc_checking = 0;
+
+ malloc_check_data("strcat", str1, len);
+
+ rtn = str1;
+
+ while( *str1 )
+ {
+ str1++;
+ }
+
+ while( (*str1 = *str2) != '\0' )
+ {
+ str1++;
+ str2++;
+ }
+
+ return(rtn);
+}
+
+char *
+strdup(str1)
+ register char * str1;
+{
+ char * malloc();
+ char * rtn;
+ register char * str2;
+
+ malloc_check_str("strdup", str1);
+
+ rtn = str2 = malloc((unsigned)strlen(str1)+1);
+
+ if( rtn != (char *) 0)
+ {
+ while( (*str2 = *str1) != '\0' )
+ {
+ str1++;
+ str2++;
+ }
+ }
+
+ return(rtn);
+}
+
+char *
+strncat(str1,str2,len)
+ register char * str1;
+ register char * str2;
+ register int len;
+{
+ int len1;
+ int len2;
+ char * rtn;
+
+ malloc_check_strn("strncat", str2, len);
+
+ malloc_checking = 1;
+
+ len2 = strlen(str2) + 1;
+ len1 = strlen(str1);
+
+ malloc_checking = 0;
+
+
+ if( (len+1) < len2 )
+ {
+ len1 += len + 1;
+ }
+ else
+ {
+ len1 += len2;
+ }
+ malloc_check_data("strncat", str1, len1);
+
+ rtn = str1;
+
+ while( *str1 )
+ {
+ str1++;
+ }
+
+ while( len-- && ((*str1++ = *str2++) != '\0') )
+ {
+ }
+
+ if( ! len )
+ {
+ *str1 = '\0';
+ }
+
+ return(rtn);
+}
+
+int
+strcmp(str1,str2)
+ register char * str1;
+ register char * str2;
+{
+ malloc_check_str("strcmp", str1);
+ malloc_check_str("strcmp", str2);
+
+ while( *str1 && (*str1 == *str2) )
+ {
+ str1++;
+ str2++;
+ }
+
+
+ /*
+ * in order to deal with the case of a negative last char of either
+ * string when the other string has a null
+ */
+ if( (*str2 == '\0') && (*str1 == '\0') )
+ {
+ return(0);
+ }
+ else if( *str2 == '\0' )
+ {
+ return(1);
+ }
+ else if( *str1 == '\0' )
+ {
+ return(-1);
+ }
+
+ return( *str1 - *str2 );
+}
+
+int
+strncmp(str1,str2,len)
+ register char * str1;
+ register char * str2;
+ register int len;
+{
+ malloc_check_strn("strncmp", str1, len);
+ malloc_check_strn("strncmp", str2, len);
+
+ while( --len >= 0 && *str1 && (*str1 == *str2) )
+ {
+ str1++;
+ str2++;
+ }
+
+ if( len < 0 )
+ {
+ return(0);
+ }
+ /*
+ * in order to deal with the case of a negative last char of either
+ * string when the other string has a null
+ */
+ if( (*str2 == '\0') && (*str1 == '\0') )
+ {
+ return(0);
+ }
+ else if( *str2 == '\0' )
+ {
+ return(1);
+ }
+ else if( *str1 == '\0' )
+ {
+ return(-1);
+ }
+
+ return( *str1 - *str2 );
+}
+
+char *
+strcpy(str1,str2)
+ register char * str1;
+ register char * str2;
+{
+ char * rtn;
+ int len;
+
+ malloc_checking = 1;
+ len = strlen(str2) + 1;
+ malloc_checking = 0;
+
+ malloc_check_data("strcpy", str1, len);
+ malloc_check_data("strcpy", str2, len);
+
+ rtn = str1;
+
+ while( (*str1++ = *str2++) != '\0')
+ {
+ }
+
+ return(rtn);
+}
+
+char *
+strncpy(str1,str2,len)
+ register char * str1;
+ register char * str2;
+ register int len;
+{
+ extern int malloc_checking;
+ char * rtn;
+
+ malloc_check_data("strncpy", str1, len);
+ malloc_check_strn("strncpy", str2, len);
+
+ rtn = str1;
+
+ while((len-- > 0) && (*str1++ = *str2++) != '\0')
+ {
+ }
+ while( (len-- > 0) )
+ {
+ *str1++ = '\0';
+ }
+
+ return(rtn);
+}
+
+int
+strlen(str1)
+ register char * str1;
+{
+ register char * s;
+
+ if(! malloc_checking )
+ {
+ malloc_check_str("strlen", str1);
+ }
+
+ for( s = str1; *s; s++)
+ {
+ }
+
+ return( s - str1 );
+}
+
+char *
+strchr(str1,c)
+ register char * str1;
+ register int c;
+{
+ malloc_check_str("strchr", str1);
+
+ while( *str1 && (*str1 != (char) c) )
+ {
+ str1++;
+ }
+
+ if(*str1 != (char) c)
+ {
+ str1 = (char *) 0;
+ }
+
+ return(str1);
+}
+
+char *
+strrchr(str1,c)
+ register char * str1;
+ register int c;
+{
+ register char * rtn = (char *) 0;
+
+ malloc_check_str("strrchr", str1);
+
+ while( *str1 )
+ {
+ if(*str1 == (char) c )
+ {
+ rtn = str1;
+ }
+ str1++;
+ }
+
+ if( *str1 == (char) c)
+ {
+ rtn = str1;
+ }
+
+ return(rtn);
+}
+
+char *
+index(str1,c)
+ char * str1;
+ char c;
+{
+ return( strchr(str1,c) );
+}
+
+char *
+rindex(str1,c)
+ char * str1;
+ char c;
+{
+ return( strrchr(str1,c) );
+}
+
+char *
+strpbrk(str1,str2)
+ register char * str1;
+ register char * str2;
+{
+ register char * tmp;
+
+ malloc_check_str("strpbrk", str1);
+ malloc_check_str("strpbrk", str2);
+
+ while(*str1)
+ {
+ for( tmp=str2; *tmp && *tmp != *str1; tmp++)
+ {
+ }
+ if( *tmp )
+ {
+ break;
+ }
+ str1++;
+ }
+
+ if( ! *str1 )
+ {
+ str1 = (char *) 0;
+ }
+
+ return(str1);
+}
+
+int
+strspn(str1,str2)
+ register char * str1;
+ register char * str2;
+{
+ register char * tmp;
+ char * orig = str1;
+
+ malloc_check_str("strspn", str1);
+ malloc_check_str("strspn", str2);
+
+ while(*str1)
+ {
+ for( tmp=str2; *tmp && *tmp != *str1; tmp++)
+ {
+ }
+ if(! *tmp )
+ {
+ break;
+ }
+ str1++;
+ }
+
+ return( (int) (str1 - orig) );
+}
+
+int
+strcspn(str1,str2)
+ register char * str1;
+ register char * str2;
+{
+ register char * tmp;
+ char * orig = str1;
+
+ malloc_check_str("strcspn", str1);
+ malloc_check_str("strcspn", str2);
+
+ while(*str1)
+ {
+ for( tmp=str2; *tmp && *tmp != *str1; tmp++)
+ {
+ }
+ if( *tmp )
+ {
+ break;
+ }
+ str1++;
+ }
+
+ return( (int) (str1 - orig) );
+}
+
+/*
+ * strtok() source taken from that posted to comp.lang.c by Chris Torek
+ * in Jan 1990.
+ */
+
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * Get next token from string s (NULL on 2nd, 3rd, etc. calls),
+ * where tokens are nonempty strings separated by runs of
+ * chars from delim. Writes NULs into s to end tokens. delim need not
+ * remain constant from call to call.
+ *
+ * Modified by cpc: changed variable names to conform with naming
+ * conventions used in rest of code. Added malloc pointer
+ * check calls.
+ */
+char *
+strtok(str1, str2)
+ char * str1;
+ char * str2;
+{
+ static char * last;
+ char * strtoken();
+
+ if( str1 )
+ {
+ malloc_check_str("strtok", str1);
+ last = str1;
+ }
+ malloc_check_str("strtok", str2);
+
+ return (strtoken(&last, str2, 1));
+}
+
+
+/*
+ * Get next token from string *stringp, where tokens are (possibly empty)
+ * strings separated by characters from delim. Tokens are separated
+ * by exactly one delimiter iff the skip parameter is false; otherwise
+ * they are separated by runs of characters from delim, because we
+ * skip over any initial `delim' characters.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim will usually, but need not, remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strtoken returns NULL.
+ */
+char *
+strtoken(stringp, delim, skip)
+ register char **stringp;
+ register char *delim;
+ int skip;
+{
+ register char *s;
+ register char *spanp;
+ register int c, sc;
+ char *tok;
+
+ if ((s = *stringp) == NULL)
+ return (NULL);
+
+ if (skip) {
+ /*
+ * Skip (span) leading delimiters (s += strspn(s, delim)).
+ */
+ cont:
+ c = *s;
+ for (spanp = delim; (sc = *spanp++) != 0;) {
+ if (c == sc) {
+ s++;
+ goto cont;
+ }
+ }
+ if (c == 0) { /* no token found */
+ *stringp = NULL;
+ return (NULL);
+ }
+ }
+
+ /*
+ * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+ * Note that delim must have one NUL; we stop if we see that, too.
+ */
+ for (tok = s;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1 1997/09/22 14:51:11 hjs
+ * dmake 4.1 orginal sourcen
+ *
+ * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura
+ * dmake gold 4.1.00 initial import
+ *
+ * Revision 1.1.1.1 1996/10/27 07:30:14 dvadura
+ * Dmake 4.1 Initial Import
+ *
+ * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura
+ * Initial import for final release of dmake 4.1
+ *
+ * Revision 1.1 1994/10/06 17:43:17 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1994/10/06 03:45:27 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1992/01/24 03:29:13 dvadura
+ * dmake Version 3.8, Initial revision
+ *
+ * Revision 1.7 90/08/29 22:24:19 cpcahil
+ * added new function to check on strings up to a specified length
+ * and used it within several strn* functions.
+ *
+ * Revision 1.6 90/07/16 20:06:56 cpcahil
+ * fixed several minor bugs found with Henry Spencer's string/mem function
+ * tester program.
+ *
+ * Revision 1.5 90/06/10 14:59:49 cpcahil
+ * Fixed a couple of bugs in strncpy & strdup
+ *
+ * Revision 1.4 90/05/11 00:13:10 cpcahil
+ * added copyright statment
+ *
+ * Revision 1.3 90/02/24 21:50:32 cpcahil
+ * lots of lint fixes
+ *
+ * Revision 1.2 90/02/24 17:29:40 cpcahil
+ * changed $Header to $Id so full path wouldnt be included as part of rcs
+ * id string
+ *
+ * Revision 1.1 90/02/22 23:17:44 cpcahil
+ * Initial revision
+ *
+ */
diff --git a/dmake/dbug/malloc/testmem.c b/dmake/dbug/malloc/testmem.c
new file mode 100644
index 000000000000..46fba912f8c0
--- /dev/null
+++ b/dmake/dbug/malloc/testmem.c
@@ -0,0 +1,646 @@
+/*
+ * This stuff is all stolen (with permission, since it was in the public
+ * domain) from Henry Spencer's string and memory library. Thanks Henry.
+ */
+
+/*
+ * Test program for string(3) routines.
+ *
+ * Note that at least one Bell Labs implementation of the string
+ * routines flunks a couple of these tests -- the ones which test
+ * behavior on "negative" characters.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+char * index();
+char * rindex();
+
+#define STREQ(a, b) (strcmp((a), (b)) == 0)
+
+char *it = "<UNSET>"; /* Routine name for message routines. */
+int waserror = 0; /* For exit status. */
+
+char uctest[] = "\004\203"; /* For testing signedness of chars. */
+int charsigned; /* Result. */
+
+/*
+ - check - complain if condition is not true
+ */
+void
+check(thing, number)
+int thing;
+int number; /* Test number for error message. */
+{
+ if (!thing) {
+ printf("%s flunked test %d\n", it, number);
+ waserror = 1;
+ }
+}
+
+/*
+ - equal - complain if first two args don't strcmp as equal
+ */
+void
+equal(a, b, number)
+char *a;
+char *b;
+int number; /* Test number for error message. */
+{
+ check(a != NULL && b != NULL && STREQ(a, b), number);
+}
+
+char one[50];
+char two[50];
+
+#ifdef UNIXERR
+#define ERR 1
+#endif
+#ifdef BERKERR
+#define ERR 1
+#endif
+#ifdef ERR
+int f;
+extern char *sys_errlist[];
+extern int sys_nerr;
+extern int errno;
+#endif
+
+/* ARGSUSED */
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ /*
+ * First, establish whether chars are signed.
+ */
+ if (uctest[0] < uctest[1])
+ charsigned = 0;
+ else
+ charsigned = 1;
+
+ /*
+ * Then, do the rest of the work. Split into two functions because
+ * some compilers get unhappy about a single immense function.
+ */
+ first();
+ second();
+
+ exit((waserror) ? 1 : 0);
+}
+
+first()
+{
+ /*
+ * Test strcmp first because we use it to test other things.
+ */
+ it = "strcmp";
+ check(strcmp("", "") == 0, 1); /* Trivial case. */
+ check(strcmp("a", "a") == 0, 2); /* Identity. */
+ check(strcmp("abc", "abc") == 0, 3); /* Multicharacter. */
+ check(strcmp("abc", "abcd") < 0, 4); /* Length mismatches. */
+ check(strcmp("abcd", "abc") > 0, 5);
+ check(strcmp("abcd", "abce") < 0, 6); /* Honest miscompares. */
+ check(strcmp("abce", "abcd") > 0, 7);
+ check(strcmp("a\203", "a") > 0, 8); /* Tricky if char signed. */
+ if (charsigned) /* Sign-bit comparison. */
+ check(strcmp("a\203", "a\003") < 0, 9);
+ else
+ check(strcmp("a\203", "a\003") > 0, 9);
+ check(strcmp("a", "a\203") < 0, 10); /* Tricky if char signed. */
+
+ /*
+ * Test strcpy next because we need it to set up other tests.
+ */
+ it = "strcpy";
+ check(strcpy(one, "abcd") == one, 1); /* Returned value. */
+ equal(one, "abcd", 2); /* Basic test. */
+
+ (void) strcpy(one, "x");
+ equal(one, "x", 3); /* Writeover. */
+ equal(one+2, "cd", 4); /* Wrote too much? */
+
+ (void) strcpy(two, "hi there");
+ (void) strcpy(one, two);
+ equal(one, "hi there", 5); /* Basic test encore. */
+ equal(two, "hi there", 6); /* Stomped on source? */
+
+ (void) strcpy(one, "");
+ equal(one, "", 7); /* Boundary condition. */
+
+ /*
+ * strcat
+ */
+ it = "strcat";
+ (void) strcpy(one, "ijk");
+ check(strcat(one, "lmn") == one, 1); /* Returned value. */
+ equal(one, "ijklmn", 2); /* Basic test. */
+
+ (void) strcpy(one, "x");
+ (void) strcat(one, "yz");
+ equal(one, "xyz", 3); /* Writeover. */
+ equal(one+4, "mn", 4); /* Wrote too much? */
+
+ (void) strcpy(one, "gh");
+ (void) strcpy(two, "ef");
+ (void) strcat(one, two);
+ equal(one, "ghef", 5); /* Basic test encore. */
+ equal(two, "ef", 6); /* Stomped on source? */
+
+ (void) strcpy(one, "");
+ (void) strcat(one, "");
+ equal(one, "", 7); /* Boundary conditions. */
+ (void) strcpy(one, "ab");
+ (void) strcat(one, "");
+ equal(one, "ab", 8);
+ (void) strcpy(one, "");
+ (void) strcat(one, "cd");
+ equal(one, "cd", 9);
+
+ /*
+ * strncat - first test it as strcat, with big counts, then
+ * test the count mechanism.
+ */
+ it = "strncat";
+ (void) strcpy(one, "ijk");
+ check(strncat(one, "lmn", 99) == one, 1); /* Returned value. */
+ equal(one, "ijklmn", 2); /* Basic test. */
+
+ (void) strcpy(one, "x");
+ (void) strncat(one, "yz", 99);
+ equal(one, "xyz", 3); /* Writeover. */
+ equal(one+4, "mn", 4); /* Wrote too much? */
+
+ (void) strcpy(one, "gh");
+ (void) strcpy(two, "ef");
+ (void) strncat(one, two, 99);
+ equal(one, "ghef", 5); /* Basic test encore. */
+ equal(two, "ef", 6); /* Stomped on source? */
+
+ (void) strcpy(one, "");
+ (void) strncat(one, "", 99);
+ equal(one, "", 7); /* Boundary conditions. */
+ (void) strcpy(one, "ab");
+ (void) strncat(one, "", 99);
+ equal(one, "ab", 8);
+ (void) strcpy(one, "");
+ (void) strncat(one, "cd", 99);
+ equal(one, "cd", 9);
+
+ (void) strcpy(one, "ab");
+ (void) strncat(one, "cdef", 2);
+ equal(one, "abcd", 10); /* Count-limited. */
+
+ (void) strncat(one, "gh", 0);
+ equal(one, "abcd", 11); /* Zero count. */
+
+ (void) strncat(one, "gh", 2);
+ equal(one, "abcdgh", 12); /* Count and length equal. */
+
+ /*
+ * strncmp - first test as strcmp with big counts, then test
+ * count code.
+ */
+ it = "strncmp";
+ check(strncmp("", "", 99) == 0, 1); /* Trivial case. */
+ check(strncmp("a", "a", 99) == 0, 2); /* Identity. */
+ check(strncmp("abc", "abc", 99) == 0, 3); /* Multicharacter. */
+ check(strncmp("abc", "abcd", 99) < 0, 4); /* Length unequal. */
+ check(strncmp("abcd", "abc", 99) > 0, 5);
+ check(strncmp("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */
+ check(strncmp("abce", "abcd", 99) > 0, 7);
+ check(strncmp("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */
+ if (charsigned) /* Sign-bit comparison. */
+ check(strncmp("a\203", "a\003", 2) < 0, 9);
+ else
+ check(strncmp("a\203", "a\003", 2) > 0, 9);
+ check(strncmp("abce", "abcd", 3) == 0, 10); /* Count limited. */
+ check(strncmp("abce", "abc", 3) == 0, 11); /* Count == length. */
+ check(strncmp("abcd", "abce", 4) < 0, 12); /* Nudging limit. */
+ check(strncmp("abc", "def", 0) == 0, 13); /* Zero count. */
+
+ /*
+ * strncpy - testing is a bit different because of odd semantics
+ */
+ it = "strncpy";
+ check(strncpy(one, "abc", 4) == one, 1); /* Returned value. */
+ equal(one, "abc", 2); /* Did the copy go right? */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) strncpy(one, "xyz", 2);
+ equal(one, "xycdefgh", 3); /* Copy cut by count. */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) strncpy(one, "xyz", 3); /* Copy cut just before NUL. */
+ equal(one, "xyzdefgh", 4);
+
+ (void) strcpy(one, "abcdefgh");
+ (void) strncpy(one, "xyz", 4); /* Copy just includes NUL. */
+ equal(one, "xyz", 5);
+ equal(one+4, "efgh", 6); /* Wrote too much? */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) strncpy(one, "xyz", 5); /* Copy includes padding. */
+ equal(one, "xyz", 7);
+ equal(one+4, "", 8);
+ equal(one+5, "fgh", 9);
+
+ (void) strcpy(one, "abc");
+ (void) strncpy(one, "xyz", 0); /* Zero-length copy. */
+ equal(one, "abc", 10);
+
+ (void) strncpy(one, "", 2); /* Zero-length source. */
+ equal(one, "", 11);
+ equal(one+1, "", 12);
+ equal(one+2, "c", 13);
+
+ (void) strcpy(one, "hi there");
+ (void) strncpy(two, one, 9);
+ equal(two, "hi there", 14); /* Just paranoia. */
+ equal(one, "hi there", 15); /* Stomped on source? */
+
+ /*
+ * strlen
+ */
+ it = "strlen";
+ check(strlen("") == 0, 1); /* Empty. */
+ check(strlen("a") == 1, 2); /* Single char. */
+ check(strlen("abcd") == 4, 3); /* Multiple chars. */
+
+ /*
+ * strchr
+ */
+ it = "strchr";
+ check(strchr("abcd", 'z') == NULL, 1); /* Not found. */
+ (void) strcpy(one, "abcd");
+ check(strchr(one, 'c') == one+2, 2); /* Basic test. */
+ check(strchr(one, 'd') == one+3, 3); /* End of string. */
+ check(strchr(one, 'a') == one, 4); /* Beginning. */
+ check(strchr(one, '\0') == one+4, 5); /* Finding NUL. */
+ (void) strcpy(one, "ababa");
+ check(strchr(one, 'b') == one+1, 6); /* Finding first. */
+ (void) strcpy(one, "");
+ check(strchr(one, 'b') == NULL, 7); /* Empty string. */
+ check(strchr(one, '\0') == one, 8); /* NUL in empty string. */
+
+ /*
+ * index - just like strchr
+ */
+ it = "index";
+ check(index("abcd", 'z') == NULL, 1); /* Not found. */
+ (void) strcpy(one, "abcd");
+ check(index(one, 'c') == one+2, 2); /* Basic test. */
+ check(index(one, 'd') == one+3, 3); /* End of string. */
+ check(index(one, 'a') == one, 4); /* Beginning. */
+ check(index(one, '\0') == one+4, 5); /* Finding NUL. */
+ (void) strcpy(one, "ababa");
+ check(index(one, 'b') == one+1, 6); /* Finding first. */
+ (void) strcpy(one, "");
+ check(index(one, 'b') == NULL, 7); /* Empty string. */
+ check(index(one, '\0') == one, 8); /* NUL in empty string. */
+
+ /*
+ * strrchr
+ */
+ it = "strrchr";
+ check(strrchr("abcd", 'z') == NULL, 1); /* Not found. */
+ (void) strcpy(one, "abcd");
+ check(strrchr(one, 'c') == one+2, 2); /* Basic test. */
+ check(strrchr(one, 'd') == one+3, 3); /* End of string. */
+ check(strrchr(one, 'a') == one, 4); /* Beginning. */
+ check(strrchr(one, '\0') == one+4, 5); /* Finding NUL. */
+ (void) strcpy(one, "ababa");
+ check(strrchr(one, 'b') == one+3, 6); /* Finding last. */
+ (void) strcpy(one, "");
+ check(strrchr(one, 'b') == NULL, 7); /* Empty string. */
+ check(strrchr(one, '\0') == one, 8); /* NUL in empty string. */
+
+ /*
+ * rindex - just like strrchr
+ */
+ it = "rindex";
+ check(rindex("abcd", 'z') == NULL, 1); /* Not found. */
+ (void) strcpy(one, "abcd");
+ check(rindex(one, 'c') == one+2, 2); /* Basic test. */
+ check(rindex(one, 'd') == one+3, 3); /* End of string. */
+ check(rindex(one, 'a') == one, 4); /* Beginning. */
+ check(rindex(one, '\0') == one+4, 5); /* Finding NUL. */
+ (void) strcpy(one, "ababa");
+ check(rindex(one, 'b') == one+3, 6); /* Finding last. */
+ (void) strcpy(one, "");
+ check(rindex(one, 'b') == NULL, 7); /* Empty string. */
+ check(rindex(one, '\0') == one, 8); /* NUL in empty string. */
+}
+
+second()
+{
+ /*
+ * strpbrk - somewhat like strchr
+ */
+ it = "strpbrk";
+ check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */
+ (void) strcpy(one, "abcd");
+ check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
+ check(strpbrk(one, "d") == one+3, 3); /* End of string. */
+ check(strpbrk(one, "a") == one, 4); /* Beginning. */
+ check(strpbrk(one, "") == NULL, 5); /* Empty search list. */
+ check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */
+ (void) strcpy(one, "abcabdea");
+ check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
+ check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */
+ check(strpbrk(one, "db") == one+1, 9); /* Another variant. */
+ (void) strcpy(one, "");
+ check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */
+ check(strpbrk(one, "") == NULL, 11); /* Both strings empty. */
+
+#if 0
+ /*
+ * strstr - somewhat like strchr
+ */
+ it = "strstr";
+ check(strstr("abcd", "z") == NULL, 1); /* Not found. */
+ check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */
+ (void) strcpy(one, "abcd");
+ check(strstr(one, "c") == one+2, 3); /* Basic test. */
+ check(strstr(one, "bc") == one+1, 4); /* Multichar. */
+ check(strstr(one, "d") == one+3, 5); /* End of string. */
+ check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
+ check(strstr(one, "abc") == one, 7); /* Beginning. */
+ check(strstr(one, "abcd") == one, 8); /* Exact match. */
+ check(strstr(one, "abcde") == NULL, 9); /* Too long. */
+ check(strstr(one, "de") == NULL, 10); /* Past end. */
+ check(strstr(one, "") == one+4, 11); /* Finding empty. */
+ (void) strcpy(one, "ababa");
+ check(strstr(one, "ba") == one+1, 12); /* Finding first. */
+ (void) strcpy(one, "");
+ check(strstr(one, "b") == NULL, 13); /* Empty string. */
+ check(strstr(one, "") == one, 14); /* Empty in empty string. */
+ (void) strcpy(one, "bcbca");
+ check(strstr(one, "bca") == one+2, 15); /* False start. */
+ (void) strcpy(one, "bbbcabbca");
+ check(strstr(one, "bbca") == one+1, 16); /* With overlap. */
+#endif
+
+ /*
+ * strspn
+ */
+ it = "strspn";
+ check(strspn("abcba", "abc") == 5, 1); /* Whole string. */
+ check(strspn("abcba", "ab") == 2, 2); /* Partial. */
+ check(strspn("abc", "qx") == 0, 3); /* None. */
+ check(strspn("", "ab") == 0, 4); /* Null string. */
+ check(strspn("abc", "") == 0, 5); /* Null search list. */
+
+ /*
+ * strcspn
+ */
+ it = "strcspn";
+ check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */
+ check(strcspn("abcba", "cx") == 2, 2); /* Partial. */
+ check(strcspn("abc", "abc") == 0, 3); /* None. */
+ check(strcspn("", "ab") == 0, 4); /* Null string. */
+ check(strcspn("abc", "") == 3, 5); /* Null search list. */
+
+ /*
+ * strtok - the hard one
+ */
+ it = "strtok";
+ (void) strcpy(one, "first, second, third");
+ equal(strtok(one, ", "), "first", 1); /* Basic test. */
+ equal(one, "first", 2);
+ equal(strtok((char *)NULL, ", "), "second", 3);
+ equal(strtok((char *)NULL, ", "), "third", 4);
+ check(strtok((char *)NULL, ", ") == NULL, 5);
+ (void) strcpy(one, ", first, ");
+ equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
+ check(strtok((char *)NULL, ", ") == NULL, 7);
+ (void) strcpy(one, "1a, 1b; 2a, 2b");
+ equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */
+ equal(strtok((char *)NULL, "; "), "1b", 9);
+ equal(strtok((char *)NULL, ", "), "2a", 10);
+ (void) strcpy(two, "x-y");
+ equal(strtok(two, "-"), "x", 11); /* New string before done. */
+ equal(strtok((char *)NULL, "-"), "y", 12);
+ check(strtok((char *)NULL, "-") == NULL, 13);
+ (void) strcpy(one, "a,b, c,, ,d");
+ equal(strtok(one, ", "), "a", 14); /* Different separators. */
+ equal(strtok((char *)NULL, ", "), "b", 15);
+ equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */
+ equal(strtok((char *)NULL, " ,"), "d", 17);
+ check(strtok((char *)NULL, ", ") == NULL, 18);
+ check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */
+ (void) strcpy(one, ", ");
+ check(strtok(one, ", ") == NULL, 20); /* No tokens. */
+ (void) strcpy(one, "");
+ check(strtok(one, ", ") == NULL, 21); /* Empty string. */
+ (void) strcpy(one, "abc");
+ equal(strtok(one, ", "), "abc", 22); /* No delimiters. */
+ check(strtok((char *)NULL, ", ") == NULL, 23);
+ (void) strcpy(one, "abc");
+ equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */
+ check(strtok((char *)NULL, "") == NULL, 25);
+ (void) strcpy(one, "abcdefgh");
+ (void) strcpy(one, "a,b,c");
+ equal(strtok(one, ","), "a", 26); /* Basics again... */
+ equal(strtok((char *)NULL, ","), "b", 27);
+ equal(strtok((char *)NULL, ","), "c", 28);
+ check(strtok((char *)NULL, ",") == NULL, 29);
+ equal(one+6, "gh", 30); /* Stomped past end? */
+ equal(one, "a", 31); /* Stomped old tokens? */
+ equal(one+2, "b", 32);
+ equal(one+4, "c", 33);
+
+ /*
+ * memcmp
+ */
+ it = "memcmp";
+ check(memcmp("a", "a", 1) == 0, 1); /* Identity. */
+ check(memcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
+ check(memcmp("abcd", "abce", 4) < 0, 3); /* Honestly unequal. */
+ check(memcmp("abce", "abcd", 4) > 0, 4);
+ check(memcmp("alph", "beta", 4) < 0, 5);
+ if (charsigned) /* Sign-bit comparison. */
+ check(memcmp("a\203", "a\003", 2) < 0, 6);
+ else
+ check(memcmp("a\203", "a\003", 2) > 0, 6);
+ check(memcmp("abce", "abcd", 3) == 0, 7); /* Count limited. */
+ check(memcmp("abc", "def", 0) == 0, 8); /* Zero count. */
+
+ /*
+ * memchr
+ */
+ it = "memchr";
+ check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */
+ (void) strcpy(one, "abcd");
+ check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */
+ check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */
+ check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
+ check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */
+ (void) strcpy(one, "ababa");
+ check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */
+ check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */
+ check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
+ (void) strcpy(one, "a\203b");
+ check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */
+
+ /*
+ * memcpy
+ *
+ * Note that X3J11 says memcpy must work regardless of overlap.
+ * The SVID says it might fail.
+ */
+ it = "memcpy";
+ check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */
+ equal(one, "abc", 2); /* Did the copy go right? */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) memcpy(one+1, "xyz", 2);
+ equal(one, "axydefgh", 3); /* Basic test. */
+
+ (void) strcpy(one, "abc");
+ (void) memcpy(one, "xyz", 0);
+ equal(one, "abc", 4); /* Zero-length copy. */
+
+ (void) strcpy(one, "hi there");
+ (void) strcpy(two, "foo");
+ (void) memcpy(two, one, 9);
+ equal(two, "hi there", 5); /* Just paranoia. */
+ equal(one, "hi there", 6); /* Stomped on source? */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) memcpy(one+1, one, 9);
+ equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) memcpy(one+1, one+2, 7);
+ equal(one, "acdefgh", 8); /* Overlap, left-to-right. */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) memcpy(one, one, 9);
+ equal(one, "abcdefgh", 9); /* 100% overlap. */
+
+ /*
+ * memccpy - first test like memcpy, then the search part
+ *
+ * The SVID, the only place where memccpy is mentioned, says
+ * overlap might fail, so we don't try it. Besides, it's hard
+ * to see the rationale for a non-left-to-right memccpy.
+ */
+ it = "memccpy";
+ check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */
+ equal(one, "abc", 2); /* Did the copy go right? */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) memccpy(one+1, "xyz", 'q', 2);
+ equal(one, "axydefgh", 3); /* Basic test. */
+
+ (void) strcpy(one, "abc");
+ (void) memccpy(one, "xyz", 'q', 0);
+ equal(one, "abc", 4); /* Zero-length copy. */
+
+ (void) strcpy(one, "hi there");
+ (void) strcpy(two, "foo");
+ (void) memccpy(two, one, 'q', 9);
+ equal(two, "hi there", 5); /* Just paranoia. */
+ equal(one, "hi there", 6); /* Stomped on source? */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) strcpy(two, "horsefeathers");
+ check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
+ equal(one, "abcdefgh", 8); /* Source intact? */
+ equal(two, "abcdefeathers", 9); /* Copy correct? */
+
+ (void) strcpy(one, "abcd");
+ (void) strcpy(two, "bumblebee");
+ check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */
+ equal(two, "aumblebee", 11);
+ check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */
+ equal(two, "abcdlebee", 13);
+ (void) strcpy(one, "xyz");
+ check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */
+ equal(two, "xbcdlebee", 15);
+
+ /*
+ * memset
+ */
+ it = "memset";
+ (void) strcpy(one, "abcdefgh");
+ check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */
+ equal(one, "axxxefgh", 2); /* Basic test. */
+
+ (void) memset(one+2, 'y', 0);
+ equal(one, "axxxefgh", 3); /* Zero-length set. */
+
+ (void) memset(one+5, 0, 1);
+ equal(one, "axxxe", 4); /* Zero fill. */
+ equal(one+6, "gh", 5); /* And the leftover. */
+
+ (void) memset(one+2, 010045, 1);
+ equal(one, "ax\045xe", 6); /* Unsigned char convert. */
+
+ /*
+ * bcopy - much like memcpy
+ *
+ * Berklix manual is silent about overlap, so don't test it.
+ */
+ it = "bcopy";
+ (void) bcopy("abc", one, 4);
+ equal(one, "abc", 1); /* Simple copy. */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) bcopy("xyz", one+1, 2);
+ equal(one, "axydefgh", 2); /* Basic test. */
+
+ (void) strcpy(one, "abc");
+ (void) bcopy("xyz", one, 0);
+ equal(one, "abc", 3); /* Zero-length copy. */
+
+ (void) strcpy(one, "hi there");
+ (void) strcpy(two, "foo");
+ (void) bcopy(one, two, 9);
+ equal(two, "hi there", 4); /* Just paranoia. */
+ equal(one, "hi there", 5); /* Stomped on source? */
+
+ /*
+ * bzero
+ */
+ it = "bzero";
+ (void) strcpy(one, "abcdef");
+ bzero(one+2, 2);
+ equal(one, "ab", 1); /* Basic test. */
+ equal(one+3, "", 2);
+ equal(one+4, "ef", 3);
+
+ (void) strcpy(one, "abcdef");
+ bzero(one+2, 0);
+ equal(one, "abcdef", 4); /* Zero-length copy. */
+
+ /*
+ * bcmp - somewhat like memcmp
+ */
+ it = "bcmp";
+ check(bcmp("a", "a", 1) == 0, 1); /* Identity. */
+ check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
+ check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
+ check(bcmp("abce", "abcd", 4) != 0, 4);
+ check(bcmp("alph", "beta", 4) != 0, 5);
+ check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */
+ check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
+
+#ifdef ERR
+ /*
+ * strerror - VERY system-dependent
+ */
+ it = "strerror";
+ f = open("/", 1); /* Should always fail. */
+ check(f < 0 && errno > 0 && errno < sys_nerr, 1);
+ equal(strerror(errno), sys_errlist[errno], 2);
+#ifdef UNIXERR
+ equal(strerror(errno), "Is a directory", 3);
+#endif
+#ifdef BERKERR
+ equal(strerror(errno), "Permission denied", 3);
+#endif
+#endif
+}
diff --git a/dmake/dbug/malloc/testmlc.c b/dmake/dbug/malloc/testmlc.c
new file mode 100644
index 000000000000..16e11736cc18
--- /dev/null
+++ b/dmake/dbug/malloc/testmlc.c
@@ -0,0 +1,176 @@
+/* NOT copyright by SoftQuad Inc. -- msb, 1988 */
+#ifndef lint
+static char *SQ_SccsId = "@(#)mtest3.c 1.2 88/08/25";
+#endif
+#include <stdio.h>
+/*
+** looptest.c -- intensive allocator tester
+**
+** Usage: looptest
+**
+** History:
+** 4-Feb-1987 rtech!daveb
+*/
+
+# ifdef SYS5
+# define random rand
+# else
+# include <sys/vadvise.h>
+# endif
+
+# include <stdio.h>
+# include <signal.h>
+# include <setjmp.h>
+
+# define MAXITER 1000000 /* main loop iterations */
+# define MAXOBJS 1000 /* objects in pool */
+# define BIGOBJ 90000 /* max size of a big object */
+# define TINYOBJ 80 /* max size of a small object */
+# define BIGMOD 100 /* 1 in BIGMOD is a BIGOBJ */
+# define STATMOD 10000 /* interation interval for status */
+
+main( argc, argv )
+int argc;
+char **argv;
+{
+ register int **objs; /* array of objects */
+ register int *sizes; /* array of object sizes */
+ register int n; /* iteration counter */
+ register int i; /* object index */
+ register int size; /* object size */
+ register int r; /* random number */
+
+ int objmax; /* max size this iteration */
+ int cnt; /* number of allocated objects */
+ int nm = 0; /* number of mallocs */
+ int nre = 0; /* number of reallocs */
+ int nal; /* number of allocated objects */
+ int nfre; /* number of free list objects */
+ long alm; /* memory in allocated objects */
+ long frem; /* memory in free list */
+ long startsize; /* size at loop start */
+ long endsize; /* size at loop exit */
+ long maxiter = 0; /* real max # iterations */
+
+ extern char end; /* memory before heap */
+ char *calloc();
+ char *malloc();
+ char *sbrk();
+ long atol();
+
+# ifndef SYS5
+ /* your milage may vary... */
+ vadvise( VA_ANOM );
+# endif
+
+ if (argc > 1)
+ maxiter = atol (argv[1]);
+ if (maxiter <= 0)
+ maxiter = MAXITER;
+
+ printf("MAXITER %d MAXOBJS %d ", maxiter, MAXOBJS );
+ printf("BIGOBJ %d, TINYOBJ %d, nbig/ntiny 1/%d\n",
+ BIGOBJ, TINYOBJ, BIGMOD );
+ fflush( stdout );
+
+ if( NULL == (objs = (int **)calloc( MAXOBJS, sizeof( *objs ) ) ) )
+ {
+ fprintf(stderr, "Can't allocate memory for objs array\n");
+ exit(1);
+ }
+
+ if( NULL == ( sizes = (int *)calloc( MAXOBJS, sizeof( *sizes ) ) ) )
+ {
+ fprintf(stderr, "Can't allocate memory for sizes array\n");
+ exit(1);
+ }
+
+ /* as per recent discussion on net.lang.c, calloc does not
+ ** necessarily fill in NULL pointers...
+ */
+ for( i = 0; i < MAXOBJS; i++ )
+ objs[ i ] = NULL;
+
+ startsize = sbrk(0) - &end;
+ printf( "Memory use at start: %d bytes\n", startsize );
+ fflush(stdout);
+
+ printf("Starting the test...\n");
+ fflush(stdout);
+ for( n = 0; n < maxiter ; n++ )
+ {
+ if( !(n % STATMOD) )
+ {
+ printf("%d iterations\n", n);
+ fflush(stdout);
+ }
+
+ /* determine object of interst and it's size */
+
+ r = random();
+ objmax = ( r % BIGMOD ) ? TINYOBJ : BIGOBJ;
+ size = r % objmax;
+ i = r % (MAXOBJS - 1);
+
+ /* either replace the object of get a new one */
+
+ if( objs[ i ] == NULL )
+ {
+ objs[ i ] = (int *)malloc( size );
+ nm++;
+ }
+ else
+ {
+ /* don't keep bigger objects around */
+ if( size > sizes[ i ] )
+ {
+ objs[ i ] = (int *)realloc( objs[ i ], size );
+ nre++;
+ }
+ else
+ {
+ free( objs[ i ] );
+ objs[ i ] = (int *)malloc( size );
+ nm++;
+ }
+ }
+
+ sizes[ i ] = size;
+ if( objs[ i ] == NULL )
+ {
+ printf("\nCouldn't allocate %d byte object!\n",
+ size );
+ break;
+ }
+ } /* for() */
+
+ printf( "\n" );
+ cnt = 0;
+ for( i = 0; i < MAXOBJS; i++ )
+ if( objs[ i ] )
+ cnt++;
+
+ printf( "Did %d iterations, %d objects, %d mallocs, %d reallocs\n",
+ n, cnt, nm, nre );
+ printf( "Memory use at end: %d bytes\n", sbrk(0) - &end );
+ fflush( stdout );
+
+ /* free all the objects */
+ for( i = 0; i < MAXOBJS; i++ )
+ if( objs[ i ] != NULL )
+ free( objs[ i ] );
+
+ endsize = sbrk(0) - &end;
+ printf( "Memory use after free: %d bytes\n", endsize );
+ fflush( stdout );
+
+ if( startsize != endsize )
+ printf("startsize %d != endsize %d\n", startsize, endsize );
+
+ free( objs );
+ free( sizes );
+
+ malloc_dump(2);
+ exit( 0 );
+}
+
diff --git a/dmake/dbug/malloc/tostring.c b/dmake/dbug/malloc/tostring.c
new file mode 100644
index 000000000000..5d04a1e7e282
--- /dev/null
+++ b/dmake/dbug/malloc/tostring.c
@@ -0,0 +1,169 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+#include "tostring.h"
+
+/*
+ * Function: tostring()
+ *
+ * Purpose: to convert an integer to an ascii display string
+ *
+ * Arguments: buf - place to put the
+ * val - integer to convert
+ * len - length of output field (0 if just enough to hold data)
+ * base - base for number conversion (only works for base <= 16)
+ * fill - fill char when len > # digits
+ *
+ * Returns: length of string
+ *
+ * Narrative: IF fill character is non-blank
+ * Determine base
+ * If base is HEX
+ * add "0x" to begining of string
+ * IF base is OCTAL
+ * add "0" to begining of string
+ *
+ * While value is greater than zero
+ * use val % base as index into xlation str to get cur char
+ * divide val by base
+ *
+ * Determine fill-in length
+ *
+ * Fill in fill chars
+ *
+ * Copy in number
+ *
+ *
+ * Mod History:
+ * 90/01/24 cpcahil Initial revision.
+ */
+
+#ifndef lint
+static
+char rcs_hdr[] = "$Id: tostring.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $";
+#endif
+
+#define T_LEN 10
+
+int
+tostring(buf,val,len,base,fill)
+ int base;
+ char * buf;
+ char fill;
+ int len;
+ int val;
+
+{
+ char * bufstart = buf;
+ int i = T_LEN;
+ char * xbuf = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ char tbuf[T_LEN];
+
+ /*
+ * if we are filling with non-blanks, make sure the
+ * proper start string is added
+ */
+ if( fill != ' ' )
+ {
+ switch(base)
+ {
+ case B_HEX:
+ *(buf++) = '0';
+ *(buf++) = 'x';
+ if( len )
+ {
+ len -= 2;
+ }
+ break;
+ case B_OCTAL:
+ *(buf++) = fill;
+ if( len )
+ {
+ len--;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ while( val > 0 )
+ {
+ tbuf[--i] = xbuf[val % base];
+ val = val / base;
+ }
+
+ if( len )
+ {
+ len -= (T_LEN - i);
+
+ if( len > 0 )
+ {
+ while(len-- > 0)
+ {
+ *(buf++) = fill;
+ }
+ }
+ else
+ {
+ /*
+ * string is too long so we must truncate
+ * off some characters. We do this the easiest
+ * way by just incrementing i. This means the
+ * most significant digits are lost.
+ */
+ while( len++ < 0 )
+ {
+ i++;
+ }
+ }
+ }
+
+ while( i < T_LEN )
+ {
+ *(buf++) = tbuf[i++];
+ }
+
+ return( (int) (buf - bufstart) );
+
+} /* tostring(... */
+
+/*
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1 1997/09/22 14:51:11 hjs
+ * dmake 4.1 orginal sourcen
+ *
+ * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura
+ * dmake gold 4.1.00 initial import
+ *
+ * Revision 1.1.1.1 1996/10/27 07:30:15 dvadura
+ * Dmake 4.1 Initial Import
+ *
+ * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura
+ * Initial import for final release of dmake 4.1
+ *
+ * Revision 1.1 1994/10/06 17:43:20 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1994/10/06 03:45:29 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1992/01/24 03:29:16 dvadura
+ * dmake Version 3.8, Initial revision
+ *
+ * Revision 1.4 90/05/11 00:13:11 cpcahil
+ * added copyright statment
+ *
+ * Revision 1.3 90/02/24 21:50:33 cpcahil
+ * lots of lint fixes
+ *
+ * Revision 1.2 90/02/24 17:29:42 cpcahil
+ * changed $Header to $Id so full path wouldnt be included as part of rcs
+ * id string
+ *
+ * Revision 1.1 90/02/22 23:17:44 cpcahil
+ * Initial revision
+ *
+ */
diff --git a/dmake/dbug/malloc/tostring.h b/dmake/dbug/malloc/tostring.h
new file mode 100644
index 000000000000..566ae2bedf77
--- /dev/null
+++ b/dmake/dbug/malloc/tostring.h
@@ -0,0 +1,43 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+/*
+ * $Id: tostring.h,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $
+ */
+#define B_BIN 2
+#define B_DEC 10
+#define B_HEX 16
+#define B_OCTAL 8
+
+/*
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1 1997/09/22 14:51:11 hjs
+ * dmake 4.1 orginal sourcen
+ *
+ * Revision 1.1.1.1 1997/07/15 16:02:26 dvadura
+ * dmake gold 4.1.00 initial import
+ *
+ * Revision 1.1.1.1 1996/10/27 07:30:15 dvadura
+ * Dmake 4.1 Initial Import
+ *
+ * Revision 1.1.1.1 1996/10/24 05:33:14 dvadura
+ * Initial import for final release of dmake 4.1
+ *
+ * Revision 1.1 1994/10/06 17:43:20 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1994/10/06 03:45:30 dvadura
+ * dmake Release Version 4.0, Initial revision
+ *
+ * Revision 1.1 1992/01/24 03:29:17 dvadura
+ * dmake Version 3.8, Initial revision
+ *
+ * Revision 1.2 90/05/11 00:13:11 cpcahil
+ * added copyright statment
+ *
+ * Revision 1.1 90/02/23 07:09:05 cpcahil
+ * Initial revision
+ *
+ */
diff --git a/dmake/dbug/readme b/dmake/dbug/readme
new file mode 100644
index 000000000000..15efc00a7edc
--- /dev/null
+++ b/dmake/dbug/readme
@@ -0,0 +1,13 @@
+This directory contains two public domain debugging packages.
+
+ 1. Fred Fishes DEBUG macros.
+ 2. Connor P. Cahills malloc library.
+
+Descriptions of both can be found in their respective sub-directories. dbug
+for the DEBUG macros and malloc for the malloc library. I have left the
+malloc distribution intact as it comes from the net except for the changes
+noted in the _changes file.
+
+I thank the authors for making them available for others to use.
+
+-dennis
diff --git a/dmake/dmake.c b/dmake/dmake.c
new file mode 100644
index 000000000000..941c8a203c23
--- /dev/null
+++ b/dmake/dmake.c
@@ -0,0 +1,843 @@
+/* RCS $Id: dmake.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- The main program.
+--
+-- DESCRIPTION
+--
+-- dmake [-#dbug_string] [ options ]
+-- [ macro definitions ] [ target ... ]
+--
+-- This file contains the main command line parser for the
+-- make utility. The valid flags recognized are as follows:
+--
+-- -f file - use file as the makefile
+-- -C file - duplicate console output to file (MSDOS only)
+-- -K file - .KEEP_STATE file
+-- -#dbug_string - dump out debugging info, see below
+-- -v{dfimt} - verbose, print what we are doing, as we do it.
+--
+-- options: (can be catenated, ie -irn == -i -r -n)
+--
+-- -A - enable AUGMAKE special target mapping
+-- -B - enable non-use of TABS to start recipe lines
+-- -c - use non-standard comment scanning
+-- -d - do not use directory cache
+-- -i - ignore errors
+-- -n - trace and print, do not execute commands
+-- -t - touch, update dates without executing commands
+-- -T - do not apply transitive closure on inference rules
+-- -r - don't use internal rules
+-- -s - do your work silently
+-- -S - force Sequential make, overrides -P
+-- -q - check if target is up to date. Does not
+-- do anything. Returns 0 if up to date, -1
+-- otherwise.
+-- -p - print out a version of the makefile
+-- -P# - set value of MAXPROCESS
+-- -E - define environment strings as macros
+-- -e - as -E but done after parsing makefile
+-- -u - force unconditional update of target
+-- -k - make all independent targets even if errors
+-- -V - print out this make version number
+-- -M - Microsoft make compatibility, (* disabled *)
+-- -h - print out usage info
+-- -x - export macro defs to environment
+-- -X - ignore #! lines found in makefile
+--
+-- NOTE: - #ddbug_string is only availabe for versions of dmake that
+-- have been compiled with -DDBUG switch on. Not the case for
+-- distributed versions. Any such versions must be linked
+-- together with a version of Fred Fish's debug code.
+--
+-- NOTE: - in order to compile the code the include file stddef.h
+-- must be shipped with the bundled code.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* Set this flag to one, and the global variables in vextern.h will not
+ * be defined as 'extern', instead they will be defined as global vars
+ * when this module is compiled. */
+#define _DEFINE_GLOBALS_ 1
+
+#include "extern.h"
+#include "sysintf.h"
+#include "patchlvl.h"
+#include "version.h"
+
+#ifndef MSDOS
+#define USAGE \
+"Usage:\n%s [-P#] [-{f|K} file] [-{w|W} target ...] [macro[!][[*][+][:]]=value ...]\n"
+#define USAGE2 \
+"%s [-v{cdfimtw}] [-ABcdeEghiknpqrsStTuVxX] [target ...]\n"
+#else
+#define USAGE \
+"Usage:\n%s [-P#] [-{f|C|K} file] [-{w|W} target ...] [macro[!][[*][+][:]]=value ...]\n"
+#define USAGE2 \
+"%s [-v{cdfimtw}] [-ABcdeEghiknpqrsStTuVxX] [target ...]\n"
+#endif
+
+/* We don't use va_end at all, so define it out so that it doesn't produce
+ * lots of "Value not used" warnings. */
+#ifdef va_end
+#undef va_end
+#endif
+#define va_end(expand_to_null)
+
+/* Make certain that ARG macro is correctly defined. */
+#ifdef ARG
+#undef ARG
+#endif
+#define ARG(a,b) a b
+
+static char *sccid = "Copyright (c) 1990,...,1997 by WTI Corp.";
+static char _warn = TRUE; /* warnings on by default */
+
+static void _do_VPATH();
+static void _do_ReadEnvironment();
+#if !defined(__GNUC__) && !defined(__IBMC__)
+static void _do_f_flag ANSI((char, char *, char **));
+#else
+static void _do_f_flag ANSI((int, char *, char **));
+#endif
+
+PUBLIC void
+main(argc, argv)
+int argc;
+char **argv;
+{
+#ifdef MSDOS
+ char* std_fil_name = NIL(char);
+#endif
+
+ char* fil_name = NIL(char);
+ char* state_name = NIL(char);
+ char* whatif = NIL(char);
+ char* cmdmacs;
+ char* targets;
+ FILE* mkfil;
+ int ex_val;
+ int m_export;
+
+ DB_ENTER("main");
+
+ /* Initialize Global variables to their default values */
+ Prolog(argc, argv);
+ Create_macro_vars();
+ Catch_signals(Quit);
+
+ Def_macro( "MAKECMD", Pname, M_PRECIOUS|M_NOEXPORT );
+ Pname = Basename(Pname);
+
+ DB_PROCESS(Pname);
+ (void) setvbuf(stdout, NULL, _IOLBF, BUFSIZ); /* stdout line buffered */
+
+ Continue = FALSE;
+ Comment = FALSE;
+ Get_env = FALSE;
+ Force = FALSE;
+ Target = FALSE;
+ If_expand = FALSE;
+ Listing = FALSE;
+ Readenv = FALSE;
+ Rules = TRUE;
+ Trace = FALSE;
+ Touch = FALSE;
+ Check = FALSE;
+ Microsoft = FALSE;
+ Makemkf = FALSE;
+ No_exec = FALSE;
+ m_export = FALSE;
+ cmdmacs = NIL(char);
+ targets = NIL(char);
+
+ Verbose = V_NONE;
+ Transitive = TRUE;
+ Nest_level = 0;
+ Line_number = 0;
+ Suppress_temp_file = FALSE;
+ Skip_to_eof = FALSE;
+
+ while( --argc > 0 ) {
+ register char *p;
+ char *q;
+
+ if( *(p = *++argv) == '-' ) {
+ if( p[1] == '\0' ) Fatal("Missing option letter");
+
+ /* copy options to Buffer for $(MFLAGS), strip 'f' and 'C'*/
+ q = strchr(Buffer, '\0');
+ while (*p != '\0') {
+ char c = (*q++ = *p++);
+ if( c == 'f' || c == 'C' ) q--;
+ }
+
+ if( *(q-1) == '-' )
+ q--;
+ else
+ *q++ = ' ';
+
+ *q = '\0';
+
+ for( p = *argv+1; *p; p++) switch (*p) {
+ case 'f':
+ _do_f_flag( 'f', *++argv, &fil_name ); argc--;
+ break;
+
+#if defined(MSDOS) && !defined(OS2)
+ case 'C':
+ _do_f_flag( 'C', *++argv, &std_fil_name ); argc--;
+ Hook_std_writes( std_fil_name );
+ break;
+#endif
+
+ case 'K':
+ _do_f_flag( 'K', *++argv, &state_name ); argc--;
+ Def_macro(".KEEP_STATE", state_name, M_EXPANDED|M_PRECIOUS);
+ break;
+
+ case 'W':
+ case 'w': {
+ CELLPTR wif;
+ _do_f_flag( 'w', *++argv, &whatif ); argc--;
+ wif = Def_cell(whatif);
+ wif->ce_attr |= A_WHATIF;
+ whatif = NIL(char);
+
+ if ( *p == 'W')
+ break;
+ }
+ /*FALLTHRU*/
+
+ case 'n':
+ Trace = TRUE;
+ break;
+
+ case 'k': Continue = TRUE; break;
+ case 'c': Comment = TRUE; break;
+ case 'p': Listing = TRUE; break;
+ case 'r': Rules = FALSE; break;
+ case 't': Touch = TRUE; break;
+ case 'q': Check = TRUE; break;
+ case 'u': Force = TRUE; break;
+ case 'x': m_export = TRUE; break;
+ case 'X': No_exec = TRUE; break;
+ case 'T': Transitive = FALSE; break;
+ case 'e': Get_env = 'e'; break;
+ case 'E': Get_env = 'E'; break;
+
+ case 'V': Version(); Quit(NIL(CELL)); break;
+ case 'A': Def_macro("AUGMAKE", "y", M_EXPANDED); break;
+ case 'B': Def_macro(".NOTABS", "y", M_EXPANDED); break;
+ case 'i': Def_macro(".IGNORE", "y", M_EXPANDED); break;
+ case 's': Def_macro(".SILENT", "y", M_EXPANDED); break;
+ case 'S': Def_macro(".SEQUENTIAL", "y", M_EXPANDED); break;
+ case 'g': Def_macro(".IGNOREGROUP","y", M_EXPANDED); break;
+ case 'd': Def_macro(".DIRCACHE",NIL(char),M_EXPANDED); break;
+
+ case 'v':
+ if( p[-1] != '-' ) Usage(TRUE);
+ while( p[1] ) switch( *++p ) {
+ case 'c': Verbose |= V_DIR_CACHE; break;
+ case 'd': Verbose |= V_DIR_SET; break;
+ case 'f': Verbose |= V_FILE_IO; break;
+ case 'i': Verbose |= V_INFER; break;
+ case 'm': Verbose |= V_MAKE; break;
+ case 't': Verbose |= V_LEAVE_TMP; break;
+ case 'w': Verbose |= V_WARNALL; break;
+
+ default: Usage(TRUE); break;
+ }
+ if( !Verbose ) Verbose = V_ALL;
+ break;
+
+ case 'P':
+ if( p[1] ) {
+ Def_macro( "MAXPROCESS", p+1, M_MULTI|M_EXPANDED );
+ p += strlen(p)-1;
+ }
+ else
+ Fatal( "Missing number for -P flag" );
+ break;
+
+#ifdef DBUG
+ case '#':
+ DB_PUSH(p+1);
+ p += strlen(p)-1;
+ break;
+#endif
+
+ case 'h': Usage(FALSE); break;
+ case 0: break; /* lone - */
+ default: Usage(TRUE); break;
+ }
+ }
+ else if( (q = strchr(p, '=')) != NIL(char) ) {
+ cmdmacs = DmStrAdd( cmdmacs, DmStrDup2(p), TRUE );
+ Parse_macro( p, (q[-1]!='+')?M_PRECIOUS:M_DEFAULT );
+ }
+ else {
+ register CELLPTR cp;
+ targets = DmStrAdd( targets, DmStrDup(p), TRUE );
+ Add_prerequisite(Targets, cp = Def_cell(p), FALSE, FALSE);
+ cp->ce_flag |= F_TARGET;
+ cp->ce_attr |= A_FRINGE;
+ Target = TRUE;
+ }
+ }
+
+ Def_macro( "MAKEMACROS", cmdmacs, M_PRECIOUS|M_NOEXPORT );
+ Def_macro( "MAKETARGETS", targets, M_PRECIOUS|M_NOEXPORT );
+ if( cmdmacs != NIL(char) ) FREE(cmdmacs);
+ if( targets != NIL(char) ) FREE(targets);
+
+ Def_macro( "MFLAGS", Buffer, M_PRECIOUS|M_NOEXPORT );
+ Def_macro( "%", "$@", M_PRECIOUS|M_NOEXPORT );
+
+ if( *Buffer ) Def_macro( "MAKEFLAGS", Buffer+1, M_PRECIOUS|M_NOEXPORT );
+
+ _warn = FALSE; /* disable warnings for builtin rules */
+ ex_val = Target; /* make sure we don't mark any */
+ Target = TRUE; /* of the default rules as */
+ Make_rules(); /* potential targets */
+ _warn = TRUE;
+
+ if( Rules ) {
+ char *fname;
+
+ if( (mkfil=Search_file("MAKESTARTUP", &fname)) != NIL(FILE) ) {
+ Parse(mkfil);
+ Def_macro( "MAKESTARTUP", fname, M_EXPANDED|M_MULTI|M_FORCE );
+ }
+ else
+ Fatal( "Configuration file `%s' not found", fname );
+ }
+
+ Target = ex_val;
+
+ if( Get_env == 'E' ) _do_ReadEnvironment();
+
+ if( fil_name != NIL(char) )
+ mkfil = Openfile( fil_name, FALSE, TRUE );
+ else {
+ /* Search .MAKEFILES dependent list looking for a makefile.
+ */
+ register CELLPTR cp;
+
+ cp = Def_cell( ".MAKEFILES" );
+ mkfil = TryFiles(cp->CE_PRQ);
+ }
+
+ if( mkfil != NIL(FILE) ) {
+ char *f = Filename();
+ char *p;
+
+ if( strcmp(f, "stdin") == 0 ) f = "-";
+ p = DmStrAdd( "-f", f, FALSE );
+ Def_macro( "MAKEFILE", p, M_PRECIOUS|M_NOEXPORT );
+ Parse( mkfil );
+ }
+ else if( !Rules )
+ Fatal( "No `makefile' present" );
+
+ if( Nest_level ) Fatal( "Missing .END for .IF" );
+ if( Get_env == 'e' ) _do_ReadEnvironment();
+
+ _do_VPATH(); /* kludge it up with .SOURCE */
+
+ if( Listing ) Dump(); /* print out the structures */
+ if( Trace ) Glob_attr &= ~A_SILENT; /* make sure we see the trace */
+
+ if( !Target )
+ Fatal( "No target" );
+ else {
+ Test_circle( Root, TRUE );
+ Check_circle_dfa();
+ }
+
+ if( m_export ) {
+ int i;
+
+ for( i=0; i<HASH_TABLE_SIZE; ++i ) {
+ HASHPTR hp = Macs[i];
+
+ while( hp ) {
+ if( !(hp->ht_flag & M_NOEXPORT) && hp->ht_value != NIL(char) )
+ if( Write_env_string(hp->ht_name, hp->ht_value) != 0 )
+ Warning( "Could not export %s", hp->ht_name );
+ hp = hp->ht_next;
+ }
+ }
+ }
+
+ if( Buffer != NIL(char) ) {FREE( Buffer ); Buffer = NIL(char);}
+ if( Trace ) Def_macro(".SEQUENTIAL", "y", M_EXPANDED);
+ if( Glob_attr & A_SEQ ) Def_macro( "MAXPROCESS", "1", M_EXPANDED|M_FORCE );
+
+ ex_val = Make_targets();
+
+ Clear_signals();
+ Epilog(ex_val); /* Does not return -- EVER */
+}
+
+
+static void
+_do_f_flag( flag, name, fname )
+char flag;
+char *name;
+char **fname;
+{
+ if( *fname == NIL(char) ) {
+ if( name != NIL(char) ) {
+ *fname = name;
+ } else
+ Fatal("No file name for -%c", flag);
+ } else
+ Fatal("Only one `-%c file' allowed", flag);
+}
+
+
+static void
+_do_ReadEnvironment()
+{
+ t_attr saveattr = Glob_attr;
+
+ Glob_attr |= A_SILENT;
+ ReadEnvironment();
+ Glob_attr = saveattr;
+}
+
+
+static void
+_do_VPATH()
+{
+ HASHPTR hp;
+ char *_rl[2];
+ extern char **Rule_tab;
+
+ hp = GET_MACRO("VPATH");
+ if( hp == NIL(HASH) ) return;
+
+ _rl[0] = ".SOURCE :^ $(VPATH:s/:/ /)";
+ _rl[1] = NIL(char);
+
+ Rule_tab = _rl;
+ Parse( NIL(FILE) );
+}
+
+
+/* The file table and pointer to the next FREE slot for use by both
+ Openfile and Closefile. Each open stacks the new file onto the open
+ file stack, and a corresponding close will close the passed file, and
+ return the next file on the stack. The maximum number of nested
+ include files is limited by the value of MAX_INC_DEPTH */
+
+static struct {
+ FILE *file; /* file pointer */
+ char *name; /* name of file */
+ int numb; /* line number */
+} ftab[ MAX_INC_DEPTH ];
+
+static int next_file_slot = 0;
+
+/* Set the proper macro value to reflect the depth of the .INCLUDE directives
+ * and the name of the file we are reading.
+ */
+static void
+_set_inc_depth()
+{
+ char buf[10];
+ sprintf( buf, "%d", next_file_slot );
+ Def_macro( "INCDEPTH", buf, M_MULTI|M_NOEXPORT );
+ Def_macro( "INCFILENAME",
+ next_file_slot ? ftab[next_file_slot-1].name : "",
+ M_MULTI|M_NOEXPORT );
+}
+
+
+PUBLIC FILE *
+Openfile(name, mode, err)/*
+===========================
+ This routine opens a file for input or output depending on mode.
+ If the file name is `-' then it returns standard input.
+ The file is pushed onto the open file stack. */
+char *name;
+int mode;
+int err;
+{
+ FILE *fil;
+
+ DB_ENTER("Openfile");
+
+ if( name == NIL(char) || !*name )
+ if( !err )
+ DB_RETURN(NIL(FILE));
+ else
+ Fatal( "Openfile: NIL filename" );
+
+ if( next_file_slot == MAX_INC_DEPTH )
+ Fatal( "Too many open files. Max nesting level is %d.", MAX_INC_DEPTH);
+
+ DB_PRINT( "io", ("Opening file [%s], in slot %d", name, next_file_slot) );
+
+ if( strcmp("-", name) == 0 ) {
+ name = "stdin";
+ fil = stdin;
+ }
+ else
+ fil = fopen( name, mode ? "w":"r" );
+
+ if( Verbose & V_FILE_IO )
+ printf( "%s: Openning [%s] for %s", Pname, name, mode?"write":"read" );
+
+ if( fil == NIL(FILE) ) {
+ if( Verbose & V_FILE_IO ) printf( " (fail)\n" );
+ if( err )
+ Fatal( mode ? "Cannot open file %s for write" : "File %s not found",
+ name );
+ }
+ else {
+ if( Verbose & V_FILE_IO ) printf( " (success)\n" );
+ ftab[next_file_slot].file = fil;
+ ftab[next_file_slot].numb = Line_number;
+ ftab[next_file_slot++].name = DmStrDup(name);
+ Line_number = 0;
+ _set_inc_depth();
+ }
+
+ DB_RETURN(fil);
+}
+
+
+PUBLIC FILE *
+Closefile()/*
+=============
+ This routine is used to close the last file opened. This forces make
+ to open files in a last open first close fashion. It returns the
+ file pointer to the next file on the stack, and NULL if the stack is empty.*/
+{
+ DB_ENTER("Closefile");
+
+ if( !next_file_slot )
+ DB_RETURN( NIL(FILE) );
+
+ if( ftab[--next_file_slot].file != stdin ) {
+ DB_PRINT( "io", ("Closing file in slot %d", next_file_slot) );
+
+ if( Verbose & V_FILE_IO )
+ printf( "%s: Closing [%s]\n", Pname, ftab[next_file_slot].name );
+
+ fclose( ftab[next_file_slot].file );
+ FREE( ftab[next_file_slot].name );
+ }
+
+ _set_inc_depth();
+
+ if( next_file_slot > 0 ) {
+ Line_number = ftab[next_file_slot].numb;
+ DB_RETURN( ftab[next_file_slot-1].file );
+ }
+ else
+ Line_number = 0;
+
+ DB_RETURN( NIL(FILE) );
+}
+
+
+PUBLIC FILE *
+Search_file( macname, rname )
+char *macname;
+char **rname;
+{
+ HASHPTR hp;
+ FILE *fil = NIL(FILE);
+ char *fname;
+ char *ename = NIL(char);
+
+ /* order of precedence is:
+ *
+ * MACNAME from command line (precious is marked)
+ * ... via MACNAME:=filename definition.
+ * MACNAME from environment
+ * MACNAME from builtin rules (not precious)
+ */
+
+ if( (hp = GET_MACRO(macname)) != NIL(HASH) )
+ ename = fname = Expand(hp->ht_value);
+
+ if( hp->ht_flag & M_PRECIOUS ) fil = Openfile(fname, FALSE, FALSE);
+
+ if( fil == NIL(FILE) ) {
+ fname=Expand(Read_env_string(macname));
+ if( (fil = Openfile(fname, FALSE, FALSE)) != NIL(FILE) ) FREE(ename);
+ }
+
+ if( fil == NIL(FILE) && hp != NIL(HASH) )
+ fil = Openfile(fname=ename, FALSE, FALSE);
+
+ if( rname ) *rname = fname;
+
+ return(fil);
+}
+
+
+PUBLIC char *
+Filename()/*
+============
+ Return name of file on top of stack */
+{
+ return( next_file_slot==0 ? NIL(char) : ftab[next_file_slot-1].name );
+}
+
+
+PUBLIC int
+Nestlevel()/*
+=============
+ Return the file nesting level */
+{
+ return( next_file_slot );
+}
+
+
+PUBLIC FILE *
+TryFiles(lp)
+LINKPTR lp;
+{
+ FILE *mkfil = NIL(FILE);
+
+ if( lp != NIL(LINK) ) {
+ int s_n, s_t, s_q;
+
+ s_n = Trace;
+ s_t = Touch;
+ s_q = Check;
+
+ Trace = Touch = Check = FALSE;
+ Makemkf = Wait_for_completion = TRUE;
+ mkfil = NIL(FILE);
+
+ for(; lp != NIL(LINK) && mkfil == NIL(FILE); lp=lp->cl_next) {
+ if( lp->cl_prq->ce_attr & A_FRINGE ) continue;
+
+ mkfil = Openfile( lp->cl_prq->CE_NAME, FALSE, FALSE );
+
+ if( mkfil == NIL(FILE) &&
+ Make(lp->cl_prq, NIL(CELL)) != -1 )
+ mkfil = Openfile( lp->cl_prq->CE_NAME, FALSE, FALSE );
+ }
+
+ Trace = s_n;
+ Touch = s_t;
+ Check = s_q;
+ Makemkf = Wait_for_completion = FALSE;
+ }
+
+ return(mkfil);
+}
+
+
+/*
+** print error message from variable arg list
+*/
+
+static int errflg = TRUE;
+static int warnflg = FALSE;
+
+static void
+errargs(fmt, args)
+char *fmt;
+va_list args;
+{
+ int warn = _warn && warnflg && !(Glob_attr & A_SILENT);
+
+ if( errflg || warn ) {
+ char *f = Filename();
+
+ fprintf( stderr, "%s: ", Pname );
+ if( f != NIL(char) ) fprintf(stderr, "%s: line %d: ", f, Line_number);
+
+ if( errflg )
+ fprintf(stderr, "Error -- ");
+ else if( warn )
+ fprintf(stderr, "Warning -- ");
+
+ vfprintf( stderr, fmt, args );
+ putc( '\n', stderr );
+ if( errflg && !Continue ) Quit( NIL(CELL) );
+ }
+}
+
+
+/*
+** Print error message and abort
+*/
+PUBLIC void
+#ifndef __MWERKS__
+Fatal(ARG(char *,fmt), ARG(va_alist_type,va_alist))
+#else
+Fatal(char * fmt, ...)
+#endif
+DARG(char *,fmt)
+DARG(va_alist_type,va_alist)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ Continue = FALSE;
+ errargs(fmt, args);
+ va_end(args);
+}
+
+/*
+** error message and exit (unless -k)
+*/
+PUBLIC void
+#ifndef __MWERKS__
+Error(ARG(char *,fmt), ARG(va_alist_type,va_alist))
+#else
+Error(char * fmt, ...)
+#endif
+DARG(char *,fmt)
+DARG(va_alist_type,va_alist)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ errargs(fmt, args);
+ va_end(args);
+}
+
+
+/*
+** non-fatal message
+*/
+PUBLIC void
+#ifndef __MWERKS__
+Warning(ARG(char *,fmt), ARG(va_alist_type,va_alist))
+#else
+Warning(char * fmt , ...)
+#endif
+DARG(char *,fmt)
+DARG(va_alist_type,va_alist)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ warnflg = TRUE;
+ errflg = FALSE;
+ errargs(fmt, args);
+ errflg = TRUE;
+ warnflg = FALSE;
+ va_end(args);
+}
+
+
+PUBLIC void
+No_ram()
+{
+ Fatal( "No more memory" );
+}
+
+
+PUBLIC void
+Usage( eflag )
+int eflag;
+{
+ register char *p;
+ char *fill;
+
+ fill = DmStrDup(Pname);
+ for(p=fill; *p; p++) *p=' ';
+
+ if( eflag ) {
+ fprintf(stderr, USAGE, Pname);
+ fprintf(stderr, USAGE2, fill);
+ }
+ else {
+ printf(USAGE, Pname);
+ printf(USAGE2, fill);
+ puts(" -P# - set max number of child processes for parallel make");
+ puts(" -f file - use file as the makefile");
+#ifdef MSDOS
+ puts(" -C [+]file - duplicate console output to file, ('+' => append)");
+#endif
+ puts(" -K file - use file as the .KEEP_STATE file");
+ puts(" -w target - show what you would do if 'target' were out of date");
+ puts(" -W target - rebuild pretending that 'target' is out of date");
+ puts(" -v{cdfimtw}- verbose, indicate what we are doing, (-v => -vcdfimtw)");
+ puts(" c => dump directory cache info only" );
+ puts(" d => dump change of directory info only" );
+ puts(" f => dump file open/close info only" );
+ puts(" i => dump inference information only" );
+ puts(" m => dump make of target information only" );
+ puts(" t => keep temporary files when done" );
+ puts(" w => issue non-essential warnings\n" );
+
+ puts("Options: (can be catenated, ie -irn == -i -r -n)");
+ puts(" -A - enable AUGMAKE special target mapping");
+ puts(" -B - enable the use of spaces instead of tabs to start recipes");
+ puts(" -c - use non standard comment scanning");
+ puts(" -d - do not use directory cache");
+ puts(" -E - define environment strings as macros");
+ puts(" -e - same as -E but done after parsing makefile");
+ puts(" -g - disable the special meaning of [ ... ] for group recipes");
+ puts(" -h - print out usage info");
+ puts(" -i - ignore errors");
+ puts(" -k - make independent targets, even if errors");
+ puts(" -n - trace and print, do not execute commands");
+ puts(" -p - print out a version of the makefile");
+ puts(" -q - check if target is up to date. Does not do");
+ puts(" anything. Returns 0 if up to date, 1 otherwise");
+ puts(" -r - don't use internal rules");
+ puts(" -s - do your work silently");
+ puts(" -S - disable parallel (force sequential) make, overrides -P");
+ puts(" -t - touch, update time stamps without executing commands");
+ puts(" -T - do not apply transitive closure on inference rules");
+ puts(" -u - force unconditional update of target");
+ puts(" -V - print out version number");
+ puts(" -x - export macro values to environment");
+ puts(" -X - ignore #! lines at start of makefile");
+ }
+
+ Quit(NIL(CELL));
+}
+
+
+PUBLIC void
+Version()
+{
+ extern char **Rule_tab;
+ char **p;
+
+ printf("%s - %s, ", Pname, sccid);
+ printf("Version %s, PL %d\n\n", VERSION, PATCHLEVEL);
+
+ puts("Default Configuration:");
+ for (p=Rule_tab; *p != NIL(char); p++)
+ printf("\t%s\n", *p);
+
+ printf("\n");
+printf("Please read the file readme/release for the latest release notes.\n");
+#if 0
+printf("\n");
+printf("Please support the DMAKE Reference Manual project. See the file\n");
+printf("readme/release for additional information on where to send contributions.\n");
+printf("Or, send mail to dvadura@plg.uwaterloo.ca for additional information if the\n");
+printf("above file is not readily available.\n");
+#endif
+}
diff --git a/dmake/dmake.h b/dmake/dmake.h
new file mode 100644
index 000000000000..69240f5b2695
--- /dev/null
+++ b/dmake/dmake.h
@@ -0,0 +1,200 @@
+/* RCS $Id: dmake.h,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Global defines for dmake.
+--
+-- DESCRIPTION
+-- All the interesting bits and flags that dmake uses are defined here.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_INCLUDED_
+#define _DMAKE_INCLUDED_
+
+#define MAX_INC_DEPTH 10 /* max of ten nested include files */
+#define MAX_COND_DEPTH 20 /* max nesting level of conditionals */
+#define ERROR_EXIT_VALUE 255 /* return code of aborted make */
+#define CONTINUATION_CHAR '\\' /* line continuation \<nl> */
+#define DEF_ESCAPE_CHAR '\\' /* escape char for used chars */
+#define ESCAPE_CHAR *Escape_char
+#define COMMENT_CHAR '#' /* start of comment chars */
+#define TGT_DEP_SEP ':' /* separator for targets and dependents */
+#define CONDSTART '.' /* start of conditional token eg .IF */
+#define DEF_MAKE_PNAME "dmake"/* default name to use as name of make */
+
+
+/* ............... Hashing function constants ......................... */
+#define HASH_TABLE_SIZE 200 /* See hash.c for description */
+
+
+/* Bit flags for cells and macro definitions. */
+#define M_DEFAULT 0x0000 /* default flag value */
+#define M_MARK 0x0001 /* mark for circularity checks */
+#define M_PRECIOUS 0x0002 /* keep macro, same as A_PRE... */
+#define M_MULTI 0x0004 /* multiple redefinitions ok! */
+#define M_EXPANDED 0x0008 /* macro has been assigned */
+#define M_USED 0x0010 /* macro has been expanded */
+#define M_LITERAL 0x0020 /* don't strip w/s on macro def */
+#define M_NOEXPORT 0x0040 /* don't export macro for -x */
+#define M_FORCE 0x0080 /* Force a macro redefinition */
+#define M_PUSH 0x0100 /* Push previous macro defintn */
+#define M_INIT 0x0200 /* Macro defined initially */
+#define M_VAR_BIT 0x1000 /* macro bit variable */
+#define M_VAR_CHAR 0x2000 /* macro char variable */
+#define M_VAR_STRING 0x4000 /* macro string variable */
+#define M_VAR_INT 0x8000 /* macro integer variable */
+
+#define M_VAR_MASK 0xf000 /* macro variable mask */
+
+
+
+/* Global and target attribute flag definitions.
+ * If you change the values of these or re-order them make appropriate changes
+ * in dump.c so that the output of dmake -p matches the attribute info for a
+ * target. */
+
+#define A_DEFAULT 0x00000 /* default flag value */
+#define A_PRECIOUS 0x00001 /* object is precious */
+#define A_SILENT 0x00002 /* don't echo commands */
+#define A_LIBRARY 0x00004 /* target is an archive */
+#define A_EPILOG 0x00008 /* insert shell epilog code */
+#define A_PROLOG 0x00010 /* insert shell prolog code */
+#define A_IGNORE 0x00020 /* ignore errors */
+#define A_SYMBOL 0x00040 /* lib member is a symbol */
+#define A_NOINFER 0x00080 /* no trans closure from cell */
+#define A_UPDATEALL 0x00100 /* all targets of rule modified */
+#define A_SEQ 0x00200 /* sequential make attribute */
+#define A_SETDIR 0x00400 /* cd to dir when making target */
+#define A_SHELL 0x00800 /* run the recipe using a shell */
+#define A_SWAP 0x01000 /* swap on exec. */
+#define A_MKSARGS 0x02000 /* use MKS argument swapping */
+#define A_PHONY 0x04000 /* .PHONY attribute */
+#define A_NOSTATE 0x08000 /* don't track state for me */
+#define A_IGNOREGROUP 0x10000 /* Ignore group recipe */
+#define A_EXECUTE 0x20000 /* execute this recipe under -n */
+#define A_ERRREMOVE 0x40000 /* remove this target if error */
+#define MAX_ATTR A_ERRREMOVE /* highest valid attribute */
+#define A_LIBRARYM 0x80000 /* target is an archive member */
+#define A_FRINGE 0x100000 /* cell is on the fringe */
+#define A_COMPOSITE 0x200000 /* member of lib(targ) name */
+#define A_FFNAME 0x400000 /* if set, free ce_fname in stat*/
+#define A_UPDATED 0x800000 /* Used to mark cell as updated */
+#define A_ROOT 0x01000000 /* True if it is a root prereq */
+#define A_GROUP 0x02000000 /* True if rule is to be a group*/
+#define A_WHATIF 0x04000000 /* used for WHATIF tests */
+#define A_POOL 0x08000000 /* used for directory pool */
+#define A_ERROR 0x10000000 /* used to halt construction */
+#define A_FIRST 0x20000000 /* used for .INCLUDE termination*/
+
+
+/* Global and target bit flag definitions */
+
+#define F_DEFAULT 0x0000 /* default flag value */
+#define F_MARK 0x0001 /* circularity check mark */
+#define F_MULTI 0x0002 /* multiple rules for target */
+#define F_SINGLE 0x0004 /* exec rules one/prerequisite */
+#define F_TARGET 0x0008 /* marks a target */
+#define F_RULES 0x0010 /* indicates target has rules */
+#define F_GROUP 0x0020 /* indicates that rules are to */
+ /* fed to the shell as a group */
+
+#define F_TRANS 0x0040 /* same as F_STAT not used tgthr*/
+#define F_STAT 0x0040 /* target already stated */
+#define F_VISITED 0x0080 /* target scheduled for make */
+#define F_USED 0x0080 /* used in rulparse.c */
+#define F_SPECIAL 0x0100 /* marks a special target */
+#define F_DFA 0x0200 /* bit for marking added DFA */
+#define F_EXPLICIT 0x0400 /* explicit target in makefile */
+#define F_PERCENT 0x0800 /* marks a target as a % rule */
+#define F_REMOVE 0x1000 /* marks an intermediate target */
+#define F_MAGIC 0x2000 /* marks a magic target */
+#define F_INFER 0x4000 /* target is result of inference*/
+#define F_MADE 0x8000 /* target is manufactured */
+
+
+/* Definitions for the Parser states */
+#define NORMAL_SCAN 0 /* normal processing state */
+#define RULE_SCAN 1 /* scan of rule text */
+
+/* definitions for macro operator types */
+#define M_OP_EQ 1 /* macro operation is '=' 0000 0001 */
+#define M_OP_CL 3 /* macro operation is ':=' 0000 0011 */
+#define M_OP_PL 5 /* macro operation is '+=' 0000 0101 */
+#define M_OP_DF 9 /* macro operation is '*=' 0000 1001 */
+#define M_OP_PLCL 7 /* macro operation is '+:=' 0000 0111 */
+#define M_OP_DFCL 11 /* macro operation is '*:=' 0000 1011 */
+#define M_OP_CM 17 /* macro operation is '?=' 0001 0001 */
+#define M_OP_SI 32 /* macro operation is '!' 0010 ---- */
+
+/* definitions for rule operator types */
+#define R_OP_CL 1 /* rule operation is ':' */
+#define R_OP_DCL 2 /* rule operation is '::' */
+#define R_OP_BG 4 /* rule operation is ':!' */
+#define R_OP_UP 8 /* rule operation is ':^' */
+#define R_OP_MI 16 /* rule operation is ':-' */
+#define R_OP_OR 32 /* rule operation is ':|' */
+
+/* definitions for modifier application in Apply_modifiers in expand.c */
+#define SUFFIX_FLAG 1 /* defines for macro modifier code */
+#define DIRECTORY_FLAG 2
+#define FILE_FLAG 4
+#define WHOLENAME_FLAGS 7
+#define TOLOWER_FLAG 8
+#define TOUPPER_FLAG 16
+#define INFNAME_FLAG 32
+#define JUST_FIRST_FLAG 64
+
+/* special target definitions for use inside dmake */
+#define ST_IF 1
+#define ST_ELSE 2
+#define ST_END 3
+#define ST_REST 4 /* remaining special targets */
+#define ST_INCLUDE 5
+#define ST_SOURCE 7
+#define ST_EXPORT 8
+#define ST_IMPORT 9
+#define ST_ELIF 10
+#define ST_KEEP 11
+#define ST_EXIT 12
+#define ST_IFEQ 13
+#define ST_IFNEQ 14
+
+/* Flags for controling use of -v switch */
+#define V_NONE 0x00
+#define V_LEAVE_TMP 0x01
+#define V_DIR_SET 0x02
+#define V_DIR_CACHE 0x04
+#define V_INFER 0x08
+#define V_MAKE 0x10
+#define V_FILE_IO 0x20
+#define V_WARNALL 0x40
+#define V_ALL (V_LEAVE_TMP | V_DIR_SET | V_INFER | V_MAKE |\
+ V_FILE_IO | V_DIR_CACHE | V_WARNALL)
+
+/* Macro definitions for use inside dmake */
+#define SET_TOKEN(A, B) (A)->tk_str = (B);\
+ (A)->tk_cchar = *(B);\
+ (A)->tk_quote = 1;
+
+#define CLEAR_TOKEN(A) *(A)->tk_str = (A)->tk_cchar
+#define GET_MACRO(A) Get_name(A, Macs, FALSE)
+#define iswhite(C) ((C == ' ') || (C == '\t'))
+#define STOBOOL(A) (A && ((*A | 0x20) == 'y'))
+
+#endif
+
diff --git a/dmake/dmdump.c b/dmake/dmdump.c
new file mode 100644
index 000000000000..9b4b86adf20c
--- /dev/null
+++ b/dmake/dmdump.c
@@ -0,0 +1,259 @@
+/* RCS $Id: dmdump.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Dump the internal dag to stdout.
+--
+-- DESCRIPTION
+-- This file contains the routine that is called to dump a version of
+-- the digested makefile to the standard output. May be useful perhaps
+-- to the ordinary user, and invaluable for debugging make.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+#define M_TEST (M_PRECIOUS | M_VAR_MASK)
+
+static void dump_name ANSI((CELLPTR, int, int));
+static void dump_normal_target ANSI((CELLPTR, CELLPTR, int));
+static void dump_prerequisites ANSI((LINKPTR, CELLPTR, int, int, int));
+static void dump_conditionals ANSI((CELLPTR,STRINGPTR,int,int));
+static void dump_macro ANSI((HASHPTR, int));
+
+
+PUBLIC void
+Dump()/*
+======== Dump onto standard output the digested makefile. Note that
+ the form of the dump is not representative of the contents
+ of the original makefile contents at all */
+{
+ HASHPTR hp;
+ int i;
+
+ DB_ENTER( "Dump" );
+
+ puts( "# Dump of dmake macro variables:" );
+ for( i=0; i<HASH_TABLE_SIZE; i++)
+ for( hp=Macs[i]; hp != NIL(HASH); hp = hp->ht_next ) {
+ int flag = hp->ht_flag;
+ dump_macro(hp, flag);
+ }
+
+ puts( "\n#====================================" );
+ puts( "# Dump of targets:\n" );
+
+ for( i=0; i<HASH_TABLE_SIZE; i++ )
+ for( hp = Defs[i]; hp != NIL(HASH); hp = hp->ht_next )
+ if( !(hp->CP_OWNR->ce_flag & F_PERCENT) ) {
+ if( hp->CP_OWNR == Root )
+ puts( "# ******* ROOT TARGET ********" );
+ if (Targets->ce_prq && hp->CP_OWNR == Targets->ce_prq->cl_prq)
+ puts( "# ******* FIRST USER DEFINED TARGET ******" );
+ dump_normal_target( hp->CP_OWNR,NIL(CELL),hp->CP_OWNR->ce_flag);
+ }
+
+ puts( "\n#====================================" );
+ puts( "# Dump of inference graph\n" );
+
+ for( i=0; i<HASH_TABLE_SIZE; i++ )
+ for( hp = Defs[i]; hp != NIL(HASH); hp = hp->ht_next )
+ if( (hp->CP_OWNR->ce_flag & F_PERCENT) &&
+ !(hp->CP_OWNR->ce_flag & F_MAGIC) )
+ dump_normal_target(hp->CP_OWNR,NIL(CELL),hp->CP_OWNR->ce_flag);
+
+ DB_VOID_RETURN;
+}
+
+
+
+PUBLIC void
+Dump_recipe( sp )/*
+===================
+ Given a string pointer print the recipe line out */
+STRINGPTR sp;
+{
+ char *st;
+ char *nl;
+
+ if( sp == NIL(STRING) ) return;
+
+ putchar( '\t' );
+ if( sp->st_attr & A_SILENT ) putchar( '@' );
+ if( sp->st_attr & A_IGNORE ) putchar( '-' );
+ if( sp->st_attr & A_SHELL ) putchar( '+' );
+ if( sp->st_attr & A_SWAP ) putchar( '%' );
+
+ st = sp->st_string;
+ for( nl=strchr(st,'\n'); nl != NIL( char); nl=strchr(st,'\n') ) {
+ *nl = '\0';
+ printf( "%s\\\n", st );
+ *nl = '\n';
+ st = nl+1;
+ }
+ printf( "%s\n", st );
+}
+
+
+static char *_attrs[] = { ".PRECIOUS", ".SILENT", ".LIBRARY",
+ ".EPILOG", ".PROLOG", ".IGNORE", ".SYMBOL", ".NOINFER",
+ ".UPDATEALL", ".SEQUENTIAL", ".SETDIR=", ".USESHELL", ".SWAP", ".MKSARGS",
+ ".PHONY", ".NOSTATE", ".IGNOREGROUP", ".EXECUTE", ".ERRREMOVE" };
+
+static void
+dump_normal_target( cp, namecp, flag )/*
+========================================
+ Dump in makefile like format the dag information */
+CELLPTR cp;
+CELLPTR namecp;
+int flag;
+{
+ register STRINGPTR sp;
+ t_attr attr;
+ unsigned int k;
+
+ DB_ENTER( "dump_normal_target" );
+
+ if(!(cp->ce_flag & F_TARGET) && !cp->ce_attr && !cp->ce_prq) {
+ DB_VOID_RETURN;
+ }
+
+ if(cp->ce_set && cp->ce_set != cp) {
+ DB_VOID_RETURN;
+ }
+
+ if( cp->ce_flag & F_MULTI ) {
+ int tflag = cp->ce_prq->cl_prq->ce_flag;
+ if( !(cp->ce_flag & F_PERCENT) ) tflag |= F_MULTI;
+ dump_conditionals(cp, cp->ce_cond, TRUE, TRUE);
+ putchar('\n');
+ dump_prerequisites(cp->ce_prq,(cp->ce_flag&F_PERCENT)?NIL(CELL):cp,
+ FALSE, TRUE, tflag);
+ }
+ else {
+ dump_name(namecp?namecp:cp, FALSE, TRUE );
+
+ for( k=0, attr=1; attr <= MAX_ATTR; attr <<= 1, k++ )
+ if( cp->ce_attr & attr ) {
+ printf( "%s%s ", _attrs[k],
+ (attr != A_SETDIR) ? "" : (cp->ce_dir?cp->ce_dir:"") );
+ }
+
+ putchar( ':' );
+
+ if( flag & F_MULTI ) putchar( ':' );
+ if( flag & F_SINGLE ) putchar( '!' );
+ putchar( ' ' );
+
+ dump_prerequisites( cp->ce_prq, NIL(CELL), FALSE, FALSE, F_DEFAULT);
+ dump_prerequisites( cp->ce_indprq, NIL(CELL),TRUE, FALSE, F_DEFAULT);
+
+ putchar( '\n' );
+ if( cp->ce_flag & F_GROUP ) puts( "[" );
+ for( sp = cp->ce_recipe; sp != NIL(STRING); sp = sp->st_next )
+ Dump_recipe( sp );
+ if( cp->ce_flag & F_GROUP ) {
+ puts( "]" );
+ putchar( '\n' );
+ }
+ dump_conditionals(cp, cp->ce_cond, flag&F_MULTI, FALSE);
+ putchar('\n');
+ }
+
+ DB_VOID_RETURN;
+}
+
+
+static void
+dump_conditionals( cp, sp, multi, global )
+CELLPTR cp;
+STRINGPTR sp;
+int multi;
+int global;
+{
+ if (sp) {
+ dump_name(cp, FALSE, TRUE);
+ printf(".%sCONDITIONALS %s\n", global?"GLOBAL":"",multi?"::":":");
+
+ while(sp) {
+ printf("\t%s\n",sp->st_string);
+ sp=sp->st_next;
+ }
+ }
+}
+
+
+static void
+dump_macro(hp, flag)
+HASHPTR hp;
+int flag;
+{
+ printf( "%s ", hp->ht_name );
+ if(flag & M_EXPANDED)
+ putchar( ':' );
+
+ printf( "= " );
+ if(hp->ht_value != NIL(char))
+ printf( "%s",hp->ht_value );
+
+ if(flag & M_PRECIOUS)
+ printf( "\t # PRECIOUS " );
+
+ putchar( '\n' );
+}
+
+
+static void
+dump_prerequisites( lp, namecp, quote, recurse, flag )
+LINKPTR lp;
+CELLPTR namecp;
+int quote;
+int recurse;
+int flag;
+{
+ for( ; lp; lp=lp->cl_next )
+ if( recurse )
+ dump_normal_target(lp->cl_prq, namecp, flag);
+ else if( lp->cl_prq )
+ dump_name(lp->cl_prq, quote, FALSE);
+}
+
+
+static void
+dump_name( cp, quote, all )/*
+=============================
+ print out a name */
+CELLPTR cp;
+int quote;
+int all;
+{
+ LINKPTR lp;
+ char qc = '\'';
+
+ for(lp=CeMeToo(cp);lp;lp=lp->cl_next) {
+ if( !quote && strchr(lp->cl_prq->CE_NAME,' ') != NIL(char)) {
+ quote = TRUE;
+ qc = '"';
+ }
+
+ if (quote) putchar(qc);
+ printf( "%s", lp->cl_prq->CE_NAME );
+ if (quote) putchar(qc);
+ putchar(' ');
+ if (!all) break;
+ }
+}
diff --git a/dmake/dmstring.c b/dmake/dmstring.c
new file mode 100644
index 000000000000..b4ff6177c368
--- /dev/null
+++ b/dmake/dmstring.c
@@ -0,0 +1,287 @@
+/* RCS $Id: dmstring.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- String handling code
+--
+-- DESCRIPTION
+-- Routines to handle string manipulation. This code is not specific
+-- to dmake and has/and will be used in other programs. The string
+-- "" is considered the NULL string, if NIL(char) is received instead
+-- undefined results may occurr. (In reality NIL(char) is checked for
+-- but in general it is not safe to assume NIL(char) == NULL)
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+PUBLIC char *
+DmStrJoin( src, data, n, fr )/*
+===============================
+ Join data to src according to value of n.
+
+ n = -1 - return strcat( src, data )
+ n >= 0 - return strncat( src, data, n )
+
+ FREE original src if fr == TRUE, else leave it alone */
+
+char *src;
+char *data;
+int n;
+int fr;
+{
+ char *t;
+ int l;
+ int flag = FALSE;
+
+ DB_ENTER( "DmStrJoin" );
+
+ if( src == NIL(char) ) { src = ""; flag = TRUE; }
+ if( data == NIL(char) ) data = "";
+ DB_PRINT( "str", ("Joining [%s] [%s] %d", src, data, n) );
+
+ if( n == -1 ) n = strlen( data );
+
+ l = strlen( src ) + n + 1;
+ if( (t = MALLOC( l, char )) == NIL(char) ) No_ram();
+
+ strcpy( t, src );
+ if (n) strncat( t, data, n );
+ t[ l-1 ] = '\0';
+
+ if( !flag && fr ) FREE( src );
+
+ DB_PRINT( "str", ("Result [%s]", t) );
+ DB_RETURN( t );
+}
+
+
+
+
+PUBLIC char *
+DmStrAdd( src, data, fr )/*
+===========================
+ append data to src with space in between if src is not NIL(char) or ""
+ and free both src and data if fr == TRUE, otherwise leave them be */
+
+char *src;
+char *data;
+int fr;
+{
+ char *t;
+ int l;
+ int sflag;
+ int dflag;
+
+ DB_ENTER( "DmStrAdd" );
+
+ sflag = dflag = fr;
+
+ if( src == NIL(char) ) { src = ""; sflag = FALSE; }
+ if( data == NIL(char) ) { data = ""; dflag = FALSE; }
+ DB_PRINT( "str", ("Adding [%s] [%s] %d", src, data, fr) );
+
+ l = strlen(src) + strlen(data) + 1;
+ if( *src ) l++;
+
+ if( (t = MALLOC( l, char )) == NIL(char) ) No_ram();
+
+ strcpy( t, src );
+
+ if( *data )
+ {
+ if( *src ) strcat( t, " " );
+ strcat( t, data );
+ }
+
+ if( sflag ) FREE( src );
+ if( dflag ) FREE( data );
+
+ DB_PRINT( "str", ("Result [%s]", t) );
+ DB_RETURN( t );
+}
+
+
+
+PUBLIC char *
+DmStrApp( src1, src2 )/*
+========================
+ Append two strings together, and return the result with a space between
+ the two strings. FREE the first string if it is not NIL and always
+ leave the second string be. */
+char *src1;
+char *src2;
+{
+ src2 = DmStrAdd( src1, src2, FALSE );
+ if( src1 != NIL(char) ) FREE( src1 );
+ return( src2 );
+}
+
+
+PUBLIC char *
+DmStrDup( str )/*
+================= Duplicate the contents of a string, by using malloc */
+char *str;
+{
+ char *t;
+
+ if( str == NIL(char) ) return( NIL(char) );
+
+ if( (t = MALLOC( strlen( str )+1, char )) == NIL(char) ) No_ram();
+ strcpy( t, str );
+
+ return( t );
+}
+
+
+
+PUBLIC char *
+DmStrDup2( str )/*
+==================
+ This function is used solely to properly quote command line arguments when
+ they are reinserted int MAKEMACROS so that they can be used further in
+ a processing line. */
+char *str;
+{
+ char *t;
+ size_t size;
+ size_t alloced;
+ char *tmp;
+ char *dest;
+ int seen_equal = 0;
+
+ if(str == NIL(char)) return(NIL(char));
+ size = strlen(str) + 1;
+ alloced = size + 2; /* for two quotes */
+
+ for(tmp = str; *tmp; tmp++)
+ if(*tmp == '"')
+ alloced++;
+
+ if((t = MALLOC(alloced, char)) == NIL(char)) No_ram();
+
+ for(tmp = str, dest = t; *tmp; tmp++, dest++) {
+ if(*tmp == '=' && !seen_equal) {
+ seen_equal = 1;
+ *dest++ = *tmp;
+ *dest = '"';
+ continue;
+ }
+ if(*tmp == '"')
+ *dest++ = '\\';
+ *dest = *tmp;
+ }
+
+ if(!seen_equal)
+ Fatal("DmStrDup2 invoked without argument of form x=y\n");
+
+ *dest++ = '"';
+ *dest = 0;
+
+ return t;
+}
+
+
+
+PUBLIC char *
+DmStrPbrk( s1, s2 )/*
+====================
+ find first occurence of char in s2 in string s1.
+ Returns a pointer to the first occurrence. NOTE '\0' is considered part
+ of s2 and a pointer to it is returned if no other chars match. */
+
+char *s1;
+char *s2;
+{
+ register char *t;
+
+ if( s1 == NIL(char) || s2 == NIL(char) ) return( "" );
+
+ for( t=s1; *t && (strchr( s2, *t ) == NIL(char)); t++ );
+ return( t );
+}
+
+
+
+
+PUBLIC char *
+DmStrSpn( s1, s2 )/*
+====================
+ return pointer to first char in s1 that does not belong to s2.
+ Returns the pointer if match found, else returns pointer to null char
+ in s1. (ie. "" ) */
+
+char *s1;
+char *s2;
+{
+ register char *t;
+
+ if( s1 == NIL(char) || s2 == NIL(char) ) return( "" );
+
+ for( t=s1; *t && (strchr( s2, *t ) != NIL(char)); t++ );
+ return( t );
+}
+
+
+
+
+PUBLIC char *
+DmStrStr( s1, s2 )/*
+==================== find first occurrence in s1 of s2 */
+char *s1;
+char *s2;
+{
+ register char *s;
+ register char *p;
+ register char *r;
+
+ if( s1 != NIL(char) && s2 != NIL(char) )
+ for( s=s1; *s; s++ )
+ if( *s == *s2 )
+ {
+ for( r=s+1, p = s2+1; *p && (*r == *p); r++, p++ );
+ if( !*p ) return( s );
+ }
+
+ return( NIL(char) );
+}
+
+
+
+PUBLIC char *
+DmSubStr( s, e )/*
+==================
+ Return the string between the two pointers s and e, not including the
+ char that e points to. NOTE: This routine assumes that s and e point
+ into the same string. */
+
+char *s;
+char *e;
+{
+ char save;
+ int len = e-s;
+
+ if( len < 0 || len > strlen(s) )
+ Fatal( "Internal Error: SubStr fails consistency test" );
+
+ save = *e;
+ *e = '\0';
+ s = DmStrDup( s );
+ *e = save;
+
+ return( s );
+}
diff --git a/dmake/dstdarg.h b/dmake/dstdarg.h
new file mode 100644
index 000000000000..f0dc760b5db4
--- /dev/null
+++ b/dmake/dstdarg.h
@@ -0,0 +1,43 @@
+/* RCS $Id: dstdarg.h,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+--
+-- DESCRIPTION
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+#include <stdarg.h>
+
+#define ARG(a,b) a
+
+#if __STDC__ || defined(__TURBOC__) || defined(__IBMC__)
+# define va_alist_type ...
+# ifdef va_alist
+# undef va_alist
+# endif
+# define va_alist
+# define DARG(a,b)
+#else
+# ifdef va_alist
+# define va_alist_type int
+# define DARG(a,b) a b;
+# else
+# define va_alist_type ...
+# define va_alist
+# define DARG(a,b)
+# endif
+#endif
diff --git a/dmake/expand.c b/dmake/expand.c
new file mode 100644
index 000000000000..664aa03ddc09
--- /dev/null
+++ b/dmake/expand.c
@@ -0,0 +1,1066 @@
+/* RCS $Id: expand.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Macro expansion code.
+--
+-- DESCRIPTION
+--
+-- This routine handles all the necessary junk that deals with macro
+-- expansion. It understands the following syntax. If a macro is
+-- not defined it expands to NULL, and {} are synonyms for ().
+--
+-- $$ - expands to $
+-- {{ - expands to {
+-- }} - expands to }
+-- $A - expands to whatever the macro A is defined as
+-- $(AA) - expands to whatever the macro AA is defined as
+-- $($(A)) - represents macro indirection
+-- <+...+> - get mapped to $(mktmp ...)
+--
+-- following macro is recognized
+--
+-- string1{ token_list }string2
+--
+-- and expands to string1 prepended to each element of token_list and
+-- string2 appended to each of the resulting tokens from the first
+-- operation. If string2 is of the form above then the result is
+-- the cross product of the specified (possibly modified) token_lists.
+--
+-- The folowing macro modifiers are defined and expanded:
+--
+-- $(macro:modifier_list:modifier_list:...)
+--
+-- where modifier_list a combination of:
+--
+-- D or d - Directory portion of token including separator
+-- F or f - File portion of token including suffix
+-- B or b - basename portion of token not including suffix
+-- T or t - for tokenization
+-- E or e - Suffix portion of name
+-- L or l - translate to lower case
+-- U or u - translate to upper case
+-- I or i - return inferred names
+--
+-- or a single
+-- S or s - pattern substitution (simple)
+--
+-- NOTE: Modifiers are applied once the macro value has been found.
+-- Thus the construct $($(test):s/joe/mary/) is defined and
+-- modifies the value of $($(test))
+--
+-- Also the construct $(m:d:f) is not the same as $(m:df)
+-- the first applies d to the value of $(m) and then
+-- applies f to the value of that whereas the second form
+-- applies df to the value of $(m).
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+/* Microsoft BRAINDAMAGE ALERT!!!!
+ * This #ifdef is here only to satisfy stupid bugs in MSC5.0 and MSC5.1
+ * it isn't needed for anything else. It turns loop optimization off. */
+#if defined(_MSC_VER)
+#include "optoff.h"
+#endif
+
+static char* _scan_macro ANSI((char*, char**, int));
+static char* _scan_brace ANSI((char*, char**, int*));
+static char* _cross_prod ANSI((char*, char*));
+
+#if !defined(__GNUC__) && !defined(__IBMC__)
+static char* _scan_ballanced_parens ANSI((char*, char));
+#else
+static char* _scan_ballanced_parens ANSI((char*, int));
+#endif
+
+
+PUBLIC char *
+Expand( src )/*
+===============
+ This is the driver routine for the expansion, it identifies non-white
+ space tokens and gets the ScanToken routine to figure out if they should
+ be treated in a special way. */
+
+char *src; /* pointer to source string */
+{
+ char *tmp; /* pointer to temporary str */
+ char *res; /* pointer to result string */
+ char *start; /* pointer to start of token */
+
+ DB_ENTER( "Expand" );
+ DB_PRINT( "exp", ("Expanding [%s]", src) );
+
+ res = DmStrDup( "" );
+ if( src == NIL(char) ) DB_RETURN( res );
+
+ while( *src ) {
+ char *ks, *ke;
+
+ /* Here we find the next non white space token in the string
+ * and find it's end, with respect to non-significant white space. */
+
+#ifndef _MPW
+ start = DmStrSpn( src, " \t\n" );
+#else
+ start = DmStrSpn( src, " \t\r\n" );
+#endif
+
+ res = DmStrJoin( res, src, start-src, TRUE );
+ if( !(*start) ) break;
+
+ /* START <+...+> KLUDGE */
+ if( (ks=DmStrStr(start,"<+")) != NIL(char)
+ && (ke=DmStrStr(ks,"+>")) != NIL(char) ){
+ char *t1, *t2;
+
+ res = DmStrJoin( res, t2=Expand(t1=DmSubStr(start,ks)), -1, TRUE);
+ FREE(t1); FREE(t2);
+
+ t1 = DmSubStr(ks+2, ke+1); t1[ke-ks-2] = ')';
+ t2 = DmStrJoin( "$(mktmp ", t1, -1,FALSE);
+ FREE(t1);
+ res = DmStrJoin( res, t2=Expand(t2), -1, TRUE);
+ FREE(t2);
+ src = ke+2;
+ }
+ /* END <+...+> KLUDGE */
+ else {
+ res = DmStrJoin( res, tmp = ScanToken(start,&src,TRUE), -1, TRUE );
+ FREE( tmp );
+ }
+ }
+
+ DB_PRINT( "exp", ("Returning [%s]", res) );
+ DB_RETURN( res );
+}
+
+
+PUBLIC char *
+Apply_edit( src, pat, subst, fr, anchor )/*
+===========================================
+ Take the src string and apply the pattern substitution. ie. look for
+ occurrences of pat in src and replace each occurrence with subst. This is
+ NOT a regular expressions pattern substitution, it's just not worth it.
+
+ if anchor == TRUE then the src pattern match must be at the end of a token.
+ ie. this is for SYSV compatibility and is only used for substitutions of
+ the caused by $(macro:pat=sub). So if src = "fre.o.k june.o" then
+ $(src:.o=.a) results in "fre.o.k june.a", and $(src:s/.o/.a) results in
+ "fre.a.k june.a" */
+
+char *src; /* the source string */
+char *pat; /* pattern to find */
+char *subst; /* substitute string */
+int fr; /* if TRUE free src */
+int anchor; /* if TRUE anchor */
+{
+ char *res;
+ char *p;
+ char *s;
+ int l;
+
+ DB_ENTER( "Apply_edit" );
+
+ if( !*pat ) DB_RETURN( src ); /* do nothing if pat is NULL */
+
+ DB_PRINT( "mod", ("Source str: [%s]", src) );
+ DB_PRINT( "mod", ("Replacing [%s], with [%s]", pat, subst) );
+
+ s = src;
+ l = strlen( pat );
+ if( (p = DmStrStr( s, pat )) != NIL(char) ) {
+ res = DmStrDup( "" );
+ do {
+ if( anchor )
+ if( !*(p+l) || (strchr(" \t", *(p+l)) != NIL(char)) )
+ res = DmStrJoin( DmStrJoin(res,s,p-s,TRUE), subst, -1, TRUE );
+ else
+ res = DmStrJoin( res, s, p+l-s, TRUE );
+ else
+ res = DmStrJoin( DmStrJoin(res,s,p-s,TRUE), subst, -1, TRUE );
+
+ s = p + l;
+ }
+ while( (p = DmStrStr( s, pat )) != NIL(char) );
+
+ res = DmStrJoin( res, s, -1, TRUE );
+ if( fr ) FREE( src );
+ }
+ else
+ res = src;
+
+
+ DB_PRINT( "mod", ("Result [%s]", res) );
+ DB_RETURN( res );
+}
+
+
+PUBLIC void
+Map_esc( tok )/*
+================
+ Map an escape sequence and replace it by it's corresponding character
+ value. It is assumed that tok points at the initial \, the esc
+ sequence in the original string is replaced and the value of tok
+ is not modified. */
+char *tok;
+{
+ if( strchr( "\"\\vantbrf01234567", tok[1] ) ) {
+ switch( tok[1] ) {
+ case 'a' : *tok = 0x07; break;
+ case 'b' : *tok = '\b'; break;
+ case 'f' : *tok = '\f'; break;
+ case 'n' : *tok = '\n'; break;
+ case 'r' : *tok = '\r'; break;
+ case 't' : *tok = '\t'; break;
+ case 'v' : *tok = 0x0b; break;
+ case '\\': *tok = '\\'; break;
+ case '\"': *tok = '\"'; break;
+
+ default: {
+ register int i = 0;
+ register int j = 0;
+ for( ; i<2 && isdigit(tok[2]); i++ ) {
+ j = (j << 3) + (tok[1] - '0');
+ strcpy( tok+1, tok+2 );
+ }
+ j = (j << 3) + (tok[1] - '0');
+ *tok = j;
+ }
+ }
+ strcpy( tok+1, tok+2 );
+ }
+}
+
+
+PUBLIC char*
+Apply_modifiers( mod, src )/*
+=============================
+ This routine applies the appropriate modifiers to the string src
+ and returns the proper result string */
+
+int mod;
+char *src;
+{
+ char *s;
+ char *e;
+ TKSTR str;
+
+ DB_ENTER( "Apply_modifiers" );
+
+ if ( mod & INFNAME_FLAG ) {
+ SET_TOKEN( &str, src );
+ e = NIL(char);
+
+ while( *(s = Get_token( &str, "", FALSE )) != '\0' ) {
+ HASHPTR hp;
+
+ if ( (hp = Get_name(s, Defs, FALSE)) != NIL(HASH)
+ && hp->CP_OWNR
+ && hp->CP_OWNR->ce_fname
+ ) {
+ e = DmStrApp(e,hp->CP_OWNR->ce_fname);
+ }
+ else
+ e = DmStrApp(e,s);
+ }
+
+ FREE(src);
+ src = e;
+ mod &= ~INFNAME_FLAG;
+ }
+
+ if(mod & (TOLOWER_FLAG|TOUPPER_FLAG) ) {
+ int lower;
+ lower = mod & TOLOWER_FLAG;
+
+ for (s=src; *s; s++)
+ if ( isalpha(*s) )
+ *s = ((lower) ? tolower(*s) : toupper(*s));
+
+ mod &= ~(TOLOWER_FLAG|TOUPPER_FLAG);
+ }
+
+ if (mod & JUST_FIRST_FLAG) {
+ SET_TOKEN(&str, src);
+ if ((s = Get_token(&str,"",FALSE)) != '\0') {
+ e = DmStrDup(s);
+ CLEAR_TOKEN(&str);
+ FREE(src);
+ src = e;
+ }
+ else {
+ CLEAR_TOKEN(&str);
+ }
+ mod &= ~JUST_FIRST_FLAG;
+ }
+
+ if( !mod || mod == (SUFFIX_FLAG | DIRECTORY_FLAG | FILE_FLAG) )
+ DB_RETURN( src );
+
+ SET_TOKEN( &str, src );
+ DB_PRINT( "mod", ("Source string [%s]", src) );
+
+ while( *(s = Get_token( &str, "", FALSE )) != '\0' ) {
+ /* search for the directory portion of the filename. If the
+ * DIRECTORY_FLAG is set, then we want to keep the directory portion
+ * othewise throw it away and blank out to the end of the token */
+
+ if( (e = Basename(s)) != s)
+ if( !(mod & DIRECTORY_FLAG) ) {
+ strcpy(s, e);
+ e = s+(str.tk_str-e);
+ for(; e != str.tk_str; e++)
+ *e = ' ';
+ }
+ else
+ s = e;
+
+ /* search for the suffix, if there is none, treat it as a NULL suffix.
+ * if no file name treat it as a NULL file name. same copy op as
+ * for directory case above */
+
+ e = strrchr( s, '.' ); /* NULL suffix if e=0 */
+ if( e == NIL(char) ) e = s+strlen(s);
+
+ if( !(mod & FILE_FLAG) ) {
+ strcpy( s, e );
+ e = s+(str.tk_str-e);
+ for( ; e != str.tk_str; e++ ) *e = ' ';
+ }
+ else
+ s = e;
+
+ /* The last and final part. This is the suffix case, if we don't want
+ * it then just erase to the end of the token. */
+
+ if( s != NIL(char) )
+ if( !(mod & SUFFIX_FLAG) )
+ for( ; s != str.tk_str; s++ ) *s = ' ';
+ }
+
+ /* delete the extra white space, it looks ugly */
+ for( s = src, e = NIL(char); *s; s++ )
+ if( *s == ' ' || *s == '\t' || *s == '\n' ) {
+ if( e == NIL(char) )
+ e = s;
+ }
+ else {
+ if( e != NIL(char) ) {
+ if( e+1 < s ) {
+ strcpy( e+1, s );
+ s = e+1;
+ *e = ' ';
+ }
+ e = NIL(char);
+ }
+ }
+
+ if( e != NIL(char) )
+ if( e < s )
+ strcpy( e, s );
+
+ DB_PRINT( "mod", ("Result string [%s]", src) );
+ DB_RETURN( src );
+}
+
+
+PUBLIC char*
+Tokenize( src, separator, op, mapesc )/*
+========================================
+ Tokenize the input of src and join each token found together with
+ the next token separated by the separator string.
+
+ When doing the tokenization, <sp>, <tab>, <nl>, and \<nl> all
+ constitute white space. */
+
+char *src;
+char *separator;
+char op;
+int mapesc;
+{
+ TKSTR tokens;
+ char *tok;
+ char *res;
+ int first = (op == 't' || op == 'T');
+
+ DB_ENTER( "Tokenize" );
+
+ /* map the escape codes in the separator string first */
+ if ( mapesc )
+ for(tok=separator; (tok = strchr(tok,ESCAPE_CHAR)) != NIL(char); tok++)
+ Map_esc( tok );
+
+ DB_PRINT( "exp", ("Separator [%s]", separator) );
+
+ /* By default we return an empty string */
+ res = DmStrDup( "" );
+
+ /* Build the token list */
+ SET_TOKEN( &tokens, src );
+ while( *(tok = Get_token( &tokens, "", FALSE )) != '\0' ) {
+ char *x;
+
+ if( first ) {
+ FREE( res );
+ res = DmStrDup( tok );
+ first = FALSE;
+ }
+ else if (op == '^') {
+ res = DmStrAdd(res, DmStrJoin(separator, tok, -1, FALSE), TRUE);
+ }
+ else if (op == '+') {
+ res = DmStrAdd(res, DmStrJoin(tok, separator, -1, FALSE), TRUE);
+ }
+ else {
+ res = DmStrJoin(res, x =DmStrJoin(separator, tok, -1, FALSE),
+ -1, TRUE);
+ FREE( x );
+ }
+
+ DB_PRINT( "exp", ("Tokenizing [%s] --> [%s]", tok, res) );
+ }
+
+ FREE( src );
+ DB_RETURN( res );
+}
+
+
+static char*
+_scan_ballanced_parens(p, delim)
+char *p;
+char delim;
+{
+ int pcount = 0;
+ int bcount = 0;
+
+ if ( p ) {
+ do {
+ if (delim)
+ if( !(bcount || pcount) && *p == delim) {
+ return(p);
+ }
+
+ if ( *p == '(' ) pcount++;
+ else if ( *p == '{' ) bcount++;
+ else if ( *p == ')' && pcount ) pcount--;
+ else if ( *p == '}' && bcount ) bcount--;
+
+ p++;
+ }
+ while (*p && (pcount || bcount || delim));
+ }
+
+ return(p);
+}
+
+
+PUBLIC char*
+ScanToken( s, ps, doexpand )/*
+==============================
+ This routine scans the token characters one at a time and identifies
+ macros starting with $( and ${ and calls _scan_macro to expand their
+ value. the string1{ token_list }string2 expansion is also handled.
+ In this case a temporary result is maintained so that we can take it's
+ cross product with any other token_lists that may possibly appear. */
+
+char *s; /* pointer to start of src string */
+char **ps; /* pointer to start pointer */
+int doexpand;
+{
+ char *res; /* pointer to result */
+ char *start; /* pointer to start of prefix */
+ int crossproduct = 0; /* if 1 then computing X-prod */
+
+ start = s;
+ res = DmStrDup( "" );
+ while( 1 ) {
+ switch( *s ) {
+ /* Termination, We halt at seeing a space or a tab or end of string.
+ * We return the value of the result with any new macro's we scanned
+ * or if we were computing cross_products then we return the new
+ * cross_product.
+ * NOTE: Once we start computing cross products it is impossible to
+ * stop. ie. the semantics are such that once a {} pair is
+ * seen we compute cross products until termination. */
+
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\0':
+ {
+ char *tmp;
+
+ *ps = s;
+ if( !crossproduct )
+ tmp = DmStrJoin( res, start, (s-start), TRUE );
+ else
+ {
+ tmp = DmSubStr( start, s );
+ tmp = _cross_prod( res, tmp );
+ }
+ return( tmp );
+ }
+
+ case '$':
+ case '{':
+ {
+ /* Handle if it's a macro or if it's a {} construct.
+ * The results of a macro expansion are handled differently based
+ * on whether we have seen a {} beforehand. */
+
+ char *tmp;
+ tmp = DmSubStr( start, s ); /* save the prefix */
+
+ if( *s == '$' ) {
+ start = _scan_macro( s+1, &s, doexpand );
+
+ if( crossproduct ) {
+ res = _cross_prod( res, DmStrJoin( tmp, start, -1, TRUE ) );
+ }
+ else {
+ res = DmStrJoin(res,tmp=DmStrJoin(tmp,start,-1,TRUE),-1,TRUE);
+ FREE( tmp );
+ }
+ FREE( start );
+ }
+ else if( strchr("{ \t",s[1]) == NIL(char) ){
+ int ok;
+ start = _scan_brace( s+1, &s, &ok );
+
+ if( ok ) {
+ if ( crossproduct ) {
+ res = _cross_prod(res,_cross_prod(tmp,start));
+ }
+ else {
+ char *freeres;
+ res = Tokenize(start,
+ freeres=DmStrJoin(res,tmp,-1,TRUE),
+ '^', FALSE);
+ FREE(freeres);
+ FREE(tmp);
+ }
+ crossproduct = TRUE;
+ }
+ else {
+ res =DmStrJoin(res,tmp=DmStrJoin(tmp,start,-1,TRUE),-1,TRUE);
+ FREE( start );
+ FREE( tmp );
+ }
+ }
+ else { /* handle the {{ case */
+ res = DmStrJoin( res, start, (s-start+1), TRUE );
+ s += (s[1]=='{')?2:1;
+ FREE( tmp );
+ }
+
+ start = s;
+ }
+ break;
+
+ case '}':
+ if( s[1] != '}' ) {
+ /* error malformed macro expansion */
+ s++;
+ }
+ else { /* handle the }} case */
+ res = DmStrJoin( res, start, (s-start+1), TRUE );
+ s += 2;
+ start = s;
+ }
+ break;
+
+ default: s++;
+ }
+ }
+}
+
+
+static char*
+_scan_macro( s, ps, doexpand )/*
+================================
+ This routine scans a macro use and expands it to the value. It
+ returns the macro's expanded value and modifies the pointer into the
+ src string to point at the first character after the macro use.
+ The types of uses recognized are:
+
+ $$ and $<sp> - expands to $
+ $(name) - expands to value of name
+ ${name} - same as above
+ $($(name)) - recurses on macro names (any level)
+ and
+ $(func[,args ...] [data])
+ and
+ $(name:modifier_list:modifier_list:...)
+
+ see comment for Expand for description of valid modifiers.
+
+ NOTE that once a macro name bounded by ( or { is found only
+ the appropriate terminator (ie. ( or } is searched for. */
+
+char *s; /* pointer to start of src string */
+char **ps; /* pointer to start pointer */
+int doexpand; /* If TRUE enables macro expansion */
+{
+ char sdelim; /* start of macro delimiter */
+ char edelim; /* corresponding end macro delim */
+ char *start; /* start of prefix */
+ char *macro_name; /* temporary macro name */
+ char *recurse_name; /* recursive macro name */
+ char *result; /* result for macro expansion */
+ int bflag = 0; /* brace flag, ==0 => $A type macro */
+ int done = 0; /* != 0 => done macro search */
+ int lev = 0; /* brace level */
+ int mflag = 0; /* != 0 => modifiers present in mac */
+ int fflag = 0; /* != 0 => GNU style function */
+ HASHPTR hp; /* hash table pointer for macros */
+
+ DB_ENTER( "_scan_macro" );
+
+ /* Check for $ at end of line, or $ followed by white space */
+ if( !*s || strchr(" \t", *s) != NIL(char)) {
+ *ps = s;
+ DB_RETURN( DmStrDup("") );
+ }
+
+ if( *s == '$' ) { /* Take care of the simple $$ case. */
+ *ps = s+1;
+ DB_RETURN( DmStrDup("$") );
+ }
+
+ sdelim = *s; /* set and remember start/end delim */
+ if( sdelim == '(' )
+ edelim = ')';
+ else
+ edelim = '}';
+
+ start = s; /* build up macro name, find its end*/
+ while( !done ) {
+ switch( *s ) {
+ case '(': /* open macro brace */
+ case '{':
+ if( *s == sdelim ) {
+ lev++;
+ bflag++;
+ }
+ break;
+
+ case ':': /* halt at modifier */
+ if( lev == 1 && !fflag && doexpand ) {
+ done = TRUE;
+ mflag = 1;
+ }
+ break;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ if ( lev == 1 ) fflag = 1;
+ break;
+
+ case '\0': /* check for null */
+ *ps = s;
+ done = TRUE;
+ if( lev ) {
+ bflag = 0;
+ s = start;
+ }
+ break;
+
+ case ')': /* close macro brace */
+ case '}':
+ if( *s == edelim && lev ) --lev;
+ /*FALLTHRU*/
+
+ default:
+ done = !lev;
+ }
+ s++;
+ }
+
+ /* Check if this is a $A type macro. If so then we have to
+ * handle it a little differently. */
+ if( bflag )
+ macro_name = DmSubStr( start+1, s-1 );
+ else
+ macro_name = DmSubStr( start, s );
+
+ if (!doexpand) {
+ *ps = s;
+ DB_RETURN(macro_name);
+ }
+
+ /* Check to see if the macro name contains spaces, if so then treat it
+ * as a GNU style function invocation and call the function mapper to
+ * deal with it. We do not call the function expander if the function
+ * invocation begins with a '$' */
+ if( fflag && *macro_name != '$' ) {
+ result = Exec_function(macro_name);
+ }
+ else {
+ /* Check if the macro is a recursive macro name, if so then
+ * EXPAND the name before expanding the value */
+ if( strchr( macro_name, '$' ) != NIL(char) ) {
+ recurse_name = Expand( macro_name );
+ FREE( macro_name );
+ macro_name = recurse_name;
+ }
+
+ /* Code to do value expansion goes here, NOTE: macros whose assign bit
+ is one have been evaluated and assigned, they contain no further
+ expansions and thus do not need their values expanded again. */
+
+ if( (hp = GET_MACRO( macro_name )) != NIL(HASH) ) {
+ if( hp->ht_flag & M_MARK )
+ Fatal( "Detected circular macro [%s]", hp->ht_name );
+
+ if( !(hp->ht_flag & M_EXPANDED) ) {
+ hp->ht_flag |= M_MARK;
+ result = Expand( hp->ht_value );
+ hp->ht_flag ^= M_MARK;
+ }
+ else if( hp->ht_value != NIL(char) )
+ result = DmStrDup( hp->ht_value );
+ else
+ result = DmStrDup( "" );
+
+ /*
+ * Mark macros as used only if we are not expanding them for
+ * the purpose of a .IF test, so we can warn about redef after use*/
+
+ if( !If_expand ) hp->ht_flag |= M_USED;
+ }
+ else
+ result = DmStrDup( "" );
+ }
+
+ if( mflag ) {
+ char separator;
+ int modifier_list = 0;
+ int aug_mod = FALSE;
+ char *pat1;
+ char *pat2;
+ char *p;
+
+ /* Yet another brain damaged AUGMAKE kludge. We should accept the
+ * AUGMAKE bullshit of $(f:pat=sub) form of macro expansion. In
+ * order to do this we will forgo the normal processing if the
+ * AUGMAKE solution pans out, otherwise we will try to process the
+ * modifiers ala dmake.
+ *
+ * So we look for = in modifier string.
+ * If found we process it and not do the normal stuff */
+
+ for( p=s; *p && *p != '=' && *p != edelim; p++ );
+
+ if( *p == '=' ) {
+ char *tmp;
+
+ pat1 = Expand(tmp = DmSubStr(s,p)); FREE(tmp);
+ s = p+1;
+ p = _scan_ballanced_parens(s+1, edelim);
+
+ if ( !*p ) {
+ Warning( "Incomplete macro expression [%s]", s );
+ p = s+1;
+ }
+ pat2 = Expand(tmp = DmSubStr(s,p)); FREE(tmp);
+
+ result = Apply_edit( result, pat1, pat2, TRUE, TRUE );
+ FREE( pat1 );
+ FREE( pat2 );
+ s = p;
+ aug_mod = TRUE;
+ }
+
+ if( !aug_mod )
+ while( *s && *s != edelim ) { /* while not at end of macro */
+ char switch_char;
+
+ switch( switch_char = *s++ ) {
+ case '1': modifier_list |= JUST_FIRST_FLAG; break;
+
+ case 'b':
+ case 'B': modifier_list |= FILE_FLAG; break;
+
+ case 'd':
+ case 'D': modifier_list |= DIRECTORY_FLAG; break;
+
+ case 'f':
+ case 'F': modifier_list |= FILE_FLAG | SUFFIX_FLAG; break;
+
+ case 'e':
+ case 'E': modifier_list |= SUFFIX_FLAG; break;
+
+ case 'l':
+ case 'L': modifier_list |= TOLOWER_FLAG; break;
+
+ case 'i':
+ case 'I': modifier_list |= INFNAME_FLAG; break;
+
+ case 'u':
+ case 'U': modifier_list |= TOUPPER_FLAG; break;
+
+ case 'S':
+ case 's':
+ if( modifier_list ) {
+ Warning( "Edit modifier must appear alone, ignored");
+ modifier_list = 0;
+ }
+ else {
+ separator = *s++;
+ for( p=s; *p != separator && *p != edelim; p++ );
+
+ if( *p == edelim )
+ Warning("Syntax error in edit pattern, ignored");
+ else {
+ char *t1, *t2;
+ pat1 = DmSubStr( s, p );
+ for(s=p=p+1; (*p != separator) && (*p != edelim); p++ );
+ pat2 = DmSubStr( s, p );
+ t1 = Expand(pat1); FREE(pat1);
+ t2 = Expand(pat2); FREE(pat2);
+ result = Apply_edit( result, t1, t2, TRUE, FALSE );
+ FREE( t1 );
+ FREE( t2 );
+ }
+ s = p;
+ }
+ /* find the end of the macro spec, or the start of a new
+ * modifier list for further processing of the result */
+
+ for( ; (*s != edelim) && (*s != ':'); s++ );
+ if( *s == ':' ) s++;
+ break;
+
+ case 'T':
+ case 't':
+ case '^':
+ case '+':
+ if( modifier_list ) {
+ Warning( "Tokenize modifier must appear alone, ignored");
+ modifier_list = 0;
+ }
+ else {
+ separator = *s++;
+
+ if( separator == '$' ) {
+ p = _scan_ballanced_parens(s,'\0');
+
+ if ( *p ) {
+ char *tmp;
+ pat1 = Expand(tmp = DmSubStr(s-1,p));
+ FREE(tmp);
+ result = Tokenize(result, pat1, switch_char, TRUE);
+ FREE(pat1);
+ }
+ else {
+ Warning( "Incomplete macro expression [%s]", s );
+ }
+ s = p;
+ }
+ else if ( separator == '\"' ) {
+ /* we change the semantics to allow $(v:t")") */
+ for (p = s; *p && *p != separator; p++)
+ if (*p == '\\')
+ if (p[1] == '\\' || p[1] == '"')
+ p++;
+
+ if( *p == 0 )
+ Fatal( "Unterminated separator string" );
+ else {
+ pat1 = DmSubStr( s, p );
+ result = Tokenize( result, pat1, switch_char, TRUE);
+ FREE( pat1 );
+ }
+ s = p;
+ }
+ else {
+ Warning(
+ "Separator must be a quoted string or macro expression");
+ }
+
+ /* find the end of the macro spec, or the start of a new
+ * modifier list for further processing of the result */
+
+ for( ; (*s != edelim) && (*s != ':'); s++ );
+ if( *s == ':' ) s++;
+ }
+ break;
+
+ case ':':
+ if( modifier_list ) {
+ result = Apply_modifiers( modifier_list, result );
+ modifier_list = 0;
+ }
+ break;
+
+ default:
+ Warning( "Illegal modifier in macro, ignored" );
+ break;
+ }
+ }
+
+ if( modifier_list ) /* apply modifier */
+ result = Apply_modifiers( modifier_list, result );
+
+ s++;
+ }
+
+ *ps = s;
+ FREE( macro_name );
+ DB_RETURN( result );
+}
+
+
+static char*
+_scan_brace( s, ps, flag )/*
+============================
+ This routine scans for { token_list } pairs. It expands the value of
+ token_list by calling Expand on it. Token_list may be anything at all.
+ Note that the routine count's ballanced parentheses. This means you
+ cannot have something like { fred { joe }, if that is what you really
+ need the write it as { fred {{ joe }, flag is set to 1 if all ok
+ and to 0 if the braces were unballanced. */
+
+char *s;
+char **ps;
+int *flag;
+{
+ char *t;
+ char *start;
+ char *res;
+ int lev = 1;
+ int done = 0;
+
+ DB_ENTER( "_scan_brace" );
+
+ start = s;
+ while( !done )
+ switch( *s++ ) {
+ case '{':
+ if( *s == '{' ) break; /* ignore {{ */
+ lev++;
+ break;
+
+ case '}':
+ if( *s == '}' ) break; /* ignore }} */
+ if( lev )
+ if( --lev == 0 ) done = TRUE;
+ break;
+
+ case '$':
+ if( *s == '{' || *s == '}' ) {
+ if( (t = strchr(s,'}')) != NIL(char) )
+ s = t;
+ s++;
+ }
+ break;
+
+ case '\0':
+ if( lev ) {
+ done = TRUE;
+ s--;
+ /* error malformed macro expansion */
+ }
+ break;
+ }
+
+ start = DmSubStr( start, (lev) ? s : s-1 );
+
+ if( lev ) {
+ /* Braces were not ballanced so just return the string.
+ * Do not expand it. */
+
+ res = DmStrJoin( "{", start, -1, FALSE );
+ *flag = 0;
+ }
+ else {
+ *flag = 1;
+ res = Expand( start );
+
+ if( (t = DmStrSpn( res, " \t" )) != res ) strcpy( res, t );
+ }
+
+ FREE( start ); /* this is ok! start is assigned a DmSubStr above */
+ *ps = s;
+
+ DB_RETURN( res );
+}
+
+
+static char*
+_cross_prod( x, y )/*
+=====================
+ Given two strings x and y compute the cross-product of the tokens found
+ in each string. ie. if x = "a b" and y = "c d" return "ac ad bc bd".
+
+ NOTE: buf will continue to grow until it is big enough to handle
+ all cross product requests. It is never freed! (maybe I
+ will fix this someday) */
+
+char *x;
+char *y;
+{
+ static char *buf = NULL;
+ static int buf_siz = 0;
+ char *brkx;
+ char *brky;
+ char *cy;
+ char *cx;
+ char *res;
+ int i;
+
+ if( *x && *y ) {
+ res = DmStrDup( "" ); cx = x;
+ while( *cx ) {
+ cy = y;
+ brkx = DmStrPbrk( cx, " \t\n" );
+ if( (brkx-cx == 2) && *cx == '\"' && *(cx+1) == '\"' ) cx = brkx;
+
+ while( *cy ) {
+ brky = DmStrPbrk( cy, " \t\n" );
+ if( (brky-cy == 2) && *cy == '\"' && *(cy+1) == '\"' ) cy = brky;
+ i = brkx-cx + brky-cy + 2;
+
+ if( i > buf_siz ) { /* grow buf to the correct size */
+ if( buf != NIL(char) ) FREE( buf );
+ if( (buf = MALLOC( i, char )) == NIL(char)) No_ram();
+ buf_siz = i;
+ }
+
+ strncpy( buf, cx, (i = brkx-cx) );
+ buf[i] = '\0';
+ if (brky-cy > 0) strncat( buf, cy, brky-cy );
+ buf[i+(brky-cy)] = '\0';
+ strcat( buf, " " );
+ res = DmStrJoin( res, buf, -1, TRUE );
+ cy = DmStrSpn( brky, " \t\n" );
+ }
+ cx = DmStrSpn( brkx, " \t\n" );
+ }
+
+ FREE( x );
+ res[ strlen(res)-1 ] = '\0';
+ }
+ else
+ res = DmStrJoin( x, y, -1, TRUE );
+
+ FREE( y );
+ return( res );
+}
diff --git a/dmake/extern.h b/dmake/extern.h
new file mode 100644
index 000000000000..563910a2c9de
--- /dev/null
+++ b/dmake/extern.h
@@ -0,0 +1,66 @@
+/* RCS $Id: extern.h,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- External declarations for dmake functions.
+--
+-- DESCRIPTION
+-- ANSI is a macro that allows the proper handling of ANSI style
+-- function declarations.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef EXTERN_h
+#define EXTERN_h
+
+/* Define this for the RS/6000 if it breaks something then we have to put a
+ * #ifdef around it. */
+#if defined(rs6000)
+#define _POSIX_SOURCE
+#endif
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#if defined (_MPW)
+# include <types.h>
+# include <time.h>
+#else
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif
+#include <signal.h>
+#include "itypes.h"
+#include "stdmacs.h"
+#include "alloc.h"
+#include "db.h"
+#include "dstdarg.h"
+#include "dmake.h"
+#include "struct.h"
+#include "vextern.h"
+#include "public.h"
+
+/* Include this last as it invalidates some functions that are defined
+ * externally above and turns them into no-ops. Have to do this after
+ * the extern declarations however. */
+#include "config.h"
+#include "posix.h"
+
+#endif
diff --git a/dmake/function.c b/dmake/function.c
new file mode 100644
index 000000000000..d3bcffbb25b9
--- /dev/null
+++ b/dmake/function.c
@@ -0,0 +1,625 @@
+/* RCS $Id: function.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- GNU style functions for dmake.
+--
+-- DESCRIPTION
+-- All GNU stule functions understood by dmake are implemented in this
+-- file. Currently the only such function is $(mktmp ...) which is
+-- not part of GNU-make is an extension provided by dmake.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+static char *_exec_mktmp ANSI((char *, char *, char *));
+static char *_exec_subst ANSI((char *, char *, char *));
+static char *_exec_iseq ANSI((char *, char *, char *, int));
+static char *_exec_sort ANSI((char *));
+static char *_exec_echo ANSI((char *));
+static char *_exec_uniq ANSI((char *));
+static char *_exec_shell ANSI((char *, char *));
+static char *_exec_call ANSI((char *, char *));
+static char *_exec_assign ANSI((char *));
+static char *_exec_foreach ANSI((char *, char *, char *));
+static char *_exec_andor ANSI((char *, int));
+static char *_exec_not ANSI((char *));
+static int _mystrcmp ANSI((CONST PVOID, CONST PVOID));
+
+
+PUBLIC char *
+Exec_function(buf)/*
+====================
+ Execute the function given by the value of args.
+
+ So far mktmp is the only valid function, anything else elicits and error
+ message. It is my hope to support the GNU style functions in this portion
+ of the code at some time in the future. */
+char *buf;
+{
+ char *fname;
+ char *args;
+ char *mod1;
+ char *mod2 = NIL(char);
+ char *res = NIL(char);
+
+ /* This must succeed since the presence of ' ', \t or \n is what
+ * determines if this function is called in the first place. */
+ FREE(ScanToken(buf, &args, FALSE));
+ fname = DmSubStr(buf, args);
+
+ if( (mod1 = strchr(fname,',')) != NIL(char) ){
+ *mod1 = '\0';
+ mod1++;
+
+ if( (mod2 = strchr(mod1,',')) != NIL(char) ){
+ *mod2 = '\0';
+ mod2++;
+ }
+ }
+
+ switch( *fname ) {
+ case 'a':
+ if(strncmp(fname,"assign",6) == 0)
+ res = _exec_assign(args);
+ else if(strncmp(fname,"and",3) == 0)
+ res = _exec_andor(args, TRUE);
+ else
+ res = _exec_call(fname,args);
+ break;
+
+ case 'e':
+ if(strncmp(fname,"eq",2) == 0)
+ res = _exec_iseq(mod1,mod2,args,TRUE);
+ else if (strncmp(fname,"echo",4) == 0)
+ res = _exec_echo(args);
+ else
+ res = _exec_call(fname,args);
+ break;
+
+ case 'f':
+ if(strncmp(fname,"foreach",7) == 0)
+ res = _exec_foreach(mod1,mod2,args);
+ else
+ res = _exec_call(fname,args);
+ break;
+
+ case 'm':
+ if(strncmp(fname,"mktmp",5) == 0)
+ res = _exec_mktmp(mod1,mod2,args);
+ else
+ res = _exec_call(fname,args);
+ break;
+
+ case 'n':
+ if( strncmp(fname,"null", 4) == 0 )
+ res = _exec_iseq(mod1,NIL(char),args,TRUE);
+ else if (strncmp(fname,"nil",3) == 0 )
+ res = DmStrDup("");
+ else if (strncmp(fname,"not",3) == 0 )
+ res = _exec_not(args);
+ else
+ res = _exec_call(fname,args);
+ break;
+
+ case '!':
+ if(strncmp(fname,"!null",5) == 0)
+ res = _exec_iseq(mod1,NIL(char),args,FALSE);
+ else if(strncmp(fname,"!eq",3) ==0)
+ res = _exec_iseq(mod1,mod2,args,FALSE);
+ else
+ res = _exec_call(fname,args);
+ break;
+
+ case 'o':
+ if(strncmp(fname,"or",2) == 0)
+ res = _exec_andor(args, FALSE);
+ else
+ res = _exec_call(fname,args);
+ break;
+
+ case 's':
+ if(strncmp(fname,"sort",4) == 0)
+ res = _exec_sort(args);
+ else if(strncmp(fname,"shell",5)==0)
+ res = _exec_shell(args,mod1);
+ else if(strncmp(fname,"strip",5)==0)
+ res = Tokenize(Expand(args)," ",'t',TRUE);
+ else if(strncmp(fname,"subst",5)==0)
+ res = _exec_subst(mod1,mod2,args);
+ else
+ res = _exec_call(fname,args);
+ break;
+
+ case 'u':
+ if(strncmp(fname,"uniq",4) == 0)
+ res = _exec_uniq(args);
+ else
+ res = _exec_call(fname,args);
+ break;
+
+ default:
+ res = _exec_call(fname,args);
+ }
+
+ if( res == NIL(char) ) res = DmStrDup("");
+
+ FREE(fname);
+ return(res);
+}
+
+
+static char *
+_exec_assign( macrostring )
+char *macrostring;
+{
+ if ( !Parse_macro(macrostring, M_MULTI|M_FORCE) ) {
+ Error( "Dynamic macro assignment failed, while making [%s]\n",
+ Current_target ? Current_target->CE_NAME : "NIL");
+ return(DmStrDup(""));
+ }
+
+ return(DmStrDup(LastMacName));
+}
+
+
+static char *
+_exec_echo(data)
+char *data;
+{
+ return(DmStrDup(DmStrSpn(data," \t")));
+}
+
+
+static char *
+_exec_call( var, list )
+char *var;
+char *list;
+{
+ char *res = NIL(char);
+ char *s;
+ TKSTR tk;
+ int i=0;
+
+ list = Expand(list);
+
+ SET_TOKEN(&tk,list);
+ while( *(s=Get_token(&tk, "", FALSE)) != '\0' ) {
+ char buf[40];
+
+ sprintf(buf, "%d", i++);
+ Def_macro(buf,s,M_MULTI|M_NOEXPORT|M_FORCE|M_PUSH);
+ }
+ CLEAR_TOKEN(&tk);
+
+ var = DmStrJoin(DmStrJoin("$(",var,-1,FALSE),")",-1,TRUE);
+ res = Expand(var);
+
+ i=0;
+ SET_TOKEN(&tk,list);
+ while( *(s=Get_token(&tk, "", FALSE)) != '\0' ) {
+ HASHPTR hp;
+ char buf[40];
+
+ sprintf(buf, "%d", i++);
+ hp = GET_MACRO(buf);
+ Pop_macro(hp);
+ FREE(hp->ht_name);
+ if(hp->ht_value) FREE(hp->ht_value);
+ FREE(hp);
+ }
+ CLEAR_TOKEN(&tk);
+
+ FREE(var);
+ FREE(list);
+ return(res);
+}
+
+
+static char *
+_exec_foreach( var, list, data )
+char *var;
+char *list;
+char *data;
+{
+ char *res = NIL(char);
+ char *s;
+ TKSTR tk;
+ HASHPTR hp;
+
+ var = Expand(var);
+ list = Expand(list);
+
+ data = DmStrSpn(data," \t\n");
+ SET_TOKEN(&tk,list);
+ hp = Def_macro(var,"",M_MULTI|M_NOEXPORT|M_FORCE|M_PUSH);
+
+ while( *(s=Get_token(&tk, "", FALSE)) != '\0' ) {
+ Def_macro(var,s,M_MULTI|M_NOEXPORT|M_FORCE);
+ res = DmStrAdd(res,Expand(data),TRUE);
+ }
+
+ CLEAR_TOKEN(&tk);
+ Pop_macro(hp);
+ FREE(hp->ht_name);
+ if(hp->ht_value) FREE(hp->ht_value);
+ FREE(hp);
+ FREE(var);
+ FREE(list);
+
+ return(res);
+}
+
+
+static char *
+_exec_mktmp( file, text, data )
+char *file;
+char *text;
+char *data;
+{
+ register char *p;
+ char *tmpname;
+ char *name;
+ FILE *tmpfile = NIL(FILE);
+
+ /* This is only a test of the recipe line so prevent the tempfile side
+ * effects. */
+ if( Suppress_temp_file ) return(NIL(char));
+
+ name = Current_target ? Current_target->CE_NAME:"makefile text";
+
+ if( file && *file ) {
+ char *newtmp;
+
+ /* This call to Get_temp sets TMPFILE for subsequent expansion of file.
+ * DO NOT DELETE IT! */
+ Get_temp( &newtmp, "", FALSE ); FREE(newtmp);
+ tmpname = Expand(file);
+
+ if( *tmpname ) {
+ if( (tmpfile = fopen(tmpname, "w")) == NIL(FILE) )
+ Open_temp_error( tmpname, name );
+
+ Def_macro("TMPFILE", tmpname, M_EXPANDED|M_MULTI);
+ Link_temp( Current_target, tmpfile, tmpname );
+ }
+ else
+ FREE(tmpname);
+ }
+
+ if( !tmpfile )
+ tmpfile = Start_temp( "", Current_target, &tmpname );
+
+ if( !text || !*text ) text = tmpname;
+ data = Expand(DmStrSpn(data, " \t\n"));
+
+ for(p=strchr(data,'\n'); p; p=strchr(p,'\n')) {
+ char *q = DmStrSpn(++p," \t");
+ strcpy(p,q);
+ }
+
+/* do not map escape sequences while writing a tmpfile */
+/* Append_line( data, FALSE, tmpfile, name, FALSE, TRUE ); */
+ Append_line( data, FALSE, tmpfile, name, FALSE, FALSE );
+ Close_temp( Current_target, tmpfile );
+ FREE(data);
+
+ return( Expand(text) );
+}
+
+
+static char *
+_exec_iseq( lhs, rhs, data, eq )
+char *lhs;
+char *rhs;
+char *data;
+int eq;
+{
+ char *l = Expand(lhs);
+ char *r = Expand(rhs);
+ char *i = DmStrSpn(data, " \t\n");
+ char *e = strchr(i, ' ');
+ char *res = NIL(char);
+ int val = strcmp(l,r);
+
+ if( (!val && eq) || (val && !eq) ) {
+ if( e != NIL(char) ) *e = '\0';
+ res = Expand(i);
+ }
+ else if( e != NIL(char) ) {
+ e = DmStrSpn(e," \t\n");
+ if( *e ) res = Expand(e);
+ }
+
+ FREE(l);
+ FREE(r);
+ return(res);
+}
+
+
+static char *
+_exec_sort( args )
+char *args;
+{
+ char *res = NIL(char);
+ char *data = Expand(args);
+ char **tokens;
+ char *p;
+ char *white = " \t\n";
+ int j;
+ int i;
+
+ for(i=0,p=DmStrSpn(data,white);*p;p=DmStrSpn(DmStrPbrk(p,white),white),i++);
+
+ if( i != 0 ) {
+ TALLOC(tokens, i, char *);
+
+ for( i=0,p=DmStrSpn(data,white); *p; p=DmStrSpn(p,white),i++){
+ tokens[i] = p;
+ p = DmStrPbrk(p,white);
+ if( *p ) *p++ = '\0';
+ }
+
+ qsort( tokens, i, sizeof(char *), _mystrcmp );
+
+ for( j=0; j<i; j++ ) res = DmStrApp(res, tokens[j]);
+ FREE(data);
+ FREE(tokens);
+ }
+
+ return(res);
+}
+
+
+static char *
+_exec_uniq( args )
+char *args;
+{
+ char *res = NIL(char);
+ char *data = Expand(args);
+ char **tokens;
+ char **tokens_after;
+ char *p;
+ char *white = " \t\n";
+ int j;
+ int i;
+ char *last = "";
+ int k = 0;
+
+ for(i=0,p=DmStrSpn(data,white);*p;p=DmStrSpn(DmStrPbrk(p,white),white),i++);
+
+ if( i != 0 ) {
+ TALLOC(tokens, i, char *);
+ TALLOC(tokens_after, i, char *);
+
+ for( i=0,p=DmStrSpn(data,white); *p; p=DmStrSpn(p,white),i++){
+ tokens[i] = p;
+ p = DmStrPbrk(p,white);
+ if( *p ) *p++ = '\0';
+ }
+
+ qsort( tokens, i, sizeof(char *), _mystrcmp );
+
+ for( j=0; j<i; j++ ) {
+ if (strcmp(tokens[j], last) != 0) {
+ tokens_after[k++] = tokens[j];
+ last = tokens[j];
+ }
+ }
+
+ for( j=0; j<k; j++ ) res = DmStrApp(res, tokens_after[j]);
+ FREE(data);
+ FREE(tokens);
+ FREE(tokens_after);
+ }
+
+ return(res);
+}
+
+static int
+_mystrcmp( p, q )
+CONST PVOID p;
+CONST PVOID q;
+{
+ return(strcmp(*((CONST char **)p),*((CONST char **)q)));
+}
+
+
+static char *
+_exec_subst( pat, subst, data )
+char *pat;
+char *subst;
+char *data;
+{
+ char *res;
+
+ pat = Expand(pat);
+ subst = Expand(subst);
+ res = Apply_edit( Expand(data), pat, subst, TRUE, FALSE );
+ FREE(pat);
+ FREE(subst);
+
+ return(res);
+}
+
+
+static char *
+_exec_shell( data, mod1 )
+char *data;
+char *mod1;
+{
+ extern char *tempnam();
+ static int nestlevel = 0;
+ static int org_out;
+ static int bsize;
+ static char *buffer;
+ static char *tmpnm;
+ static FILE *tmp;
+
+ int wait = Wait_for_completion;
+ uint16 vflag = Verbose;
+ int tflag = Trace;
+ char *res = NIL(char);
+ CELL cell;
+ STRING rcp;
+ HASH cname;
+
+ if( Suppress_temp_file ) return(NIL(char));
+
+ /* Set the temp CELL used for building prerequisite candidates to
+ * all zero so that we don't have to keep initializing all the
+ * fields. */
+ {
+ register char *s = (char *) &cell;
+ register int n = sizeof(CELL);
+ while( n ) { *s++ = '\0'; n--; }
+ }
+ rcp.st_string = DmStrSpn(data, " \t+-%@");
+ rcp.st_attr = Rcp_attribute( data );
+ rcp.st_next = NIL(STRING);
+ cname.ht_name = "Shell escape";
+ cell.ce_name = &cname;
+ cell.ce_all.cl_prq = &cell;
+ cell.ce_all.cl_next = NIL(LINK);
+ cell.ce_all.cl_flag = 0;
+ cell.ce_fname = cname.ht_name;
+ cell.ce_recipe = &rcp;
+ cell.ce_flag = F_TARGET|F_RULES;
+ cell.ce_attr = A_PHONY|A_SILENT;
+
+ if( nestlevel == 0 ) {
+ tmpnm = tempnam(NIL(char),"mk");
+ org_out = dup(1);
+
+ if( (tmp = fopen(tmpnm, "w+")) == NIL(FILE) )
+ Open_temp_error( tmpnm, cname.ht_name );
+
+ close(1);
+ dup( fileno(tmp) );
+
+ bsize = (Buffer_size < BUFSIZ)?BUFSIZ:Buffer_size;
+ buffer = MALLOC(bsize,char);
+ }
+
+ Wait_for_completion = TRUE;
+ Verbose &= V_LEAVE_TMP;
+ Trace = FALSE;
+ nestlevel++;
+ Exec_commands( &cell );
+ Unlink_temp_files( &cell );
+ nestlevel--;
+ Trace = tflag;
+ Verbose = vflag;
+ Wait_for_completion = wait;
+
+ /* Now we have to read the temporary file, get the tokens and return them
+ * as a string. */
+ rewind(tmp);
+ while( fgets(buffer, bsize, tmp) ) {
+ char *p = strchr(buffer, '\n');
+
+ if( p == NIL(char) )
+ res = DmStrJoin(res,buffer,-1,TRUE);
+ else {
+ *p = '\0';
+ res = DmStrApp(res,buffer);
+ }
+ }
+
+ fclose(tmp);
+ if( nestlevel == 0 ) {
+ close(1);
+ dup(org_out);
+ close(org_out);
+ Remove_file(tmpnm);
+ FREE(tmpnm);
+ FREE(buffer);
+ }
+ else {
+ if( (tmp = fopen(tmpnm, "w+")) == NIL(FILE) )
+ Open_temp_error( tmpnm, cname.ht_name );
+
+ close(1);
+ dup( fileno(tmp) );
+ }
+
+ if ( mod1 ) {
+ mod1 = Expand(res);
+ FREE(res);
+ res = mod1;
+ }
+
+ return(res);
+}
+
+
+static int
+not (arg)
+int arg;
+{
+ return(!arg);
+}
+
+
+static int
+nop (arg)
+int arg;
+{
+ return(arg);
+}
+
+
+static char *
+_exec_andor( args, doand )
+char *args;
+int doand;
+{
+ char *next;
+ char *p;
+ char *white = " \t\n";
+ int res=doand;
+
+ args = DmStrSpn(args,white);
+ do {
+ p=ScanToken(args, &next, TRUE);
+
+ if (doand ? !*p : *p) {
+ res = !doand;
+ FREE(p);
+ break;
+ }
+
+ FREE(p);
+ }
+ while (*(args=DmStrSpn(next,white)));
+
+ return(res ? DmStrDup("t") : DmStrDup(""));
+}
+
+
+static char *
+_exec_not( args )
+char *args;
+{
+ char *white = " \t\n";
+ char *p=Expand(args);
+ int res = (*DmStrSpn(p,white) == '\0');
+
+ FREE(p);
+ return(res ? DmStrDup("t") : DmStrDup(""));
+}
diff --git a/dmake/getinp.c b/dmake/getinp.c
new file mode 100644
index 000000000000..7d2af1dc8e43
--- /dev/null
+++ b/dmake/getinp.c
@@ -0,0 +1,671 @@
+/* RCS $Id: getinp.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Handle reading of input.
+--
+-- DESCRIPTION
+-- The code in this file reads the input from the specified stream
+-- into the provided buffer of size Buffer_size. In doing so it deletes
+-- comments. Comments are delimited by the #, and
+-- <nl> character sequences. An exception is \# which
+-- is replaced by # in the input. Line continuations are signalled
+-- at the end of a line and are recognized inside comments.
+-- The line continuation is always <\><nl>.
+--
+-- If the file to read is NIL(FILE) then the Get_line routine returns the
+-- next rule from the builtin rule table if there is one.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+#define IS_WHITE(A) ((A == ' ') || (A == '\t') || (A == '\n') || (A == '\r'))
+#define SCAN_WHITE(A) \
+ while( IS_WHITE(*A) ) A++;
+
+static int _is_conditional ANSI((char*));
+static int _handle_conditional ANSI((int, TKSTRPTR));
+
+static int rule_ind = 0; /* index of rule when reading Rule_tab */
+static int skip = FALSE; /* if true the skip input */
+
+
+PUBLIC int
+Get_line( buf, fil )/*
+======================
+ Read a line of input from the file stripping
+ off comments. The routine returns TRUE if EOF */
+char *buf;
+FILE *fil;
+{
+ extern char **Rule_tab;
+ register char *p;
+ register char *c;
+ char *q;
+ char *buf_org;
+ static int ignore = FALSE;
+ int cont = FALSE;
+ int pos = 0;
+ int res;
+ register char *tmp = NIL(char);
+
+ DB_ENTER( "Get_line" );
+
+ if( Skip_to_eof ) {
+ Skip_to_eof = FALSE;
+ rule_ind = 0;
+
+ if( Verbose & V_MAKE )
+ Warning("Ignoring remainder of file %s", Filename());
+
+ DB_RETURN(TRUE);
+ }
+
+ if( fil == NIL(FILE) ) {
+ /* Reading the internal rule table. Set the rule_index to zero.
+ * This way ReadEnvironment works as expected every time. */
+
+ while( (p = Rule_tab[ rule_ind++ ]) != NIL(char) )
+ /* The last test in this if *p != '~', handles the environment
+ * passing conventions used by MKS to pass arguments. We want to
+ * skip those environment entries. */
+ if( !Readenv || (Readenv && (strchr(p,'=') != NIL(char)) && *p!='~')){
+ strcpy( buf, p );
+
+ DB_PRINT( "io", ("Returning [%s]", buf) );
+ DB_RETURN( FALSE );
+ }
+
+ rule_ind = 0;
+
+ DB_PRINT( "io", ("Done Ruletab") );
+ DB_RETURN( TRUE );
+ }
+
+ buf_org = buf;
+
+do_again:
+ do {
+ p = buf+pos;
+ if(feof( fil ) || (fgets( p, Buffer_size-pos, fil ) == NIL(char)))
+ DB_RETURN( TRUE );
+
+#ifdef _MPW
+ if ( p[0] == 10 && p[1] == COMMENT_CHAR)
+ p[0] = ' ';
+#endif
+
+ Line_number++;
+
+ /* ignore input if ignore flag set and line ends in a continuation
+ character. */
+ q = p+strlen(p)-2;
+ if( q<p ) q=p;
+
+ /* ignore each RETURN at the end of a line before any further
+ * processing */
+ if( q[0] == '\r' && q[1] == '\n' ) {
+ q[0] = '\n';
+ q[1] = '\0';
+ q--;
+ }
+ /* you also have to deal with END_OF_FILE chars to process raw
+ * DOS-Files. Normally they are the last chars in file, but after
+ * working on these file with vi, there is an additional NEWLINE
+ * after the last END_OF_FILE. So if the second last char in the
+ * actual line is END_OF_FILE, you can skip the last char. Then
+ * you can search the line back until you find no more END_OF_FILE
+ * and nuke each you found by string termination. */
+ if( q[0] == '\032' )
+ q--;
+ while( q[1] == '\032' ) {
+ q[1] = '\0';
+ q--;
+ }
+
+ if( ignore ) {
+ if( q[0] != CONTINUATION_CHAR || q[1] != '\n' ) ignore = FALSE;
+ *p = '\0';
+ continue;
+ }
+
+ c = Do_comment(p, &q, Group || (*buf == '\t') || (Notabs && *buf ==' '));
+
+ /* Does the end of the line end in a continuation sequence? */
+
+ if( (q[0] == CONTINUATION_CHAR) && (q[1] == '\n')) {
+ /* If the continuation was at the end of a comment then ignore the
+ * next input line, (or lines until we get one ending in just <nl>)
+ * else it's a continuation, so build the input line from several
+ * text lines on input. The maximum size of this is governened by
+ * Buffer_size */
+ if( q != p && q[-1] == CONTINUATION_CHAR ) {
+ strcpy( q, q+1 );
+ q--;
+ cont = FALSE;
+ }
+ else if( c != NIL(char) )
+ ignore = TRUE;
+ else
+ cont = TRUE;
+ }
+ else {
+ cont = FALSE;
+ }
+
+ q = ( c == NIL(char) ) ? q+2 : c;
+ pos += q-p;
+ }
+ while( (cont || !*buf) && (pos <= Buffer_size) );
+
+ if( buf[ pos-1 ] == '\n' )
+ buf[ --pos ] = '\0';
+ else
+ if( pos == Buffer_size-1 )
+ Fatal( "Input line too long, increase MAXLINELENGTH" );
+
+ /* STUPID AUGMAKE uses "include" at the start of a line as
+ * a signal to include a new file, so let's look for it.
+ * if we see it replace it by .INCLUDE: and stick this back
+ * into the buffer. We also allow GNU make if[n]eq/else/endif.
+ *
+ * These substitutions are made only if we are not parsing a group
+ * recipe. */
+ if( (p = DmStrSpn(buf, " \t\r\n")) == NIL(char) )
+ p = buf;
+
+ if (!Group) {
+ if( !strncmp( "include", p, 7 ) &&
+ (p[7] == ' ' || p[7] == '\t') )
+ tmp = DmStrJoin( ".INCLUDE:", p+7, -1, FALSE );
+ else if( !strncmp( "ifeq", p, 4 ) &&
+ (p[4] == ' ' || p[4] == '\t') )
+ tmp = DmStrJoin( ".IFEQ", p+4, -1, FALSE );
+ else if( !strncmp( "ifneq", p, 5 ) &&
+ (p[5] == ' ' || p[5] == '\t') )
+ tmp = DmStrJoin( ".IFNEQ", p+5, -1, FALSE );
+ else if( !strncmp( "elif", p, 4 ) &&
+ (p[4] == ' ' || p[4] == '\t') )
+ tmp = DmStrJoin( ".ELIF", p+4, -1, FALSE );
+ else if( !strncmp( "else", p, 4 ) &&
+ (p[4] == ' ' || p[4] == '\t' || p[4] == '\0') )
+ tmp = DmStrJoin( ".ELSE", p+4, -1, FALSE );
+ else if( !strncmp( "endif", p, 5 ) &&
+ (p[5] == ' ' || p[5] == '\t' || p[5] == '\0') )
+ tmp = DmStrJoin( ".END", p+5, -1, FALSE );
+ }
+
+ if( tmp != NIL(char)) {
+ strcpy( buf, tmp );
+ FREE( tmp );
+ tmp = NIL(char);
+ }
+
+ /* Now that we have the next line of input to make, we should check to
+ * see if it is a conditional expression. If it is then process it,
+ * otherwise pass it on to the parser. */
+
+ if( *(p = DmStrSpn(buf, " \t\r\n")) == CONDSTART ) {
+ TKSTR token;
+
+ SET_TOKEN( &token, p );
+
+ p = Get_token( &token, "", FALSE );
+
+ if( (res = _is_conditional(p)) != 0 ) /* ignore non-control special */
+ { /* targets */
+ res = _handle_conditional( res, &token );
+ skip = TRUE;
+ }
+ else {
+ CLEAR_TOKEN( &token );
+ res = TRUE;
+ }
+ }
+
+ if( skip ) {
+ buf = buf_org; /* ignore line just read in */
+ pos = 0;
+ skip = res;
+ goto do_again;
+ }
+
+ DB_PRINT( "io", ("Returning [%s]", buf) );
+ DB_RETURN( FALSE );
+}
+
+
+PUBLIC char *
+Do_comment(str, pend, keep)/*
+=============================
+ Search the input string looking for comment chars. If it contains
+ comment chars then NUKE the remainder of the line, if the comment
+ char is preceeded by \ then shift the remainder of the line left
+ by one char. */
+char *str;
+char **pend;
+int keep;
+{
+ char *c = str;
+
+ while( (c = strchr(c, COMMENT_CHAR)) != NIL(char) ) {
+ if( Comment || State == NORMAL_SCAN )
+ if( c != str && c[-1] == ESCAPE_CHAR ) {
+ strcpy( c-1, c ); /* copy it left, due to \# */
+ if( pend ) (*pend)--; /* shift tail pointer left */
+ }
+ else {
+ if( !No_exec
+ && c == str
+ && c[1] == '!'
+ && Line_number == 1
+ && Nestlevel() == 1 ) {
+ char *cmnd;
+
+ cmnd = Expand(c+2);
+ cmnd[strlen(cmnd)-1] = '\0'; /* strip last newline */
+ Current_target = Root;
+ Swap_on_exec = TRUE;
+ Wait_for_completion = TRUE;
+ Do_cmnd(cmnd, FALSE, TRUE, Current_target, FALSE, FALSE, TRUE);
+ }
+
+ *c = '\0'; /* a true comment so break */
+ break;
+ }
+ else {
+ if( keep )
+ c = NIL(char);
+ else
+ *c = '\0';
+
+ break;
+ }
+ }
+
+ return(c);
+}
+
+
+PUBLIC char *
+Get_token( string, brk, anchor )/*
+==================================
+ Return the next token in string.
+
+ Returns empty string when no more tokens in string.
+ brk is a list of chars that also cause breaks in addition to space and
+ tab, but are themselves returned as tokens. if brk is NULL then the
+ remainder of the line is returned as a single token.
+
+ 'anchor' if 1, says break on chars in the brk list, but only if
+ the entire token begins with the first char of the brk list, if
+ 0 then any char of brk will cause a break to occurr.
+
+ If 'anchor' is 2, then break only seeing the first char in the break
+ list allowing only chars in the break list to form the prefix. */
+
+TKSTRPTR string;
+char *brk;
+int anchor;
+{
+ register char *s;
+ register char *curp;
+ register char *t;
+ int done = FALSE;
+ char space[100];
+
+ DB_ENTER( "Get_token" );
+
+ s = string->tk_str; /* Get string parameters */
+ *s = string->tk_cchar; /* ... and strip leading w/s */
+
+ SCAN_WHITE( s );
+
+ DB_PRINT( "tok", ("What's left [%s]", s) );
+
+ if( !*s ) {
+ DB_PRINT( "tok", ("Returning NULL token") );
+ DB_RETURN( "" );
+ }
+
+
+ /* Build the space list. space contains all those chars that may possibly
+ * cause breaks. This includes the brk list as well as white space. */
+
+ if( brk != NIL(char) ) {
+ strcpy( space, " \t\r\n" );
+ strcat( space, brk );
+ }
+ else {
+ space[0] = 0xff; /* a char we know will not show up */
+ space[1] = 0;
+ }
+
+
+ /* Handle processing of quoted tokens. Note that this is disabled if
+ * brk is equal to NIL */
+
+ while( *s == '\"' && ((brk != NIL(char)) || !string->tk_quote) ) {
+ s++;
+ if( string->tk_quote ) {
+ curp = s-1;
+ do { curp = strchr( curp+1, '\"' ); }
+ while( (curp != NIL(char)) && (*(curp+1) == '\"'));
+
+ if( curp == NIL(char) ) Fatal( "Unmatched quote in token" );
+ string->tk_quote = !string->tk_quote;
+
+ /* Check for "" case, and if found ignore it */
+ if( curp == s ) continue;
+ goto found_token;
+ }
+ else
+ SCAN_WHITE( s );
+
+ string->tk_quote = !string->tk_quote;
+ }
+
+
+ /* Check for a token break character at the beginning of the token.
+ * If found return the next set of break chars as a token. */
+
+ if( anchor == 2 && brk != NIL(char) ) {
+ curp = s;
+ while( *curp && (strchr(brk,*curp)!=NIL(char)) && (*curp!=*brk) ) curp++;
+ done = (*brk == *curp++);
+ }
+ else if( (brk != NIL(char)) && (strchr( brk, *s ) != NIL(char)) ) {
+ curp = DmStrSpn( s, brk );
+ done = (anchor == 0) ? TRUE :
+ ((anchor == 1)?(*s == *brk) : (*brk == curp[-1]));
+ }
+
+
+ /* Scan for the next token in the list and return it less the break char
+ * that was used to terminate the token. It will possibly be returned in
+ * the next call to Get_token */
+
+ if( !done ) {
+ SCAN_WHITE( s );
+
+ t = s;
+ do {
+ done = TRUE;
+ curp = DmStrPbrk(t, space);
+
+ if( anchor && *curp && !IS_WHITE( *curp ) )
+ if( ((anchor == 1)?*curp:DmStrSpn(curp,brk)[-1]) != *brk ) {
+ t++;
+ done = FALSE;
+ }
+ }
+ while( !done );
+
+ if( (curp == s) && (strchr(brk, *curp) != NIL(char)) ) curp++;
+ }
+
+found_token:
+ string->tk_str = curp;
+ string->tk_cchar = *curp;
+ *curp = '\0';
+
+ DB_PRINT( "tok", ("Returning [%s]", s) );
+ DB_RETURN( s );
+}
+
+
+static int
+_is_conditional( tg )/*
+=======================
+ Look at tg and return it's value if it is a conditional identifier
+ otherwise return 0. */
+char *tg;
+{
+ DB_ENTER( "_is_conditional" );
+
+ tg++;
+ switch( *tg ) {
+ case 'I': if( !strcmp( tg, "IF" )) DB_RETURN( ST_IF );
+ else if( !strcmp( tg, "IFEQ" )) DB_RETURN( ST_IFEQ );
+ else if( !strcmp( tg, "IFNEQ" )) DB_RETURN( ST_IFNEQ ); break;
+
+ case 'E':
+ if( !strcmp( tg, "END" )) DB_RETURN( ST_END );
+ else if( !strcmp( tg, "ENDIF")) DB_RETURN( ST_END );
+ else if( !strcmp( tg, "ELSE" )) DB_RETURN( ST_ELSE );
+ else if( !strcmp( tg, "ELIF" )) DB_RETURN( ST_ELIF );
+ break;
+ }
+
+ DB_RETURN( 0 );
+}
+
+
+
+#define SEEN_END 0x00
+#define SEEN_IF 0x01
+#define SEEN_ELSE 0x02
+#define SEEN_ELIF 0x04
+
+#define ACCEPT_IF 0x10
+#define ACCEPT_ELIF 0x20
+
+static int
+_handle_conditional( opcode, tg )/*
+===================================
+ Perform the necessary processing for .IF conditinal targets.
+ Someday this should be modified to do bracketted expressions ala
+ CPP... sigh */
+int opcode;
+TKSTRPTR tg;
+{
+ static short action[MAX_COND_DEPTH];
+ static char ifcntl[MAX_COND_DEPTH];
+ char *tok, *lhs, *rhs, *op, *expr;
+ char *lop, *partstr;
+ int result, n, m;
+
+ DB_ENTER( "_handle_conditional" );
+
+ switch( opcode ) {
+ case ST_ELIF:
+ if( !(ifcntl[Nest_level] & SEEN_IF) || (ifcntl[Nest_level]&SEEN_ELSE) )
+ Fatal(".ELIF without a preceeding .IF" );
+ /*FALLTHRU*/
+
+ case ST_IF:
+ case ST_IFEQ:
+ case ST_IFNEQ:
+ if( opcode != ST_ELIF && (Nest_level+1) == MAX_COND_DEPTH )
+ Fatal( ".IF .ELSE ... .END nesting too deep" );
+
+ If_expand = TRUE;
+ expr = Expand( Get_token( tg, NIL(char), FALSE ));
+ If_expand = FALSE;
+ lhs = DmStrSpn( expr, " \t" );
+ if( !*lhs ) lhs = NIL(char);
+
+ if ( (lop = DmStrStr(lhs, "&&" )) != NIL(char) )
+ Fatal( ".IF do not support && " );
+ if ( (lop = DmStrStr(lhs, "defined" )) != NIL(char) )
+ Fatal( ".IF do not support defined " );
+ if ( (lop = DmStrStr(lhs, "DEFINED" )) != NIL(char) )
+ Fatal( ".IF do not support defined " );
+/*-----------------18.03.99 14:38-------------------
+ * hjs - simple OR fixed and less code
+--------------------------------------------------*/
+ if ( (lop = DmStrStr(lhs, "||" )) != NIL(char) )
+ {
+/* printf("todo: %s\n", expr ); */
+ partstr = MALLOC( strlen (lhs ) + 5, char);
+ result = FALSE;
+ while(( lop = DmStrStr(lhs, "||" )) != NIL(char) )
+ {
+ n = strlen( lop );
+ m = strlen( lhs );
+ strncpy( partstr, lhs, m - n );
+ partstr[ m - n ] = '\0';
+ result |= partcomp( partstr, opcode);
+ lhs = lop+2;
+ lhs = DmStrSpn( lhs, " \t" );
+ }
+ result |= partcomp( lhs, opcode );
+/*
+ if ( result )
+ printf("TRUE\n\n");
+ else
+ printf("false\n\n");
+ FREE( partstr );
+*/
+ }
+/*--------------------------------------------------*/
+ else
+ result = partcomp( lhs, opcode );
+
+ if( expr != NIL(char) ) FREE( expr );
+
+ if( opcode != ST_ELIF ) {
+ Nest_level++;
+ action[Nest_level] = 1;
+ }
+ ifcntl[Nest_level] |= (opcode==ST_ELIF)?SEEN_ELIF:SEEN_IF;
+
+ if( result ) {
+ if( !(ifcntl[Nest_level] & (ACCEPT_IF|ACCEPT_ELIF)) ) {
+ action[ Nest_level ] = action[ Nest_level-1 ];
+ ifcntl[Nest_level] |= (opcode==ST_ELIF)?ACCEPT_ELIF:ACCEPT_IF;
+ }
+ else
+ action[Nest_level] = 1;
+ }
+ else
+ action[Nest_level] = 1;
+ break;
+
+ case ST_ELSE:
+ if( Nest_level <= 0 ) Fatal( ".ELSE without .IF" );
+ if( ifcntl[Nest_level] & SEEN_ELSE )
+ Fatal( "Missing .IF or .ELIF before .ELSE" );
+
+ if( ifcntl[Nest_level] & (ACCEPT_IF|ACCEPT_ELIF) )
+ action[Nest_level] = 1;
+ else if( action[ Nest_level-1 ] != 1 )
+ action[ Nest_level ] ^= 0x1; /* flip between 0 and 1 */
+
+ ifcntl[Nest_level] |= SEEN_ELSE;
+ break;
+
+ case ST_END:
+ ifcntl[Nest_level] = SEEN_END;
+ Nest_level--;
+ if( Nest_level < 0 ) Fatal( "Unmatched .END[IF]" );
+ break;
+ }
+
+ DB_RETURN( action[ Nest_level ] );
+}
+
+
+int partcomp( char* lhs, int opcode )
+{
+
+ char *tok, *rhs, *op;
+ int result, opsind;
+ const int localopscount=4;
+ char* localops[]={"==","!=","<=",">="};
+ int lint, rint;
+
+#define EQUAL 0
+#define NOTEQUAL 1
+#define LESS_EQUAL 2
+#define GREATER_EQUAL 3
+
+ opsind=0;
+/* printf( "eval: %s\n", lhs);*/
+ if( opcode == ST_IFEQ || opcode == ST_IFNEQ ) { /* no == */
+ for( op = lhs; ((*op)&&(*op != ' ')&&(*op != '\t')); op++ );
+ if( *op )
+ op++;
+ else
+ op = NIL(char);
+ } else while ( opsind < localopscount && (op = DmStrStr( lhs, localops[opsind] )) == NIL(char))
+ {
+/* printf("%d %s\n", opsind, localops[opsind]);*/
+ opsind++;
+ }
+
+/* if ( opsind == localopscount )
+ Fatal( "Unknown Operator\n" );*/
+
+ if( op == NIL(char) )
+ result = (lhs != NIL(char));
+ else {
+/* printf("op#%s\n",op);*/
+ if( opcode != ST_IFEQ && opcode != ST_IFNEQ ) /* no == */
+ op[1] = op[0];
+/* printf("op#%s\n",op);*/
+ if( lhs != op ) {
+ for( tok = op-1; (tok != lhs) && ((*tok == ' ')||(*tok == '\t'));
+ tok-- );
+ tok[1] = '\0';
+ }
+ else
+ lhs = NIL(char);
+
+ if( opcode == ST_IFEQ || opcode == ST_IFNEQ ) /* no == */
+ op--;
+ else
+ op++;
+ rhs = DmStrSpn( op+1, " \t" );
+ if( !*rhs ) rhs = NIL(char);
+
+ if ( opsind > NOTEQUAL ) {
+/* printf("new ops\n");*/
+ switch( opsind ){
+ case LESS_EQUAL:
+ case GREATER_EQUAL:
+ if ( lhs[0] == '"' ) lhs++;
+ if ( rhs[0] == '"' ) rhs++;
+ lint = atoi( lhs );
+ rint = atoi( rhs );
+ result = ( lint >= rint ) ? TRUE : FALSE;
+ if ( opsind == LESS_EQUAL && lint != rint )
+ result = !result;
+ break;
+ default:
+ result = FALSE;
+ }
+ }
+ else {
+ if( (rhs == NIL(char)) || (lhs == NIL(char)) )
+ result = (rhs == lhs) ? TRUE : FALSE;
+ else {
+ tok = rhs + strlen( rhs );
+ for( tok=tok-1; (tok != lhs) && ((*tok == ' ')||(*tok == '\t'));
+ tok--);
+ tok[1] = '\0';
+
+ result = (strcmp( lhs, rhs ) == 0) ? TRUE : FALSE;
+ }
+ if( *op == '!' || opcode == ST_IFNEQ ) result = !result;
+ }
+ }
+/* printf("partresult %d\n",result);*/
+ return result;
+};
+
diff --git a/dmake/hash.c b/dmake/hash.c
new file mode 100644
index 000000000000..c2387da4456b
--- /dev/null
+++ b/dmake/hash.c
@@ -0,0 +1,52 @@
+/* RCS $Id: hash.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Hashing function for hash tables.
+--
+-- DESCRIPTION
+-- Hash an identifier. The hashing function works by computing the sum
+-- of each char and the previous hash value multiplied by 129. Finally the
+-- length of the identifier is added in. This way the hash depends on the
+-- chars as well as the length, and appears to be sufficiently unique,
+-- and is FAST to COMPUTE, unlike the previous hash function...
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+PUBLIC uint16
+Hash( id, phv )/*
+=================
+ This function computes the identifier's hash value and returns the hash
+ value modulo the key size as well as the full hash value. The reason
+ for returning both is so that hash table searches can be sped up. You
+ compare hash keys instead and compare strings only for those whose 32-bit
+ hash keys match. (not many) */
+
+char *id;
+uint32 *phv;
+{
+ register char *p = id;
+ register uint32 hash = (uint32) 0;
+
+ while( *p ) hash = (hash << 7) + hash + (uint32) (*p++);
+ *phv = hash = hash + (uint32) (p-id);
+
+ return( (uint16) (hash % HASH_TABLE_SIZE) );
+}
+
diff --git a/dmake/imacs.c b/dmake/imacs.c
new file mode 100644
index 000000000000..bb92255d7ed1
--- /dev/null
+++ b/dmake/imacs.c
@@ -0,0 +1,181 @@
+/* RCS $Id: imacs.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Define default internal macros.
+--
+-- DESCRIPTION
+-- This file adds to the internal macro tables the set of default
+-- internal macros, and for those that are accessible internally via
+-- variables creates these variables, and initializes them to point
+-- at the default values of these macros.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+#include "version.h"
+
+static void _set_int_var ANSI((char *, char *, int, int *));
+static void _set_string_var ANSI((char *, char *, int, char **));
+static void _set_bit_var ANSI((char *, char *, int));
+
+/*
+** Arrange to parse the strings stored in Rules[]
+*/
+PUBLIC void
+Make_rules()
+{
+ Parse(NIL(FILE));
+}
+
+
+#define M_FLAG M_DEFAULT | M_EXPANDED
+
+/*
+** Add to the macro table all of the internal macro variables plus
+** create secondary variables which will give access to their values
+** easily, both when needed and when the macro value is modified.
+** The latter is accomplished by providing a flag in the macro and a field
+** which gives a pointer to the value if it is a char or string macro value
+** and a mask representing the bit of the global flag register that is affected
+** by this macro's value.
+*/
+PUBLIC void
+Create_macro_vars()
+{
+ static char* switchar;
+ static char* version;
+ char swchar[2];
+ char buf[20];
+
+ swchar[0] = Get_switch_char(), swchar[1] = '\0';
+ _set_string_var("SWITCHAR", swchar, M_PRECIOUS, &switchar);
+ if (*swchar == '/')
+ DirSepStr = "\\";
+ else
+#if (_MPW)
+ DirSepStr = ":";
+#else
+ DirSepStr = "/";
+#endif
+ _set_string_var("DIRSEPSTR", DirSepStr, M_DEFAULT,&DirSepStr);
+ _set_string_var("DIRBRKSTR", DirBrkStr, M_DEFAULT, &DirBrkStr);
+ swchar[0] = DEF_ESCAPE_CHAR, swchar[1] = '\0';
+ _set_string_var(".ESCAPE_PREFIX", swchar, M_FLAG, &Escape_char);
+
+ _set_bit_var(".SILENT", "", A_SILENT );
+ _set_bit_var(".IGNORE", "", A_IGNORE );
+ _set_bit_var(".PRECIOUS", "", A_PRECIOUS);
+ _set_bit_var(".EPILOG", "", A_EPILOG );
+ _set_bit_var(".PROLOG", "", A_PROLOG );
+ _set_bit_var(".NOINFER", "", A_NOINFER );
+ _set_bit_var(".SEQUENTIAL","",A_SEQ );
+ _set_bit_var(".USESHELL", "", A_SHELL );
+ _set_bit_var(".SWAP", "", A_SWAP );
+ _set_bit_var(".MKSARGS", "", A_MKSARGS );
+ _set_bit_var(".IGNOREGROUP","",A_IGNOREGROUP);
+
+ Glob_attr = A_DEFAULT; /* set all flags to NULL */
+
+ _set_string_var("SHELL", "", M_DEFAULT, &Shell );
+ _set_string_var("SHELLFLAGS", " ", M_DEFAULT, &Shell_flags );
+ _set_string_var("GROUPSHELL", "", M_DEFAULT, &GShell );
+ _set_string_var("GROUPFLAGS", " ", M_DEFAULT, &GShell_flags);
+ _set_string_var("SHELLMETAS", "", M_DEFAULT, &Shell_metas );
+ _set_string_var("GROUPSUFFIX", "", M_DEFAULT, &Grp_suff );
+ _set_string_var("AUGMAKE",NIL(char), M_DEFAULT, &Augmake );
+ _set_string_var(".KEEP_STATE", "", M_DEFAULT, &Keep_state );
+ _set_string_var(".NOTABS", "", M_MULTI, &Notabs );
+ _set_string_var(".DIRCACHE", "y", M_DEFAULT, &UseDirCache );
+ _set_string_var(".DIRCACHERESPECTCASE", "", M_DEFAULT, &DcacheRespCase);
+
+ _set_string_var("MAKEDIR",Get_current_dir(),M_PRECIOUS|M_NOEXPORT,&Makedir);
+ _set_string_var("MAKEVERSION", VERSION, M_DEFAULT|M_PRECIOUS, &version);
+ _set_string_var("PWD", Makedir, M_DEFAULT|M_NOEXPORT, &Pwd);
+ _set_string_var("TMD", "", M_DEFAULT|M_NOEXPORT, &Tmd);
+
+ Def_macro("NULL", "", M_PRECIOUS|M_NOEXPORT|M_FLAG);
+
+ _set_int_var( "MAXLINELENGTH", "0", M_DEFAULT|M_NOEXPORT, &Buffer_size );
+ _set_int_var( "PREP", "0", M_DEFAULT, &Prep );
+ (void) Def_macro("MAXLINELENGTH", "1024", M_FLAG | M_DEFAULT);
+
+ /* set MAXPROCESSLIMIT high initially so that it allows MAXPROCESS to
+ * change from command line. */
+ _set_int_var( "MAXPROCESSLIMIT", "100", M_DEFAULT|M_NOEXPORT,&Max_proclmt );
+ _set_int_var( "MAXPROCESS", "1", M_DEFAULT|M_NOEXPORT, &Max_proc );
+ _set_int_var( "DYNAMICNESTINGLEVEL", "100", M_DEFAULT|M_NOEXPORT,
+ &DynamicNestLevel);
+ sprintf(buf,"%d",NAME_MAX);
+ _set_int_var( "NAMEMAX", buf, M_DEFAULT|M_NOEXPORT, &NameMax);
+}
+
+
+/*
+** Define an integer variable value, and set up the macro.
+*/
+static void
+_set_int_var(name, val, flag, var)
+char *name;
+char *val;
+int flag;
+int *var;
+{
+ HASHPTR hp;
+
+ hp = Def_macro(name, val, M_FLAG | flag);
+ hp->ht_flag |= M_VAR_INT | M_MULTI | M_INIT;
+ hp->MV_IVAR = var;
+ *var = atoi(val);
+}
+
+
+/*
+** Define a string variables value, and set up the macro.
+*/
+static void
+_set_string_var(name, val, flag, var)
+char *name;
+char *val;
+int flag;
+char **var;
+{
+ HASHPTR hp;
+
+ hp = Def_macro(name, val, M_FLAG | flag);
+ hp->ht_flag |= M_VAR_STRING | M_MULTI | M_INIT;
+ hp->MV_SVAR = var;
+ *var = hp->ht_value;
+}
+
+
+/*
+** Define a bit variable value, and set up the macro.
+*/
+static void
+_set_bit_var(name, val, mask)
+char *name;
+char *val;
+int mask;
+{
+ HASHPTR hp;
+
+ hp = Def_macro(name, val, M_FLAG);
+ hp->ht_flag |= M_VAR_BIT | M_MULTI | M_INIT;
+ hp->MV_MASK = mask;
+ hp->MV_BVAR = &Glob_attr;
+}
diff --git a/dmake/infer.c b/dmake/infer.c
new file mode 100644
index 000000000000..478db5867f9a
--- /dev/null
+++ b/dmake/infer.c
@@ -0,0 +1,832 @@
+/* RCS $Id: infer.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Infer how to make a target.
+--
+-- DESCRIPTION
+-- This file contains the code to infer a recipe, and possibly some new
+-- prerequisites for a target which dmake does not know how to make, or
+-- has no explicit recipe.
+--
+-- The inference fails if no path through the inference graph can be
+-- found by which we can make the target.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+/* attributes that get transfered from the % start cell to the inferred
+ * cells. */
+
+#define A_TRANSFER (A_EPILOG | A_PRECIOUS | A_SILENT | A_SHELL | A_SETDIR |\
+ A_SEQ | A_LIBRARY | A_IGNORE | A_PROLOG | A_SWAP |\
+ A_NOSTATE )
+
+
+/* Define local static functions */
+static DFALINKPTR dfa_subset ANSI((DFALINKPTR, DFASETPTR));
+static void free_dfas ANSI((DFALINKPTR));
+static int count_dots ANSI((char *));
+static char * buildname ANSI((char *, char *, char *));
+static void free_icells ANSI((void));
+static ICELLPTR union_iset ANSI((ICELLPTR, ICELLPTR));
+static ICELLPTR add_iset ANSI((ICELLPTR,ICELLPTR,CELLPTR,DFALINKPTR,
+ CELLPTR,int,int,char *,char *, int));
+static ICELLPTR derive_prerequisites ANSI((ICELLPTR, ICELLPTR *));
+static char * dump_inf_chain ANSI((ICELLPTR, int, int));
+
+
+PUBLIC void
+Infer_recipe( cp, setdirroot )/*
+================================
+ Perform a breadth-first search of the inference graph and return if
+ possible an inferred set of prerequisites for making the current target. */
+CELLPTR cp;
+CELLPTR setdirroot;
+{
+ ICELLPTR nomatch, match;
+
+ DB_ENTER("Infer_recipe");
+
+ if( cp->ce_attr & A_NOINFER ) {DB_VOID_RETURN;}
+
+ match = NIL(ICELL);
+ nomatch = add_iset( NIL(ICELL), NIL(ICELL), NIL(CELL), NIL(DFALINK),
+ setdirroot, Prep+count_dots(cp->CE_NAME), 0,
+ DmStrDup(cp->CE_NAME), NIL(char),
+ cp->ce_time != (time_t)0L);
+
+ /* Make sure we try whole heartedly to infer at least one suffix */
+ if( nomatch->ic_dmax == 0 ) ++nomatch->ic_dmax;
+
+ DB_EXECUTE( "inf", _dump_iset("nomatch",nomatch); );
+
+ while( nomatch != NIL(ICELL) ) {
+ ICELLPTR new_nomatch = NIL(ICELL);
+ ICELLPTR ic, pmatch, mmatch;
+ CELLPTR prereq;
+ int first;
+
+ for( ic=nomatch; ic != NIL(ICELL); ic=ic->ic_next ) {
+ int ipush = FALSE;
+
+ if( ic->ic_dir ) ipush = Push_dir(ic->ic_dir, ic->ic_name, FALSE);
+ match = union_iset(match, derive_prerequisites(ic, &new_nomatch));
+ if( ipush ) Pop_dir(FALSE);
+ }
+
+ DB_EXECUTE( "inf", _dump_iset("match",match); );
+ DB_EXECUTE( "inf", _dump_iset("nomatch",new_nomatch); );
+
+ /* We have now deduced the two sets MATCH and NOMATCH. MATCH holds the
+ * set of edges that we encountered that matched. If this set is empty
+ * then we can apply transitive closure (if enabled) to the elements of
+ * NOMATCH to see if we can find some other method to make the target.
+ *
+ * If MATCH is non-empty, we have found a method for making the target.
+ * It is the shortest method for doing so (ie. uses fewest number of
+ * steps). If MATCH contains more than one element then we have a
+ * possible ambiguity.
+ */
+ if( match == NIL(ICELL) ) {
+ nomatch = new_nomatch;
+ if( Transitive ) continue;
+ goto all_done;
+ }
+
+ /* Ok, we have a set of possible matches in MATCH, we should check the
+ * set for ambiguity. If more than one inference path exists of the
+ * same depth, then we may issue an ambiguous inference error message.
+ *
+ * The message is suppressed if MATCH contains two elements and one of
+ * them is the empty-prerequisite-rule. In this case we ignore the
+ * ambiguity and take the rule that infers the prerequisite.
+ *
+ * Also if there are any chains that rely on a non-existant prerequisite
+ * that may get made because it has a recipe then we prefer any that
+ * rely on existing final prerequisites over those that we have to make.
+ */
+
+ /* Split out those that have to be made from those that end in
+ * prerequisites that already exist. */
+ pmatch = mmatch = NIL(ICELL);
+ for(; match; match = ic ) {
+ ic = match->ic_next;
+ match->ic_next = NIL(ICELL);
+
+ if( match->ic_exists )
+ pmatch = union_iset(pmatch, match);
+ else
+ mmatch = union_iset(mmatch, match);
+ }
+
+ if( pmatch )
+ match = pmatch;
+ else
+ match = mmatch;
+
+ /* Make sure it is unique */
+ if( match->ic_next != NIL(ICELL) ) {
+ int dump = (match->ic_next->ic_next != NIL(ICELL));
+
+ /* Check for definite ambiguity */
+ if( !dump )
+ if( (match->ic_meta->ce_prq && match->ic_next->ic_meta->ce_prq) ||
+ (!match->ic_meta->ce_prq && !match->ic_next->ic_meta->ce_prq) )
+ dump = TRUE;
+ else if(!match->ic_meta->ce_prq && match->ic_next->ic_meta->ce_prq )
+ match = match->ic_next;
+
+ if( dump ) {
+ int count = 1;
+
+ Continue = TRUE;
+ Error( "Ambiguous inference chains for target '%s'", cp->CE_NAME );
+ for( ic=match; ic; ic=ic->ic_next )
+ (void) dump_inf_chain(ic, TRUE, count++);
+ Fatal( "resolve ambiguity before proceeding.");
+ /*NOTREACHED*/
+ }
+ }
+
+ /* MATCH now points at the derived recipe. We must now take cp, and
+ * construct the correct graph so that the make may proceed. */
+
+ if( Verbose & V_INFER ) {
+ char *tmp = dump_inf_chain(match, TRUE, FALSE);
+ printf("%s: Inferring prerequistes and recipes using:\n%s: ... %s\n",
+ Pname, Pname, tmp );
+ FREE(tmp); }
+
+ pmatch = NIL(ICELL);
+ prereq = NIL(CELL);
+ first = TRUE;
+
+ while( match ) {
+ CELLPTR infcell=NIL(CELL);
+
+ /* Compute the inferred prerequisite first. */
+ if( match->ic_name ) {
+ if( match->ic_meta )
+ infcell = Def_cell( match->ic_name );
+ else
+ infcell = cp;
+
+ infcell->ce_flag |= F_TARGET;
+
+ if( infcell != cp ) {
+ infcell->ce_flag |= F_INFER;
+ if( !first ) infcell->ce_flag |= F_REMOVE;
+ }
+
+ if( !match->ic_flag )
+ infcell->ce_attr |= A_NOINFER;
+
+ first = FALSE;
+ }
+
+ /* Add global prerequisites from previous rule if there are any and
+ * the recipe. */
+ if( pmatch ) {
+ CELLPTR imeta = pmatch->ic_meta;
+ LINKPTR lp;
+
+ infcell->ce_per = pmatch->ic_dfa->dl_per;
+ infcell->ce_attr |= (imeta->ce_attr & A_TRANSFER);
+
+ if( !(infcell->ce_flag & F_RULES) ) {
+ infcell->ce_flag |= (imeta->ce_flag&(F_SINGLE|F_GROUP))|F_RULES;
+ infcell->ce_recipe = imeta->ce_recipe;
+ }
+
+ /* Add any conditional macro definitions that may be associated
+ * with the inferred cell. */
+ if (imeta->ce_cond != NIL(STRING)) {
+ STRINGPTR sp,last;
+
+ last = infcell->ce_cond;
+ for(sp=imeta->ce_cond; sp; sp=sp->st_next) {
+ STRINGPTR new;
+ TALLOC(new, 1, STRING);
+ new->st_string = DmStrDup(sp->st_string);
+ if(last)
+ last->st_next = new;
+ else
+ infcell->ce_cond = new;
+ last = new;
+ }
+ }
+
+ pmatch->ic_dfa->dl_per = NIL(char);
+
+ /* If infcell already had a directory set then modify it based on
+ * whether it was the original cell or some intermediary. */
+ if( imeta->ce_dir )
+ if( infcell->ce_dir && infcell == cp ) {
+ /* cp->ce_dir was set and we have pushed the directory prior
+ * to calling this routine. We should therefore pop it and
+ * push the new concatenated directory required by the
+ * inference. */
+ infcell->ce_dir=DmStrDup(Build_path(infcell->ce_dir,
+ imeta->ce_dir));
+ }
+ else
+ infcell->ce_dir = imeta->ce_dir;
+
+ for( lp=imeta->ce_indprq; lp != NIL(LINK); lp=lp->cl_next ) {
+ char *name = lp->cl_prq->CE_NAME;
+ CELLPTR tcp;
+
+ name = buildname( cp->CE_NAME, name, infcell->ce_per );
+ tcp = Def_cell( name );
+ tcp->ce_flag |= F_REMOVE;
+ Add_prerequisite( infcell, tcp, FALSE, FALSE );
+
+ if( Verbose & V_INFER )
+ printf( "%s: Inferred indirect prerequisite [%s]\n",
+ Pname, name );
+ FREE(name);
+ }
+ }
+
+ /* Add the previous cell as the prerequisite */
+ if( prereq )
+ (Add_prerequisite(infcell,prereq,FALSE,FALSE))->cl_flag |=F_TARGET;
+
+ pmatch = match;
+ prereq = infcell;
+ match = match->ic_parent;
+ }
+
+ DB_PRINT("inf", ("Terminated due to a match"));
+ break;
+ }
+
+all_done:
+ free_icells();
+
+ DB_VOID_RETURN;
+}
+
+
+static ICELLPTR
+derive_prerequisites( ic, nnmp )/*
+===================================
+ Take a cell and derive a set of prerequisites from the cell. Categorize
+ them into those that MATCH (ie. those that we found in the file system),
+ and those that do not match NOMATCH that we may possibly have a look at
+ later. When we process the next level of the breadth-first search.
+
+ Once MATCH is non-empty we will stop inserting elements into NOMATCH
+ since we know that either MATCH is successful and unique or it will
+ issue an ambiguity error. We will never go on to look at elements
+ in NOMATCH after wards. */
+ICELLPTR ic;
+ICELLPTR *nnmp;
+{
+ ICELLPTR match = NIL(ICELL);
+ DFALINKPTR pdfa;
+ DFALINKPTR dfas;
+
+ DB_ENTER("derive_prerequisites");
+
+ /* If none of the inference nodes match then forget about the inference.
+ * The user did not tell us how to make such a target. We also stop the
+ * Inference if the new set of DFA's is a proper subset of a previous
+ * subset and it's PREP counts exceed the value of Prep.
+ */
+ dfas = dfa_subset( Match_dfa(ic->ic_name), &ic->ic_dfastack );
+
+ DB_EXECUTE("inf", _dump_dfa_stack(dfas, &ic->ic_dfastack); );
+
+ /* Ok, we have nothing here to work with so return an empty cell. */
+ if( dfas == NIL(DFALINK) ) {
+ DB_PRINT( "mem", ("%s:<- mem %ld",ic->ic_name, (long)coreleft()));
+ DB_PRINT( "inf", ("<<< Exit, no dfas, cp = %04x", NIL(CELL)) );
+ DB_RETURN( NIL(ICELL) );
+ }
+
+ /* Save the dfas, we are going to use on the stack for this cell. */
+ ic->ic_dfastack.df_set = dfas;
+
+ /* Run through the %-meta cells, build the prerequisite cells. For each
+ * %-meta go through it's list of edges and try to use each in turn to
+ * deduce a likely prerequisite. We perform a breadth-first search
+ * matching the first path that results in a unique method for making the
+ * target. */
+ for( pdfa = dfas; pdfa != NIL(DFALINK); pdfa = pdfa->dl_next ) {
+ LINK tl;
+ LINKPTR edge;
+ CELLPTR pmeta;
+
+ pmeta = pdfa->dl_meta;
+ DB_PRINT( "inf", ("Using dfa: [%s]", pmeta->CE_NAME) );
+
+ /* If the %-meta is a singleton meta then deal with it differently from
+ * the case when it is a bunch of %-meta's found on the original entries
+ * prerequisite list. */
+ if( pmeta->ce_flag & F_MULTI )
+ edge = pmeta->ce_prq;
+ else {
+ tl.cl_prq = pmeta;
+ tl.cl_next = NIL(LINK);
+ edge = &tl;
+ }
+
+ /* Now run through the list of prerequisite edge's for the %-meta. */
+ for( ; edge != NIL(LINK); edge = edge->cl_next ) {
+ HASHPTR thp; /* temporary hash table pointer */
+ HASH iprqh; /* hash cell for new prerequisite */
+ CELL iprq; /* inferred prerequisite to look for */
+ CELLPTR idirroot; /* Inferred prerequisite root */
+ CELLPTR nidirroot; /* Inferred prerequisite root */
+ STRINGPTR ircp; /* Inferred prerequisites recipe */
+ char *idir; /* directory to CD to. */
+ int ipush = 0; /* flag for push on inferred prereq */
+ char *name = NIL(char); /* prerequisite name */
+ CELLPTR meta = edge->cl_prq;
+ int dmax_fix;
+ int trans;
+ int noinf;
+ int exists;
+
+ if( meta->ce_prq )
+ name = meta->ce_prq->cl_prq->CE_NAME;
+
+ DB_PRINT( "inf", ("Trying edge from [%s] to [%s] for [%s]",
+ meta->CE_NAME, name?name:"(nil)", ic->ic_name) );
+
+ /* Set the temp CELL used for building prerequisite candidates to
+ * all zero so that we don't have to keep initializing all the
+ * fields. */
+ {
+ register char *s = (char *) &iprq;
+ register int n = sizeof(CELL);
+ while( n ) { *s++ = '\0'; n--; }
+ }
+
+ nidirroot = idirroot = ic->ic_setdirroot;
+ iprq.ce_name = &iprqh;
+
+ if( name ) {
+ /* Build the prerequisite name from the %-meta prerequisite given
+ * for the %-meta rule. */
+ iprqh.ht_name = buildname( ic->ic_name, name, pdfa->dl_per );
+ if((dmax_fix = (count_dots(name)-count_dots(meta->CE_NAME))) < 0)
+ dmax_fix = 0;
+
+ if( !strcmp(ic->ic_name, iprqh.ht_name) ||
+ (count_dots(iprqh.ht_name) > ic->ic_dmax + dmax_fix) ) {
+ FREE( iprqh.ht_name );
+ continue;
+ }
+
+ DB_PRINT( "inf", ("Checking prerequisite [%s]", iprqh.ht_name) );
+
+ /* See if the prerequisite CELL has been previously defined. If
+ * it has, then make a copy of it into iprq, and use it to try
+ * the inference. We make the copy so that we don't modify the
+ * stat of the inferred cell if the inference fails.
+ */
+ thp = Get_name( iprqh.ht_name, Defs, FALSE );
+ if(thp != NIL(HASH)) {
+ iprq = *thp->CP_OWNR;
+ ircp = iprq.ce_recipe;
+ }
+ else
+ ircp = NIL(STRING);
+ }
+ else
+ iprqh.ht_name = NIL(char);
+
+
+ /* If the %-meta has a .SETDIR set then we change to the new
+ * directory prior to performing the stat of the new prerequisite.
+ * If the change of directory fails then the rule is droped from
+ * further consideration.
+ */
+ if( iprq.ce_dir ) {
+ if( (ipush = Push_dir(iprq.ce_dir, iprqh.ht_name, TRUE)) != 0 ) {
+ nidirroot = thp->CP_OWNR;
+ idir = Pwd;
+ }
+ else {
+ if( iprqh.ht_name ) FREE( iprqh.ht_name );
+ continue;
+ }
+ }
+ else
+ idir = NIL(char);
+
+
+ /* Stat the inferred prerequisite.
+ */
+ if( name ) {
+ if( Verbose & V_INFER )
+ printf( "%s: Trying prerequisite [%s] for [%s]\n", Pname,
+ iprqh.ht_name, ic->ic_name );
+
+ if( !(iprq.ce_flag & F_STAT) ) Stat_target(&iprq, FALSE, FALSE);
+ }
+
+
+ /* If the STAT succeeded or if the prerequisite has a recipe for
+ * making it then it's a match and a candidate for getting infered.
+ * Otherwise it is not a match, and we cannot yet tell if it is
+ * going to be a successful path to follow, so we save it for
+ * later consideration.
+ */
+ noinf = ((Glob_attr)&A_NOINFER);
+ if( meta->ce_prq )
+ noinf |= ((meta->ce_prq->cl_prq->ce_attr)&A_NOINFER);
+ trans = Transitive || !noinf;
+ exists = (iprq.ce_time != (time_t)0L);
+
+ if( exists || (ircp != NIL(STRING)) || !name ) {
+ match = add_iset( match, ic, meta, pdfa, idirroot, ic->ic_dmax,
+ trans, iprq.ce_name->ht_name, idir, exists );
+ DB_PRINT("inf",("Added to MATCH %s",iprq.ce_name->ht_name));
+ }
+ else if( !noinf && match == NIL(ICELL) ) {
+ *nnmp = add_iset( *nnmp, ic, meta, pdfa, nidirroot, ic->ic_dmax,
+ trans, iprq.ce_name->ht_name, idir, exists );
+ DB_PRINT("inf",("Added to NOMATCH %s",iprq.ce_name->ht_name));
+ }
+
+ /* If we pushed a directory for the inferred prerequisite then
+ * pop it.
+ */
+ if( ipush ) Pop_dir(FALSE);
+ if( iprqh.ht_name ) FREE(iprqh.ht_name);
+ }
+ }
+
+ DB_RETURN(match);
+}
+
+
+static char *
+buildname( tg, meta, per )
+char *tg;
+char *meta;
+char *per;
+{
+ char *name;
+
+ name = Apply_edit( meta, "%", per, FALSE, FALSE );
+ if( strchr(name, '$') ) {
+ HASHPTR m_at;
+ char *tmp;
+
+ m_at = Def_macro( "@", tg, M_MULTI );
+ tmp = Expand( name );
+
+ if( m_at->ht_value != NIL(char) ) {
+ FREE( m_at->ht_value );
+ m_at->ht_value = NIL(char);
+ }
+
+ if( name != meta ) FREE( name );
+ name = tmp;
+ }
+ else if( name == meta )
+ name = DmStrDup( name );
+
+ return(name);
+}
+
+
+static DFALINKPTR
+dfa_subset( pdfa, stack )/*
+============================
+ This is the valid DFA subset computation. Whenever a CELL has a Match_dfa
+ subset computed this algorithm is run to see if any of the previously
+ computed sets on the DFA stack are proper subsets of the new set. If they
+ are, then any elements of the matching subset whose Prep counts exceed
+ the allowed maximum given by Prep are removed from the computed DFA set,
+ and hence from consideration, thereby cutting off the cycle in the
+ inference graph. */
+DFALINKPTR pdfa;
+register DFASETPTR stack;
+{
+ register DFALINKPTR element;
+ DFALINKPTR nelement;
+
+ DB_ENTER( "dfa_subset" );
+
+ DB_PRINT("inf",("Computing DFA subset, PREP = %d",Prep));
+ DB_EXECUTE("inf", _dump_dfa_stack(pdfa, stack); );
+
+ for(; pdfa != NIL(DFALINK) && stack != NIL(DFASET); stack = stack->df_next) {
+ int subset = TRUE;
+
+ for( element=stack->df_set; subset && element != NIL(DFALINK);
+ element=element->dl_next ) {
+ register DFALINKPTR subel;
+
+ for( subel = pdfa;
+ subel != NIL(DFALINK) && (subel->dl_meta != element->dl_meta);
+ subel = subel->dl_next );
+
+ DB_PRINT("inf",("Looking for %s, (%s)",element->dl_meta->CE_NAME,
+ (subel != NIL(DFALINK))?"succ":"fail"));
+
+ if( (subset = (subel != NIL(DFALINK))) != 0 )
+ element->dl_member = subel;
+ }
+
+ if( subset )
+ for( element=stack->df_set; element != NIL(DFALINK);
+ element=element->dl_next ) {
+ DFALINKPTR mem = element->dl_member;
+ int npr = element->dl_prep + 1;
+
+ if( npr > Prep )
+ mem->dl_delete++;
+ else
+ mem->dl_prep = npr;
+ }
+ }
+
+ for( element = pdfa; element != NIL(DFALINK); element = nelement ) {
+ nelement = element->dl_next;
+
+ if( element->dl_delete ) {
+ /* A member of the subset has a PREP count equal to PREP, so
+ * it should not be considered further in the inference, hence
+ * we remove it from the doubly linked set list */
+ if( element == pdfa )
+ pdfa = element->dl_next;
+ else
+ element->dl_prev->dl_next = element->dl_next;
+
+ if( element->dl_next != NIL(DFALINK) )
+ element->dl_next->dl_prev = element->dl_prev;
+
+ DB_PRINT("inf", ("deleting dfa [%s]", element->dl_meta->CE_NAME));
+ FREE( element->dl_per );
+ FREE( element );
+ }
+ }
+
+ DB_RETURN( pdfa );
+}
+
+
+
+static void
+free_dfas( chain )/*
+=====================
+ Free the list of DFA's constructed by Match_dfa, and linked together by
+ LINK cells. FREE the % value as well, as long as it isn't NIL. */
+DFALINKPTR chain;
+{
+ register DFALINKPTR tl;
+
+ DB_ENTER( "free_dfas" );
+
+ for( tl=chain; tl != NIL(DFALINK); chain = tl ) {
+ tl = tl->dl_next;
+
+ DB_PRINT( "inf", ("Freeing DFA [%s], %% = [%s]", chain->dl_meta->CE_NAME,
+ chain->dl_per) );
+
+ if( chain->dl_per != NIL(char) ) FREE( chain->dl_per );
+ FREE( chain );
+ }
+
+ DB_VOID_RETURN;
+}
+
+
+static int
+count_dots( name )/*
+=====================*/
+char *name;
+{
+ register char *p;
+ register int i = 0;
+
+ for( p = name; *p; p++ ) if(*p == '.') i++;
+
+ return( i );
+}
+
+
+static ICELLPTR _icells = NIL(ICELL);
+#ifdef DBUG
+static int _icell_cost = 0;
+#endif
+
+static ICELLPTR
+add_iset( iset, parent, meta, dfa, setdirroot, dmax, noinf, name, dir, exists)
+ICELLPTR iset;
+ICELLPTR parent;
+CELLPTR meta;
+DFALINKPTR dfa;
+CELLPTR setdirroot;
+int dmax;
+int noinf;
+char *name;
+char *dir;
+int exists;
+{
+ ICELLPTR icell;
+
+ DB_ENTER("add_iset");
+ TALLOC(icell, 1, ICELL);
+
+ DB_EXECUTE("inf", _icell_cost+=(sizeof(ICELL)+strlen(dir?dir:"")+strlen(name?name:"")+2););
+
+ icell->ic_meta = meta;
+ icell->ic_dfa = dfa;
+ icell->ic_setdirroot = setdirroot;
+
+ if( parent ) icell->ic_dfastack.df_next = &parent->ic_dfastack;
+
+ icell->ic_dmax = dmax;
+ icell->ic_dir = DmStrDup(dir);
+ icell->ic_name = DmStrDup(name);
+ icell->ic_parent = parent;
+ icell->ic_next = iset;
+ icell->ic_flag = noinf;
+ icell->ic_exists = exists;
+
+ icell->ic_link = _icells;
+ _icells = icell;
+
+ DB_RETURN(icell);
+}
+
+
+static void
+free_icells()
+{
+ register ICELLPTR ic;
+
+ DB_ENTER("free_icells");
+
+ for( ; _icells; _icells = ic ) {
+ ic = _icells->ic_link;
+
+ free_dfas(_icells->ic_dfastack.df_set);
+ if( _icells->ic_dir ) FREE(_icells->ic_dir);
+ if( _icells->ic_name) FREE(_icells->ic_name);
+ FREE(_icells);
+ }
+
+ DB_PRINT("inf",("Used %d memory for icells",_icell_cost));
+ DB_EXECUTE("inf", _icell_cost=0; );
+
+ DB_VOID_RETURN;
+}
+
+
+static ICELLPTR
+union_iset( iset, uset )
+ICELLPTR iset;
+ICELLPTR uset;
+{
+ register ICELLPTR ic;
+
+ if( iset == NIL(ICELL) ) return(uset);
+
+ for( ic=iset; ic->ic_next != NIL(ICELL); ic=ic->ic_next );
+ ic->ic_next = uset;
+
+ return(iset);
+}
+
+
+static char *
+dump_inf_chain( ip, flag, print )/*
+====================================*/
+ICELLPTR ip;
+int flag;
+int print;
+{
+ char *tmp;
+
+ if( ip == NIL(ICELL) ) return(NIL(char));
+
+ tmp = dump_inf_chain(ip->ic_parent, FALSE, FALSE);
+
+ if( ip->ic_meta ) {
+ tmp = DmStrJoin(tmp, "(", -1, TRUE);
+ tmp = DmStrJoin(tmp, ip->ic_meta->CE_NAME, -1, TRUE);
+
+ if( ip->ic_dir && !*ip->ic_dir ) {
+ tmp = DmStrJoin(tmp, "[", -1, TRUE);
+ if( strncmp(Makedir,ip->ic_dir, strlen(Makedir)) )
+ tmp = DmStrJoin(tmp, ip->ic_dir, -1, TRUE);
+ else
+ tmp = DmStrJoin(tmp, ip->ic_dir+strlen(Makedir)+1, -1, TRUE);
+ tmp = DmStrJoin(tmp, "]", -1, TRUE);
+ }
+ tmp = DmStrJoin(tmp, (ip->ic_name)?") -->":")", -1, TRUE);
+ }
+
+ if( ip->ic_name ) tmp = DmStrApp( tmp, ip->ic_name );
+
+ if( flag && ip->ic_meta->ce_prq) {
+ tmp = DmStrJoin(tmp, "(", -1, TRUE);
+ tmp = DmStrJoin(tmp, ip->ic_meta->ce_prq->cl_prq->CE_NAME, -1, TRUE);
+ tmp = DmStrJoin(tmp, ")", -1, TRUE);
+ }
+
+ if( print ) {
+ fprintf( stderr, "%s: %2d. %s\n", Pname, print, tmp );
+ FREE(tmp);
+ tmp = NIL(char);
+ }
+
+ return(tmp);
+}
+
+
+#ifdef DBUG
+_dump_dfa_stack(dfas, dfa_stack)
+DFALINKPTR dfas;
+DFASETPTR dfa_stack;
+{
+ register DFALINKPTR pdfa;
+ char *tmp = NIL(char);
+ DFASETPTR ds;
+
+ for( pdfa = dfas; pdfa != NIL(DFALINK); pdfa = pdfa->dl_next )
+ tmp = DmStrApp( tmp, pdfa->dl_meta->CE_NAME );
+
+ tmp = DmStrApp( tmp, ":: {" );
+ for( ds = dfa_stack; ds != NIL(DFASET); ds = ds->df_next ) {
+ tmp = DmStrApp( tmp, "[" );
+ for( pdfa = ds->df_set; pdfa != NIL(DFALINK); pdfa = pdfa->dl_next )
+ tmp = DmStrApp( tmp, pdfa->dl_meta->CE_NAME );
+ tmp = DmStrApp( tmp, "]" );
+ }
+ tmp = DmStrApp( tmp, "}" );
+
+ printf( "DFA set and stack contents:\n%s\n", tmp );
+ FREE(tmp);
+}
+
+
+_dump_iset( name, iset )
+char *name;
+ICELLPTR iset;
+{
+ int cell = 0;
+
+ printf( "**** ISET for %s\n", name );
+ for( ; iset != NIL(ICELL); iset = iset->ic_next ){
+ printf( "cell %d\n", cell++ );
+ if( iset->ic_meta )
+ printf( "edge: %s --> %s\n", iset->ic_meta->CE_NAME,
+ iset->ic_meta->ce_prq ?
+ iset->ic_meta->ce_prq->cl_prq->CE_NAME :
+ "(nil)" );
+ else
+ printf( "edge: (nil)\n" );
+
+ if( iset->ic_dfa )
+ printf( "dfa: %s\n", iset->ic_dfa->dl_meta->CE_NAME );
+ else
+ printf( "dfa: (nil)\n" );
+
+ printf( "sdr: %04x\n", iset->ic_setdirroot );
+ _dump_dfa_stack(iset->ic_dfastack.df_set, &iset->ic_dfastack);
+
+ printf( "dmax: %d\n", iset->ic_dmax );
+ printf( "name: %s\n", iset->ic_name );
+ printf( "dir: %s\n", iset->ic_dir?iset->ic_dir:"(nil)" );
+
+ printf( "parent: " );
+ if( iset->ic_parent )
+ if( iset->ic_parent->ic_meta )
+ printf( "%s --> %s\n",
+ iset->ic_parent->ic_meta->CE_NAME,
+ iset->ic_parent->ic_meta->ce_prq ?
+ iset->ic_parent->ic_meta->ce_prq->cl_prq->CE_NAME :
+ "(nil)" );
+ else
+ printf( "(nil)\n" );
+ else
+ printf( "(nil)\n" );
+ }
+ printf( "==================================\n" );
+}
+#endif
diff --git a/dmake/itypes.h b/dmake/itypes.h
new file mode 100644
index 000000000000..a218c9e0704b
--- /dev/null
+++ b/dmake/itypes.h
@@ -0,0 +1,47 @@
+/* RCS $Id: itypes.h,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Type declarations for common types
+--
+-- DESCRIPTION
+-- portable type declarations.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+
+#ifndef ITYPES_h
+#define ITYPES_h
+
+#if defined(M_I86) || defined(MC68000)
+typedef char int8; /* typedefs for right size ints */
+typedef int int16;
+typedef long int32;
+typedef unsigned char uint8;
+typedef unsigned int uint16;
+typedef unsigned long uint32;
+#else
+typedef char int8; /* typedefs for right size ints */
+typedef short int16;
+typedef long int32;
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned long uint32;
+#endif
+
+#endif
+
diff --git a/dmake/mac/arlib.c b/dmake/mac/arlib.c
new file mode 100644
index 000000000000..2f06bca68f9e
--- /dev/null
+++ b/dmake/mac/arlib.c
@@ -0,0 +1,56 @@
+/* RCS $Id: arlib.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $
+--
+-- SYNOPSIS
+-- Library access code.
+--
+-- DESCRIPTION
+-- This implementation uses the library timestamp inplace of the
+-- library member timestamp.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+PUBLIC time_t
+seek_arch(name, lib)
+char* name;
+char* lib;
+{
+ static int warned = FALSE;
+
+ if (!warned && !(Glob_attr&A_SILENT))
+ warned = TRUE,
+ Warning("Can't extract library member timestamp;\n\
+ using library timestamp instead.");
+ return (Do_stat(lib, NULL, NULL, TRUE));
+}
+
+PUBLIC int
+touch_arch(name, lib)
+char* name;
+char* lib;
+{
+ static int warned = FALSE;
+
+ if (!warned && !(Glob_attr&A_SILENT))
+ warned = TRUE,
+ Warning("Can't update library member timestamp;\n\
+ touching library instead.");
+ return (Do_touch(lib, NULL, NULL));
+}
+
diff --git a/dmake/mac/bogus.c b/dmake/mac/bogus.c
new file mode 100644
index 000000000000..efd7d39b9470
--- /dev/null
+++ b/dmake/mac/bogus.c
@@ -0,0 +1,99 @@
+/* RCS $Id: bogus.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Write the shell of subroutines we can't or don't
+-- need to implement
+--
+-- DESCRIPTION
+-- dmake uses a couple of functions which I am either unable to figure out
+-- how to implement or which are not needed. The shells of these routines
+-- are in this file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+
+
+/*
+ * tzset() is a Microsoft "extension" to ANSI C. It sets global
+ * variables telling if we are in dayling savings time, the time
+ * zone, and difference between the current time and GMT.
+ * None of these globals are used by dmake, so this routine is
+ * not needed
+ */
+PUBLIC void
+tzset ()
+{
+}
+
+
+
+/*
+ * Add an environmental variable that child processes can use.
+ * Since MPW currently doesn't allow child processes, this isn't
+ * needed.
+ */
+PUBLIC int
+putenv (char *pEnvString)
+{
+ return (0);
+}
+
+
+
+/*
+ * Execute a child process. This may be able to be done with
+ * the MPW system() call someday, but cannot be done currently.
+ */
+PUBLIC int
+runargv (CELLPTR target, int ignore, int,
+ int last, int shell, char *pCmd)
+{
+ static int warned = FALSE;
+
+ if (!warned && !(Glob_attr & A_SILENT)) {
+ warned = TRUE;
+ Fatal ("Can't execute any targets: use '-n' option.");
+ } /* if */
+
+ return (0);
+} /* int runargv () */
+
+
+
+/*
+ * Wait for the child process to complete. Only needed to be implemented
+ * if we could executing multiple processes at once.
+ */
+PUBLIC int
+Wait_for_child(int abort_flg, int pid)
+{
+ return (1);
+}
+
+
+
+/*
+ * Do any cleanup for any processes when we quit.
+ */
+PUBLIC void
+Clean_up_processes()
+{
+}
diff --git a/dmake/mac/config.mk b/dmake/mac/config.mk
new file mode 100644
index 000000000000..2a6806cff159
--- /dev/null
+++ b/dmake/mac/config.mk
@@ -0,0 +1,44 @@
+# This is an OS Mac specific configuration file
+# It assumes that OBJDIR, TARGET and DEBUG are previously defined.
+# It defines CFLAGS, LDARGS, CPPFLAGS, STARTUPFILE, LDOBJS
+# It augments SRC, OBJDIR, TARGET, CFLAGS, LDLIBS
+#
+
+STARTUPFILE = :$(OS):startup.mk
+
+CPPFLAGS = $(CFLAGS)
+LDOBJS = $(CSTARTUP) :$(OBJDIR):{$(<:f)}
+LDARGS = $(LDFLAGS) -o $@ $(LDOBJS) $(LDLIBS)
+
+# Debug flags
+DB_CFLAGS = -sym on
+DB_LDFLAGS = -sym on
+DB_LDLIBS =
+
+# NO Debug flags
+NDB_CFLAGS = -sym off
+NDB_LDFLAGS = -sym off
+NDB_LDLIBS =
+
+# Local configuration modifications for CFLAGS.
+CFLAGS += -I :$(OS) -d _MPW -s $(<:b)
+LDFLAGS += -w -c 'MPS ' -t MPST
+
+# Since we writing out what files we want to execute, we can't use .SETDIR
+# to specify the files to compile in the Mac directory.
+# Instead, we copy the files to the (top-level) current directory and compile
+# them there.
+%.c : ":$(OS):%.c"
+ duplicate -y $< $@
+
+# Common Mac source files.
+OS_SRC = arlib.c bogus.c dirbrk.c directry.c environ.c main.c rmprq.c \
+ ruletab.c tempnam.c tomacfil.c
+.IF $(SHELL) != mwp
+ .SETDIR=$(OS) : $(OS_SRC)
+.ENDIF
+SRC += $(OS_SRC)
+
+# Set source dirs so that we can find files named in this
+# config file.
+.SOURCE.h : $(OS)
diff --git a/dmake/mac/dirbrk.c b/dmake/mac/dirbrk.c
new file mode 100644
index 000000000000..c584ad22cad1
--- /dev/null
+++ b/dmake/mac/dirbrk.c
@@ -0,0 +1,42 @@
+/* RCS $Id: dirbrk.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Define the directory separator string.
+--
+-- DESCRIPTION
+-- Define this string for any character that may appear in a path name
+-- and can be used as a directory separator.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+/* mac only uses ':' */
+char* DirBrkStr = ":";
+
+/*
+** Return TRUE if the name is the full specification of a path name to a file
+** starting at the root of the file system, otherwise return FALSE
+*/
+PUBLIC int
+If_root_path(name)
+char *name;
+{
+ return( (strchr(name, ':') != NIL(char)) &&
+ (name[0] != ':') );
+}
diff --git a/dmake/mac/directry.c b/dmake/mac/directry.c
new file mode 100644
index 000000000000..b1d452d073ba
--- /dev/null
+++ b/dmake/mac/directry.c
@@ -0,0 +1,264 @@
+/* RCS $Id: directry.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Fake directory and file functions for the Mac
+--
+-- DESCRIPTION
+-- This file contains implementations for some ANSI standard routines dmake
+-- uses which are not otherwise available for the mac.
+--
+-- Assume we are using at least 128K ROMS.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <Errors.h>
+#include <Files.h>
+#include <OSUtils.h>
+#include <StdLib.h>
+#include <Strings.h>
+/*
+ * We now include LowMem.h instead of SysEqu.h as LowMem.h is what Apple recommends
+ * we use.
+ */
+#include <LowMem.h>
+#include "extern.h"
+
+
+
+/*
+ * Implementation of stat function for dmake on the mac.
+ *
+ * Many fields aren't filled in, and the times are seconds from 1/1//1904,
+ * but it should be enough for dmake (I think we only need st_mtime and
+ * st_mode's S_IFDIR set correctly).
+ */
+PUBLIC int
+stat(pPath, pStat)
+char *pPath;
+struct stat *pStat;
+{
+ CInfoPBRec infoPB;
+ OSErr err;
+ int retVal;
+
+ infoPB.hFileInfo.ioCompletion = NULL;
+ infoPB.hFileInfo.ioNamePtr = c2pstr (pPath);
+ infoPB.hFileInfo.ioVRefNum = 0;
+ infoPB.hFileInfo.ioFDirIndex = 0;
+ infoPB.hFileInfo.ioDirID = 0;
+ err = PBGetCatInfo(&infoPB, FALSE);
+ p2cstr ((StringPtr) pPath);
+
+ if (err == noErr) {
+ pStat->st_mtime = (time_t) infoPB.hFileInfo.ioFlMdDat;
+ pStat->st_ctime = (time_t) infoPB.hFileInfo.ioFlCrDat;
+ pStat->st_mode = S_IREAD | S_IEXEC;
+
+ /* If it is a directory ... */
+ if (infoPB.hFileInfo.ioFlAttrib & 0x10) {
+ pStat->st_size = infoPB.dirInfo.ioDrNmFls;
+ pStat->st_mode |= S_IFDIR;
+ } else {
+ pStat->st_size = infoPB.hFileInfo.ioFlLgLen;
+ pStat->st_mode |= S_IFREG;
+ } /* if ... else */
+
+ /* If it is writeable */
+ if ((infoPB.hFileInfo.ioFlAttrib & 0x1) == 0) {
+ pStat->st_mode |= S_IWRITE;
+ } /* if */
+
+ retVal = 0;
+
+ } else {
+ retVal = -1;
+ } /* if ... else */
+
+ return (retVal);
+} /* PUBLIC int stat () */
+
+
+
+/*
+ * Return the current working directory, or NULL if there is an error.
+ */
+PUBLIC char *
+getcwd(char *pPath, size_t pathSize)
+{
+ DirInfo dirInfo;
+ OSErr err;
+ Str255 dirName;
+ char *pBeginName;
+ char *pC;
+ size_t len;
+ size_t spaceForColon;
+
+ /* Set up the info for the PBGetCatInfo() calls */
+ dirInfo.ioCompletion = NULL;
+ dirInfo.ioNamePtr = dirName;
+ dirInfo.ioVRefNum = 0;
+ dirInfo.ioFDirIndex = -1;
+ dirInfo.ioDrDirID = 0;
+ pBeginName = pPath + pathSize - 1;
+ spaceForColon = 0; /* Make sure we don't have an end colon on the name */
+
+ /*
+ * Keep going up the directory path until the end is reached or an error
+ * occurs. Ideally, we would check for errors at every level and stop
+ * when we received an fnfErr (File Not Found), but it appears that there
+ * are some problems with network volumes. (During testing, I received
+ * a paramErr (No Default Volume) beyond the top level.) Thus, to keep it
+ * simple, I assume any error past the first directory indicates we have
+ * seen all directories.
+ */
+ while (TRUE) {
+ err = PBGetCatInfo ((CInfoPBPtr) &dirInfo, FALSE);
+ len = ((size_t)(unsigned char) dirName[0]);
+ if ((err == noErr) && (len < pBeginName - pPath)) {
+ p2cstr (dirName);
+ pBeginName -= len + spaceForColon;
+ strcpy (pBeginName, (char *)dirName);
+ /* Note that strcpy() adds the '\0' at the end of
+ the first directory for us */
+ if (spaceForColon == 1) {
+ pBeginName[len] = ':';
+ } else {
+ /* The end of the string shouldn't have a ':' */
+ spaceForColon = 1;
+ } /* if */
+
+ /* Set up for the next call to PBGetCatInfo() with
+ the parent's directory ID */
+ dirInfo.ioDrDirID = dirInfo.ioDrParID;
+
+ } else if (spaceForColon == 1) {
+ /* We got past the top-level directory */
+ break;
+
+ } else {
+ /* We either have an error when looking at the first directory
+ or have run out of room. */
+ return (NULL);
+ } /* if ... elses */
+ } /* while */
+
+ /* Now copy the directory string to the beginning of the path string.
+ (It's possible the directory already starts at the beginning of the
+ string, but this is unlikely and doesn't hurt anything if it does,
+ so we don't bother to check for it.) */
+ pC = pPath;
+ while ((*(pC++) = *(pBeginName++)) != '\0')
+ ;
+
+ return (pPath);
+} /* PUBLIC char *getcwd () */
+
+
+
+/*
+ * Change the directory to a new default directory.
+ *
+ * Return 0 if successful, or -1 if there is an error.
+ */
+PUBLIC int
+chdir(char *pPath)
+{
+ WDPBRec WDPB;
+ VolumeParam vParam;
+ OSErr err;
+ int result;
+ char *pC;
+ char c;
+
+ /* Set up the directory */
+ c2pstr (pPath);
+ WDPB.ioCompletion = NULL;
+ WDPB.ioNamePtr = (unsigned char *)pPath;
+ WDPB.ioVRefNum = 0;
+ WDPB.ioWDProcID = 0;
+ WDPB.ioWDDirID = 0;
+ err = PBOpenWD (&WDPB, FALSE);
+ /* Restore path to a C-type string in case the caller wants
+ to use it after this call. */
+ p2cstr ((unsigned char *)pPath);
+ if (err != noErr) {
+ return (-1);
+ } /* if */
+
+ /* Set up the volume if necessary */
+ if (*pPath != ':') {
+ for (pC = pPath + 1; (*pC != ':') && (*pC != '\0'); ++pC)
+ ;
+ c = *pC;
+ *pC = '\0';
+ vParam.ioCompletion = NULL;
+ vParam.ioNamePtr = c2pstr (pPath);
+ vParam.ioVRefNum = WDPB.ioVRefNum;
+ err = PBSetVol ((ParmBlkPtr) &vParam, FALSE);
+ p2cstr ((unsigned char *)pPath);
+ *pC = c;
+ result = ((err == noErr) ? 0 : -1);
+
+ } else {
+ result = 0;
+ } /* if ... else */
+
+ return (result);
+} /* PUBLIC int chdir () */
+
+
+
+/*
+ * Change the modification time for the file to the current time.
+ *
+ * The normal version of utime can set the modification time to any
+ * time, this function aborts the function if this is tried.
+ *
+ * We return 0 if the modification time was updated and -1 if there
+ * was an error.
+ */
+PUBLIC int
+utime(char *pPath, time_t *pTimes)
+{
+ CInfoPBRec infoPB;
+ OSErr err;
+
+ if (pTimes != NULL) {
+ Fatal ("SUBROUTINE SHORTCOMING: utime cannot take a utimbuf struct");
+ } /* if */
+
+ /* Get the old info */
+ infoPB.hFileInfo.ioCompletion = NULL;
+ infoPB.hFileInfo.ioNamePtr = c2pstr (pPath);
+ infoPB.hFileInfo.ioVRefNum = 0;
+ infoPB.hFileInfo.ioFDirIndex = 0;
+ infoPB.hFileInfo.ioDirID = 0;
+ err = PBGetCatInfo (&infoPB, FALSE);
+ if (err != noErr) {
+ p2cstr ((StringPtr) pPath);
+ return (-1);
+ } /* if */
+
+ /* Change the modification time and set the new info */
+ GetDateTime (&(infoPB.hFileInfo.ioFlMdDat));
+ infoPB.hFileInfo.ioDirID = 0;
+ err = PBSetCatInfo (&infoPB, FALSE);
+ p2cstr ((StringPtr) pPath);
+ return ((err == noErr) ? 0 : -1);
+} /* PUBLIC int utime () */
diff --git a/dmake/mac/dompwmak b/dmake/mac/dompwmak
new file mode 100644
index 000000000000..c71ed12ca16d
--- /dev/null
+++ b/dmake/mac/dompwmak
@@ -0,0 +1,67 @@
+newfolder objects
+c -I. -I :mac -d _MPW -s infer -sym off -o :objects:infer.c.o infer.c
+c -I. -I :mac -d _MPW -s make -sym off -o :objects:make.c.o make.c
+c -I. -I :mac -d _MPW -s stat -sym off -o :objects:stat.c.o stat.c
+c -I. -I :mac -d _MPW -s expand -sym off -o :objects:expand.c.o expand.c
+c -I. -I :mac -d _MPW -s dmstring -sym off -o :objects:dmstring.c.o dmstring.c
+c -I. -I :mac -d _MPW -s hash -sym off -o :objects:hash.c.o hash.c
+c -I. -I :mac -d _MPW -s dag -sym off -o :objects:dag.c.o dag.c
+c -I. -I :mac -d _MPW -s dmake -sym off -o :objects:dmake.c.o dmake.c
+c -I. -I :mac -d _MPW -s path -sym off -o :objects:path.c.o path.c
+c -I. -I :mac -d _MPW -s imacs -sym off -o :objects:imacs.c.o imacs.c
+c -I. -I :mac -d _MPW -s sysintf -sym off -o :objects:sysintf.c.o sysintf.c
+c -I. -I :mac -d _MPW -s parse -sym off -o :objects:parse.c.o parse.c
+c -I. -I :mac -d _MPW -s getinp -sym off -o :objects:getinp.c.o getinp.c
+c -I. -I :mac -d _MPW -s quit -sym off -o :objects:quit.c.o quit.c
+c -I. -I :mac -d _MPW -s state -sym off -o :objects:state.c.o state.c
+c -I. -I :mac -d _MPW -s basename -sym off -o :objects:basename.c.o basename.c
+c -I. -I :mac -d _MPW -s dmdump -sym off -o :objects:dmdump.c.o dmdump.c
+c -I. -I :mac -d _MPW -s macparse -sym off -o :objects:macparse.c.o macparse.c
+c -I. -I :mac -d _MPW -s rulparse -sym off -o :objects:rulparse.c.o rulparse.c
+c -I. -I :mac -d _MPW -s percent -sym off -o :objects:percent.c.o percent.c
+c -I. -I :mac -d _MPW -s function -sym off -o :objects:function.c.o function.c
+duplicate -y :mac:arlib.c arlib.c
+c -I. -I :mac -d _MPW -s arlib -sym off -o :objects:arlib.c.o arlib.c
+delete arlib.c
+duplicate -y :mac:bogus.c bogus.c
+c -I. -I :mac -d _MPW -s bogus -sym off -o :objects:bogus.c.o bogus.c
+delete bogus.c
+duplicate -y :mac:dirbrk.c dirbrk.c
+c -I. -I :mac -d _MPW -s dirbrk -sym off -o :objects:dirbrk.c.o dirbrk.c
+delete dirbrk.c
+duplicate -y :mac:directry.c directry.c
+c -I. -I :mac -d _MPW -s directry -sym off -o :objects:directry.c.o directry.c
+delete directry.c
+duplicate -y :mac:environ.c environ.c
+c -I. -I :mac -d _MPW -s environ -sym off -o :objects:environ.c.o environ.c
+delete environ.c
+duplicate -y :mac:main.c main.c
+c -I. -I :mac -d _MPW -s main -sym off -o :objects:main.c.o main.c
+delete main.c
+duplicate -y :mac:rmprq.c rmprq.c
+c -I. -I :mac -d _MPW -s rmprq -sym off -o :objects:rmprq.c.o rmprq.c
+delete rmprq.c
+duplicate -y :mac:ruletab.c ruletab.c
+c -I. -I :mac -d _MPW -s ruletab -sym off -o :objects:ruletab.c.o ruletab.c
+delete ruletab.c
+duplicate -y :mac:tempnam.c tempnam.c
+c -I. -I :mac -d _MPW -s tempnam -sym off -o :objects:tempnam.c.o tempnam.c
+delete tempnam.c
+duplicate -y :mac:tomacfil.c tomacfil.c
+c -I. -I :mac -d _MPW -s tomacfil -sym off -o :objects:tomacfil.c.o tomacfil.c
+delete tomacfil.c
+Set p1 ":objects:infer.c.o :objects:make.c.o :objects:stat.c.o :objects:expand.c.o"
+Set p2 ":objects:dmstring.c.o :objects:hash.c.o :objects:dag.c.o :objects:dmake.c.o"
+Set p3 ":objects:path.c.o :objects:imacs.c.o :objects:sysintf.c.o :objects:parse.c.o"
+Set p4 ":objects:getinp.c.o :objects:quit.c.o :objects:state.c.o :objects:basename.c.o"
+Set p5 ":objects:dmdump.c.o :objects:macparse.c.o :objects:rulparse.c.o"
+Set p6 ":objects:percent.c.o :objects:function.c.o :objects:arlib.c.o :objects:bogus.c.o"
+Set p7 ":objects:dirbrk.c.o :objects:directry.c.o :objects:environ.c.o :objects:main.c.o"
+Set p8 ":objects:rmprq.c.o :objects:ruletab.c.o :objects:tempnam.c.o"
+Set p9 ":objects:tomacfil.c.o Micah:MPW:Libraries:CLibraries:CSANELib.o"
+Set p10 "Micah:MPW:Libraries:CLibraries:Math.o"
+Set p11 "Micah:MPW:Libraries:CLibraries:StdCLib.o"
+Set p12 "Micah:MPW:Libraries:Libraries:Runtime.o"
+Set p13 "Micah:MPW:Libraries:Libraries:Interface.o Micah:MPW:Libraries:Libraries:Toollibs.o"
+link -w -c 'MPS ' -t MPST -sym off -o dmake {p1} {p2} {p3} {p4} {p5} {p6} {p7} {p8} {p9} {p10} {p11} {p12} {p13}
+duplicate :mac:startup.mk startup.mk
diff --git a/dmake/mac/environ.c b/dmake/mac/environ.c
new file mode 100644
index 000000000000..b9bd6d014da9
--- /dev/null
+++ b/dmake/mac/environ.c
@@ -0,0 +1,231 @@
+/* RCS $Id: environ.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Set up and free for environ
+--
+-- DESCRIPTION
+-- This file contains routines that will fill in and dispose of the
+-- list of environmental variables in the environ global variable.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+/* The char used to replace the equal signs in environmental variable names. */
+const char kEqualReplace = '_';
+
+/* Maximum size of a "name=value" environmental string, including the ending '\0'.
+ Larger environmental variables will be clipped before dmake sees them.
+ (Caution: When I tested the program, the Mac or dmake trashed memory
+ when environmental variables of >4K were read in. I looked around a bit
+ and couldn't find out the exact cause, so I simply made this variable.
+ The memory trashing may be related to the value for MAXLINELENGTH.) */
+const int kMaxEnvLen = 1024;
+
+
+/* The list of environmental variables in the form "name=value".
+ (Once make_env() has been called.) */
+char **environ = NULL;
+
+/* Characters replaced during make_env() */
+struct ReplaceChar {
+ char *fpPos;
+ char fC;
+ struct ReplaceChar *fpNext;
+}; /* struct ReplaceChar */
+struct ReplaceChar *gpReplaceList = NULL;
+
+
+void AddReplace (char *pReplacePos);
+
+
+
+/*
+ * Set up the environmental variables in a format used by
+ * the environ global variable.
+ *
+ * environ has already been set to main's envp argument when
+ * this suboroutine is called. We assume that envp is a copy
+ * MPW makes for this process' use alone, so we can modify it
+ * below.
+ */
+PUBLIC void
+make_env()
+{
+ char **ppCurEnv;
+ char *pCurPos;
+#if 0
+ char **ppMacEnv;
+ char *pMacPos;
+
+ if (!gMECalled) {
+ gMECalled = TRUE;
+
+environ = MALLOC (1, char *);
+*environ = NULL;
+#endif
+#if 0
+{
+ int numenv;
+ int len;
+ int firstnil;
+
+ numenv = 1;
+ ppMacEnv = environ;
+ while (*(ppMacEnv++) != NULL) {
+ ++numenv;
+ } /* while */
+
+ ppMacEnv = environ;
+ if ((environ = MALLOC (numenv, char *)) == NULL) {
+ No_ram ();
+ } /* if */
+
+numenv = 80;
+ for (ppCurEnv = environ; (numenv-- > 0) && (*ppMacEnv != NULL); ++ppCurEnv, ++ppMacEnv) {
+ pMacPos = *ppMacEnv;
+ len = strlen (pMacPos) + 1;
+ len += strlen (pMacPos + len) + 1;
+#define MAXLEN 4098
+if (len > MAXLEN) len = MAXLEN;
+ if ((*ppCurEnv = MALLOC (len, char)) == NULL) {
+ No_ram ();
+ } /* if */
+
+ firstnil = TRUE;
+ for (pCurPos = *ppCurEnv; ((pCurPos - *ppCurEnv) < MAXLEN - 1); ++pCurPos, ++pMacPos) {
+ if (*pMacPos == '=') {
+ *pCurPos = gEqualReplace;
+
+ } else if (*pMacPos == '\0') {
+ if (firstnil) {
+ *pCurPos = '=';
+ firstnil = FALSE;
+ } else {
+ *pCurPos = *pMacPos;
+ break;
+ } /* if ... else */
+
+ } else {
+ *pCurPos = *pMacPos;
+ } /* if ... elses */
+ } /* for */
+firstnil = FALSE;
+ } /* for */
+ *ppCurEnv = NULL;
+}
+#endif
+{
+ int firstnil;
+
+ /* Get rid of any equal signs in any environmental name, and put
+ equal signs between the names and their values */
+ for (ppCurEnv = environ; *ppCurEnv != NULL; ++ppCurEnv) {
+
+ firstnil = TRUE;
+ for (pCurPos = *ppCurEnv;
+ ((pCurPos - *ppCurEnv < kMaxEnvLen - 1) &&
+ ((*pCurPos != '\0') || firstnil));
+ ++pCurPos) {
+ if (*pCurPos == '=') {
+ AddReplace (pCurPos);
+ *pCurPos = kEqualReplace;
+
+ } else if (*pCurPos == '\0') {
+ AddReplace (pCurPos);
+ *pCurPos = '=';
+ firstnil = FALSE;
+ } /* if ... else if */
+ } /* for */
+
+ /* If the environtmental variable was too large ... */
+ if (*pCurPos != '\0') {
+ AddReplace (pCurPos);
+ *pCurPos = '\0';
+ if (firstnil) {
+ AddReplace (--pCurPos);
+ *pCurPos = '=';
+ } /* if */
+ } /* if */
+ } /* for */
+}
+#if 0
+ } /* if */
+#endif
+} /* PUBLIC void make_env () */
+
+
+/*
+ * The character at pReplacePos is about to be replaced. Remember the
+ * old value so we can restore it when we're done.
+ */
+void AddReplace (char *pReplacePos) {
+ struct ReplaceChar *pReplaceChar;
+
+ if ((pReplaceChar = MALLOC (1, struct ReplaceChar)) == NULL) {
+ No_ram ();
+ } /* if */
+ pReplaceChar->fpPos = pReplacePos;
+ pReplaceChar->fC = *pReplacePos;
+ pReplaceChar->fpNext = gpReplaceList;
+ gpReplaceList = pReplaceChar;
+} /* void AddReplace () */
+
+
+/*
+ * Restore the old environmental variables to the way they looked before
+ * the make_env() call, on the unlikely chance that something else will look
+ * at our copy of the environmental variables during the program execution.
+ *
+ */
+PUBLIC void
+free_env()
+{
+ struct ReplaceChar *pReplaceChar;
+
+ while (gpReplaceList != NULL) {
+ pReplaceChar = gpReplaceList;
+ gpReplaceList = pReplaceChar->fpNext;
+
+ *(pReplaceChar->fpPos) = pReplaceChar->fC;
+
+ FREE (pReplaceChar);
+ } /* while */
+
+#if 0
+ char **ppCurEnv;
+ char *pCurPos;
+
+ if (!gFECalled) {
+ gFECalled = TRUE;
+
+//FREE (environ);
+environ = NULL;
+#endif
+#if 0
+ /* Restore the environment list to what it was before we
+ read it in. */
+ for (ppCurEnv = environ; *ppCurEnv != NULL; ++ppCurEnv) {
+ for (pCurPos = *ppCurEnv; *pCurPos != '='; ++pCurPos)
+ ;
+ *pCurPos = '\0';
+ } /* for */
+ } /* if */
+#endif
+} /* PUBLIC void free_env () */
diff --git a/dmake/mac/eold.c b/dmake/mac/eold.c
new file mode 100644
index 000000000000..5c389c5851db
--- /dev/null
+++ b/dmake/mac/eold.c
@@ -0,0 +1,119 @@
+/* RCS $Id: eold.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Set up and free for environ
+--
+-- DESCRIPTION
+-- This file contains routines that will fill in and dispose of the
+-- list of environmental variables in the environ global variable.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+
+/*
+ * Keep track of any environmental variables that have '='s in their
+ * name.
+ */
+struct EqualPos {
+ char *fpPos;
+ struct equalsign *fpNext;
+} /* struct EqualPos */
+
+struct EqualPos *gpEqualList;
+
+/*
+ * The character used to replae the equal signs.
+ */
+const char gEqualReplace = '_';
+
+
+
+/*
+ * Set up the environmental variables in a format used by
+ * the environ global variable.
+ *
+ * environ has already been set to main's envp argument when
+ * this suboroutine is called.
+ */
+void main_env () {
+ char **ppCurEnv;
+ char *pCurPos;
+ struct equalpos *pNewEqual;
+
+ gpEqualList = NULL;
+
+ for (ppCurEnv = environ; *ppCurEnv != NULL; ++ppCurEnv) {
+ for (pCurPos = *ppCurEnv; *pCurPos != '\0'; ++pCurPos) {
+ if (*pCurPos == '=') {
+ if ((pNewEqual =
+ (struct EqualPos *) malloc (sizeof (struct EqualPos))) ==
+ NULL) {
+ fputs ("Out of Memory", stderr);
+ exit (EXIT_FAILURE);
+ } /* if */
+ pNewEqual->fpPos = pCurPos;
+ pNewEqual->fpNext = gpEqualList;
+ gpEqualList = pNewEqual;
+
+ *pCurPos = gEqualReplace;
+ } /* if */
+ } /* for */
+
+ *pCurPos = '=';
+ } /* for */
+} /* void main_env () */
+
+
+
+/*
+ * Reset the environmental variables so they look like they did
+ * before the main_env() call.
+ *
+ * environ has already been set to main's envp argument when
+ * this suboroutine is called.
+ */
+void main_env () {
+ char **ppCurEnv;
+ char *pCurPos;
+ struct equalpos *pNewEqual;
+
+ gpEqualList = NULL;
+
+ for (ppCurEnv = environ; *ppCurEnv != NULL; ++ppCurEnv) {
+ for (pCurPos = *ppCurEnv; *pCurPos != '\0'; ++pCurPos) {
+ if (*pCurPos == '=') {
+ if ((pNewEqual =
+ (struct EqualPos *) malloc (sizeof (struct EqualPos))) ==
+ NULL) {
+ fputs ("Out of Memory", stderr);
+ exit (EXIT_FAILURE);
+ } /* if */
+ pNewEqual->fpPos = pCurPos;
+ pNewEqual->fpNext = gpEqualList;
+ gpEqualList = pNewEqual;
+
+ *pCurPos = gEqualReplace;
+ } /* if */
+ } /* for */
+
+ *pCurPos = '=';
+ } /* for */
+} /* void main_env () */
diff --git a/dmake/mac/main.c b/dmake/mac/main.c
new file mode 100644
index 000000000000..53cc7d7cd9fe
--- /dev/null
+++ b/dmake/mac/main.c
@@ -0,0 +1,43 @@
+/* RCS $Id: main.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- The real main function
+--
+-- DESCRIPTION
+-- In order to get the third argument to main(), which is a list of
+-- environmental variables, we have #defined main to dmakemain,
+-- and put the real main here.
+--
+-- The environmental variables are placed in the environ global variable
+-- and set up for processing by dmake in make_env().
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+
+
+/*
+ * Put envp in environ and call dmake's main().
+ */
+#undef main
+void main(int argc, char **argv, char **envp) {
+ environ = envp;
+ dmakemain (argc, argv);
+} /* void main () */
diff --git a/dmake/mac/make.sh b/dmake/mac/make.sh
new file mode 100644
index 000000000000..fc2b8db02b0f
--- /dev/null
+++ b/dmake/mac/make.sh
@@ -0,0 +1,107 @@
+#
+# $Id: make.sh,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+#
+# This MPW script builds the dmake executable using the Metroworks PPC compiler
+# and linker. The resulting dmake binary will only run on the PPC platform.
+#
+# To execute this script, you will need the following tools:
+# - MacOS 8 or later
+# - CodeWarrior for MacOS Release 5 or later
+#
+# To run this script, you need to open the MPW Shell that is bundled with CodeWarrior.
+# If you have another instance of MPW installed other than the one bundled with
+# CodeWarrior, you may encounter problems. Once you open the MPW Shell that is bundled
+# with CodeWarrior, you will need to set MPW's working directory to the "dmake"
+# directory (the directory above the directory that this script is in). Then, execute
+# this script from the MPW Worksheet by typing the following command:
+#
+# :mac:make.sh
+#
+set Exit 1
+if ( "{0}" != ':mac:make.sh' )
+ Echo "You cannot run this script from the current directory."
+ Echo "To run this script, you need to be in the "dmake" directory and then"
+ Echo "execute the following command: ":mac:make.sh""
+ Exit
+end
+if ( ! `Exists -d objects` )
+ NewFolder :objects
+end
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle infer.c
+Move -y infer.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle make.c
+Move -y make.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle stat.c
+Move -y stat.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle expand.c
+Move -y expand.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle dmstring.c
+Move -y dmstring.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle hash.c
+Move -y hash.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle dag.c
+Move -y dag.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle dmake.c
+Move -y dmake.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle path.c
+Move -y path.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle imacs.c
+Move -y imacs.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle sysintf.c
+Move -y sysintf.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle parse.c
+Move -y parse.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle getinp.c
+Move -y getinp.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle quit.c
+Move -y quit.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle state.c
+Move -y state.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle dmdump.c
+Move -y dmdump.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle macparse.c
+Move -y macparse.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle rulparse.c
+Move -y rulparse.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle percent.c
+Move -y percent.c.o :objects
+# Note that function.c needs to have __useAppleExts__ defined. Otherwise, it won't link.
+MWCPPC -o : -ansi off -I :mac -d _MPW -d __useAppleExts__ -sym off -proto ignoreoldstyle function.c
+Move -y function.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:arlib.c
+Move -y arlib.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:bogus.c
+Move -y bogus.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:dirbrk.c
+Move -y dirbrk.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:directry.c
+Move -y directry.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:environ.c
+Move -y environ.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:main.c
+Move -y main.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:rmprq.c
+Move -y rmprq.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:ruletab.c
+Move -y ruletab.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:tempnam.c
+Move -y tempnam.c.o :objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:tomacfil.c
+Move -y tomacfil.c.o :objects
+MWLinkPPC -w -c 'MPS ' -t MPST -sym off -xm m -o dmake :objects:infer.c.o :objects:make.c.o
+ :objects:stat.c.o :objects:expand.c.o :objects:dmstring.c.o :objects:hash.c.o
+ :objects:dag.c.o :objects:dmake.c.o :objects:path.c.o :objects:imacs.c.o
+ :objects:sysintf.c.o :objects:parse.c.o :objects:getinp.c.o :objects:quit.c.o
+ :objects:state.c.o :objects:dmdump.c.o :objects:macparse.c.o :objects:rulparse.c.o
+ :objects:percent.c.o :objects:function.c.o :objects:arlib.c.o :objects:bogus.c.o
+ :objects:dirbrk.c.o :objects:directry.c.o :objects:environ.c.o :objects:main.c.o
+ :objects:rmprq.c.o :objects:ruletab.c.o :objects:tempnam.c.o :objects:tomacfil.c.o
+ "{SharedLibraries}StdCLib"
+ "{SharedLibraries}InterfaceLib"
+ "{PPCLibraries}StdCRuntime.o"
+ "{PPCLibraries}PPCCRuntime.o"
+ "{PPCLibraries}PPCToolLibs.o"
+if ( `Exists -f :startup:config.mk` )
+ SetFile -a l :startup:config.mk
+end
+Duplicate -y :mac:template.mk :startup:config.mk
diff --git a/dmake/mac/make_mac.sh b/dmake/mac/make_mac.sh
new file mode 100644
index 000000000000..9e6c4cc54949
--- /dev/null
+++ b/dmake/mac/make_mac.sh
@@ -0,0 +1,105 @@
+#
+# $Id: make_mac.sh,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $
+#
+# This MPW script builds the dmake executable using the Metroworks PPC compiler
+# and linker. The resulting dmake binary will only run on the PPC platform.
+#
+# To execute this script, you will need the following tools:
+# - MacOS 8 or later
+# - CodeWarrior for MacOS Release 5 or later
+#
+# To run this script, you need to open the MPW Shell that is bundled with CodeWarrior.
+# If you have another instance of MPW installed other than the one bundled with
+# CodeWarrior, you may encounter problems. Once you open the MPW Shell that is bundled
+# with CodeWarrior, you will need to set MPW's working directory to the "dmake"
+# directory (the directory above the directory that this script is in). Then, execute
+# this script from the MPW Worksheet by typing the following command:
+#
+# :mac:make_mac.sh
+#
+set Exit 1
+if ( "{0}" != ':mac:make_mac.sh' )
+ Echo "You cannot run this script from the current directory."
+ Echo "To run this script, you need to be in the "dmake" directory and then"
+ Echo "execute the following command: ":mac:make_mac.sh""
+ Exit
+end
+if ( ! `Exists -d objects` )
+ NewFolder objects
+end
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle infer.c
+Move -y infer.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle make.c
+Move -y make.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle stat.c
+Move -y stat.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle expand.c
+Move -y expand.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle dmstring.c
+Move -y dmstring.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle hash.c
+Move -y hash.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle dag.c
+Move -y dag.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle dmake.c
+Move -y dmake.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle path.c
+Move -y path.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle imacs.c
+Move -y imacs.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle sysintf.c
+Move -y sysintf.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle parse.c
+Move -y parse.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle getinp.c
+Move -y getinp.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle quit.c
+Move -y quit.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle state.c
+Move -y state.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle dmdump.c
+Move -y dmdump.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle macparse.c
+Move -y macparse.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle rulparse.c
+Move -y rulparse.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle percent.c
+Move -y percent.c.o objects
+# Note that function.c needs to have __useAppleExts__ defined. Otherwise, it won't link.
+MWCPPC -o : -ansi off -I :mac -d _MPW -d __useAppleExts__ -sym off -proto ignoreoldstyle function.c
+Move -y function.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:arlib.c
+Move -y arlib.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:bogus.c
+Move -y bogus.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:dirbrk.c
+Move -y dirbrk.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:directry.c
+Move -y directry.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:environ.c
+Move -y environ.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:main.c
+Move -y main.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:rmprq.c
+Move -y rmprq.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:ruletab.c
+Move -y ruletab.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:tempnam.c
+Move -y tempnam.c.o objects
+MWCPPC -o : -ansi off -I :mac -d _MPW -sym off -proto ignoreoldstyle :mac:tomacfil.c
+Move -y tomacfil.c.o objects
+MWLinkPPC -w -c 'MPS ' -t MPST -sym off -xm m -o dmake :objects:infer.c.o :objects:make.c.o
+ :objects:stat.c.o :objects:expand.c.o :objects:dmstring.c.o :objects:hash.c.o
+ :objects:dag.c.o :objects:dmake.c.o :objects:path.c.o :objects:imacs.c.o
+ :objects:sysintf.c.o :objects:parse.c.o :objects:getinp.c.o :objects:quit.c.o
+ :objects:state.c.o :objects:dmdump.c.o :objects:macparse.c.o :objects:rulparse.c.o
+ :objects:percent.c.o :objects:function.c.o :objects:arlib.c.o :objects:bogus.c.o
+ :objects:dirbrk.c.o :objects:directry.c.o :objects:environ.c.o :objects:main.c.o
+ :objects:rmprq.c.o :objects:ruletab.c.o :objects:tempnam.c.o :objects:tomacfil.c.o
+ "{SharedLibraries}StdCLib"
+ "{SharedLibraries}InterfaceLib"
+ "{PPCLibraries}StdCRuntime.o"
+ "{PPCLibraries}PPCCRuntime.o"
+ "{PPCLibraries}PPCToolLibs.o"
+SetFile -a l :startup:config.mk
+Duplicate -y :mac:template.mk :startup:config.mk
diff --git a/dmake/mac/public.h b/dmake/mac/public.h
new file mode 100644
index 000000000000..31cc8fa62d49
--- /dev/null
+++ b/dmake/mac/public.h
@@ -0,0 +1,172 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char*, char*));
+int touch_arch ANSI((char*, char*));
+//void tzset () {}/PUBLIC int putenv (char *pEnvString) {return (0); }/ ANSI(());
+void tzset ANSI(());
+int Wait_for_child ANSI((int ,int ));
+void Clean_up_processes ANSI(());
+int If_root_path ANSI((char *));
+int stat ANSI((char *, struct stat *));
+char *getcwd ANSI((char *,size_t ));
+int chdir ANSI((char *));
+int utime ANSI((char *,time_t *));
+void make_env ANSI(());
+void free_env ANSI(());
+void Remove_prq ANSI((CELLPTR));
+char *tempnam ANSI((char *,char *));
+
+#endif
diff --git a/dmake/mac/rmprq.c b/dmake/mac/rmprq.c
new file mode 100644
index 000000000000..424b9a060009
--- /dev/null
+++ b/dmake/mac/rmprq.c
@@ -0,0 +1,38 @@
+/* RCS $Id: rmprq.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Remove prerequisites code.
+--
+-- DESCRIPTION
+-- This code is different for The Mac and for UNIX and parallel make
+-- architectures since the parallel case requires the rm's to be
+-- run in parallel, whereas The Mac guarantees to run them sequentially.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+PUBLIC void
+Remove_prq( tcp )
+CELLPTR tcp;
+{
+ tcp->ce_flag &= ~(F_MADE|F_VISITED);
+ tcp->ce_time = 0L;
+
+ Make( tcp, tcp );
+}
diff --git a/dmake/mac/ruletab.c b/dmake/mac/ruletab.c
new file mode 100644
index 000000000000..d970b6eb9848
--- /dev/null
+++ b/dmake/mac/ruletab.c
@@ -0,0 +1,43 @@
+/* RCS $Id: ruletab.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Default initial configuration of dmake.
+--
+-- DESCRIPTION
+-- Define here the initial set of rules that are defined before
+-- dmake performs any processing.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* These are control macros for dmake that MUST be defined at some point
+ * if they are NOT dmake will not work! These are default definitions. They
+ * may be overridden inside the .STARTUP makefile, they are here
+ * strictly so that dmake can parse the STARTUP makefile */
+
+static char *_rules[] = {
+ "MAXLINELENGTH := 4094",
+ "MAXPROCESSLIMIT := 1",
+ "MAXPROCESS := 1",
+ ".IMPORT .IGNORE: DMAKEROOT SOLARVER UPD INPATH OS UPDMINOREXT",
+ ".MAKEFILES : makefile.mk Makefile makefile",
+ ".SOURCE : .NULL",
+#include "startup.h"
+ 0 };
+
+char **Rule_tab = _rules; /* for sundry reasons in Get_environment() */
+
diff --git a/dmake/mac/startup.h b/dmake/mac/startup.h
new file mode 100644
index 000000000000..f4d18a5d6506
--- /dev/null
+++ b/dmake/mac/startup.h
@@ -0,0 +1,28 @@
+/* RCS $Id: startup.h,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Default value of MAKESTARTUP.
+--
+-- DESCRIPTION
+-- Default value is used if the environment variable is not
+-- defined.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+"MAKESTARTUP := $(DMAKEROOT):startup.mk",
+
diff --git a/dmake/mac/sysintf.h b/dmake/mac/sysintf.h
new file mode 100644
index 000000000000..f7ef353a343a
--- /dev/null
+++ b/dmake/mac/sysintf.h
@@ -0,0 +1,42 @@
+/* RCS $Id: sysintf.h,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Assorted bits of system interface
+--
+-- DESCRIPTION
+-- This file is used to abstract away some of the functions in
+-- sysintf.c.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+#define DMSTAT stat
+#define VOID_LCACHE(l,m)
+#define Hook_std_writes(A)
+#define GETPID 1
+#define DMSTRLWR(A,B)
+
+/* for directory cache */
+#define CacheStat(A,B) really_dostat(A,&buf)
+
+/*
+** standard C items
+*/
+
+/*
+** Mac interface standard items
+*/
+#define getswitchar() '-'
diff --git a/dmake/mac/template.mk b/dmake/mac/template.mk
new file mode 100644
index 000000000000..0cf10289c826
--- /dev/null
+++ b/dmake/mac/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= mac
+ OSRELEASE *:=
+ OSENVIRONMENT *:=
diff --git a/dmake/mac/tempnam.c b/dmake/mac/tempnam.c
new file mode 100644
index 000000000000..ee86ccb6a0a2
--- /dev/null
+++ b/dmake/mac/tempnam.c
@@ -0,0 +1,65 @@
+/* RCS $Id: tempnam.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Fake tempnam function for the mac
+--
+-- DESCRIPTION
+-- Get a temporary file name.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+
+#include "extern.h"
+#include <StdIO.h>
+#include <String.h>
+
+
+
+/*
+ * Try to open a temporary file in the given directory (if non-NULL)
+ * with the given prefix (if non-NULL).
+ *
+ * We ignore the directory argument.
+ */
+PUBLIC char *
+tempnam(char *pDir, char * pPrefix)
+{
+ char *pName;
+ char *pFullName;
+
+ pName = tmpnam ((char *) NULL);
+
+ /* Assume that if the name returned by tmpnam is not being used,
+ the name with the prefix is also not being used. */
+ pFullName = MALLOC (((pPrefix != NULL) ? strlen (pPrefix) : 0) +
+ strlen (pName) + 1, char);
+
+ /* Copy in the name if we successfully allocated space for it. */
+ if (pFullName != NULL) {
+ if (pPrefix != NULL) {
+ strcpy (pFullName, pPrefix);
+ } else {
+ *pFullName = '\0';
+ } /* if ... else */
+
+ strcat (pFullName, pName);
+ } /* if */
+
+ return (pFullName);
+} /* PUBLIC char *tempnam () */
diff --git a/dmake/mac/tomacfil.c b/dmake/mac/tomacfil.c
new file mode 100644
index 000000000000..d5f1ea72a496
--- /dev/null
+++ b/dmake/mac/tomacfil.c
@@ -0,0 +1,38 @@
+/* RCS $Id: tomacfil.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Routines to change unix file names to mac file names
+--
+-- DESCRIPTION
+-- Dmake sometimes assumes that files have '/' as a directory parameter in some makefiles.
+-- This works, even on DOS, but not on the Mac. In fact, on the Mac, you can't even do a
+-- a simple switch of ':' for '/' because all other the Mac has decided to reverse the use
+-- of a first-character directory delimiter to mean a relative path rather than absolute path.
+-- (i.e., ':test:b' means directory test is relative to the current directory, rather than
+-- a top-level directory. Thus, this file attempts to do the directory conversion behind
+-- the back of the rest of the program.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* This file no longer contains an override to the fopen() function as we now accept only
+ * Mac style path names
+ */
+#include <Files.h>
+
+#include "extern.h"
diff --git a/dmake/macparse.c b/dmake/macparse.c
new file mode 100644
index 000000000000..a842b091b6e5
--- /dev/null
+++ b/dmake/macparse.c
@@ -0,0 +1,211 @@
+/* RCS $Id: macparse.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Parse a macro definition
+--
+-- DESCRIPTION
+-- This file contains the code that parses a macro definition
+-- stored in a buffer. If the string in buffer is not a valid
+-- macro definition the routie Parse_macro returns 0, otherwise it
+-- returns 1 to indicate success.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+PUBLIC int
+Parse_macro( buffer, flag )/*
+=============================
+ Parse the string in buffer and define it as a macro if it is a valid macro.
+ Note especially the string .SETDIR= since it is an attribute, but looks a
+ lot like a macro definition. This would not be a problem if make used
+ white space as token separators, since this is not the case we must do
+ something about it. */
+char *buffer;
+int flag;
+{
+ char *result; /* temporary pointer for strings */
+ TKSTR input; /* place to scan the buffer from */
+ HASHPTR hv; /* pointer to hash table value */
+ int operator; /* what macro operator do we have */
+ char *tok1; /* temporary place to keep a token */
+ char *tok2; /* temporary place to keep a token */
+
+ DB_ENTER( "Parse_macro" );
+
+ SET_TOKEN( &input, buffer );
+ tok1 = Get_token( &input, "=+:*!?", 0 );
+
+ operator=Macro_op(tok1);
+ if( operator ) {
+ Error( "No macro name" );
+ CLEAR_TOKEN( &input );
+ DB_RETURN( 1 );
+ }
+
+ tok1 = DmStrDup(tok1);
+ tok2 = Get_token( &input, "=+:*!?", 2 );
+ if( !(operator = Macro_op(tok2)) || !strcmp(tok1,".SETDIR") ) {
+ CLEAR_TOKEN( &input );
+ FREE(tok1);
+ DB_RETURN(0);
+ }
+
+ tok2 = Expand(tok1); FREE(tok1); tok1 = tok2;
+ tok2 = Get_token(&input, NIL( char ), FALSE);
+
+ /* Make sure we can force the assignment. */
+ if ( operator & M_OP_SI ) {
+ flag |= M_FORCE|M_MULTI;
+ operator &= ~M_OP_SI;
+ }
+
+ switch( operator ) {
+ case M_OP_PLCL:
+ tok2 = Expand( tok2 );
+ /* Fall thru */
+
+ case M_OP_PL:
+ /* Add to an existing macro, if it is not defined, though, then
+ * just define a new macro */
+
+ if( (hv = GET_MACRO(tok1)) == NIL(HASH) || hv->ht_value == NIL(char) )
+ Def_macro( tok1, tok2, flag );
+ else {
+ result = DmStrAdd( hv->ht_value, tok2, FALSE );
+ Def_macro( tok1, result, flag );
+ FREE( result );
+ }
+ if( operator == M_OP_PLCL ) FREE(tok2);
+ break;
+
+ case M_OP_DF:
+ if( (hv = GET_MACRO(tok1)) != NIL(HASH) && !(hv->ht_flag & M_INIT) )
+ break;
+ /* else FALLTHRU */
+
+ case M_OP_EQ:
+ Def_macro( tok1, tok2, flag );
+ break;
+
+ case M_OP_DFCL:
+ if( (hv = GET_MACRO(tok1)) != NIL(HASH) && !(hv->ht_flag & M_INIT) )
+ break;
+ /* else FALLTHRU */
+
+ case M_OP_CL:
+ tok2 = Expand( tok2 );
+ Def_macro( tok1, tok2, M_EXPANDED | flag );
+ FREE( tok2 );
+ break;
+
+ case M_OP_CM:{
+ CELLPTR cp;
+ STRINGPTR sp;
+
+ if (flag & M_PUSH) {
+ Error("Nested conditional definition [%s ?= %s] ignored",
+ tok1, tok2);
+ }
+ else {
+ cp = Def_cell(tok1);
+ if (cp->ce_flag & F_MULTI) {
+ LINKPTR lp;
+ for(lp=cp->ce_prq; lp->cl_next; lp=lp->cl_next);
+ cp = lp->cl_prq;
+ }
+ TALLOC(sp,1,STRING);
+ sp->st_string = DmStrDup(tok2);
+ sp->st_next = cp->ce_cond;
+ cp->ce_cond = sp;
+
+ tok1 = NIL(char);
+ }
+ }
+ break;
+ }
+
+ if (tok1) {
+ if ( LastMacName != NIL(char) )
+ FREE( LastMacName );
+
+ LastMacName = tok1;
+ }
+
+ DB_RETURN( 1 );
+}
+
+
+
+PUBLIC int
+Macro_op( op )/*
+================
+ Check the passed in op string and map it to one of the macro operators */
+char *op;
+{
+ int ret = 0;
+ DB_ENTER( "macro_op" );
+
+ if ( *op == '!' ) {
+ ret = M_OP_SI;
+ op++;
+ }
+
+ switch( *op ) {
+ case '=': ret |= M_OP_EQ; break;
+ case ':': ret |= M_OP_CL; op++; break;
+
+ case '+':
+ op++;
+ if( *op == ':' ) {
+ ret |= M_OP_PLCL;
+ op++;
+ }
+ else {
+ ret |= M_OP_PL;
+ }
+ break;
+
+ case '*':
+ op++;
+ if( *op == ':' ) {
+ ret |= M_OP_DFCL;
+ op++;
+ }
+ else {
+ ret |= M_OP_DF;
+ }
+ break;
+
+ case '?':
+ ret |= M_OP_CM;
+ op++;
+ break;
+ }
+
+ if( *op != '=' )
+ ret = 0;
+ else {
+ op++;
+
+ if( *op != '\0' )
+ ret = 0;
+ }
+
+ DB_RETURN( ret );
+}
diff --git a/dmake/make.bat b/dmake/make.bat
new file mode 100755
index 000000000000..a0e3fdea8bcf
--- /dev/null
+++ b/dmake/make.bat
@@ -0,0 +1,273 @@
+echo off
+cls
+rem *** This is the make batchfile that is used under MSDOS to make the
+rem *** first version of dmake. It isn't pretty but it does work, assuming
+rem *** the compilers have been correctly setup. See the warning below
+rem *** concerning tlink, if you are building any of the Borland compiler
+rem *** versions.
+rem
+
+if %0%1 == %0 goto error
+if %1 == tcc20swp goto mktccswp
+
+if %1 == bcc30swp goto mkbcc30swp
+if %1 == bcc40swp goto mkbcc40swp
+if %1 == bcc45swp goto mkbcc45swp
+if %1 == bcc50swp goto mkbcc50swp
+
+if %1 == msc51 goto mkms51
+if %1 == msc51swp goto mkms51swp
+if %1 == msc60 goto mkms60
+if %1 == msc60swp goto mkms60swp
+
+if %1 == win95-bcc50 goto mkw32b50
+if %1 == win95-vpp40 goto mkw32vp40
+
+rem label the possible DOS variations for dmake here.
+:error
+echo MSDOS: You must specify 'make target' where target is one of:
+echo -------------
+echo tcc20swp - Turbo C 2.0 compile of swapping dmake..
+
+echo bcc30swp - Borland C++ 3.0 compile of swapping dmake.
+echo bcc40swp - Borland C++ 4.0 compile of swapping dmake.
+echo bcc45swp - Borland C++ 4.5 compile of swapping dmake.
+echo bcc50swp - Borland C++ 5.0 compile of swapping dmake.
+
+echo msc51 - Microsoft C 5.1 compile.
+echo msc51swp - Microsoft C 5.1, MASM 5.1 compile of swapping dmake.
+echo msc60 - Microsoft C 6.0 compile.
+echo msc60swp - Microsoft C 6.0, MASM 5.1 compile of swapping dmake.
+
+echo win95-bcc50 - Borland C++ 5.0 32-bit compile of dmake.
+echo win95-vpp40 - Microsoft VC++ 4.0 32-bit compile of dmake.
+goto end
+
+rem This is the script that makes dmake using Microsoft C 5.1
+:mkms51
+msdos\microsft\msc51\mk.bat
+goto end
+
+:mkms51swp
+msdos\microsft\msc51\mkswp.bat
+goto end
+
+rem This is the script that makes dmake using Microsoft C 6.0
+:mkms60
+msdos\microsft\msc60\mk.bat
+goto end
+
+:mkms60swp
+msdos\microsft\msc60\mkswp.bat
+goto end
+
+:mkw32vp40
+win95\microsft\vpp40\mk.bat
+goto end
+
+rem This is the script that makes dmake using Turbo C 2.0 or higher.
+:mktcc
+cls
+echo WARNING:
+echo The default response files:
+echo msdos\borland\tcc20\obj.rsp
+echo msdos\borland\tcc20\lib.rsp
+echo contain absolute paths to TURBO-C runtime startup objects, and to
+echo the standard libraries. You should check that these files contain
+echo the correct path names for your installation of Turbo-C before
+echo proceeding further. Also check that the mkdir command at the start
+echo of the response file and the copy command at the end of the response
+echo file will work on your system.
+echo --
+echo Continue if ok, or abort and edit the response files.
+pause
+msdos\borland\tcc20\mk.bat
+goto end
+
+:mktccswp
+cls
+echo WARNING:
+echo The default response files:
+echo msdos\borland\tcc20\objswp.rsp
+echo msdos\borland\tcc20\libswp.rsp
+echo contain absolute paths to TURBO-C runtime startup objects, and to
+echo the standard libraries. You should check that these files contain
+echo the correct path names for your installation of Turbo-C before
+echo proceeding further. Also check that the mkdir command at the start
+echo of the response file and the copy command at the end of the response
+echo file will work on your system.
+echo --
+echo Continue if ok, or abort and edit the response files.
+pause
+msdos\borland\tcc20\mkswp.bat
+goto end
+
+rem This is the script that makes dmake using Borland C++ 3.0.
+:mkbcc30
+cls
+echo WARNING:
+echo The default response files:
+echo msdos\borland\bcc30\obj.rsp
+echo msdos\borland\bcc30\lib.rsp
+echo contain absolute paths to Borland C++ runtime startup objects, and to
+echo the standard libraries. You should check that these files contain
+echo the correct path names for your installation of Borland C++ before
+echo proceeding further. Also check that the mkdir command at the start
+echo of the response file and the copy command at the end of the response
+echo file will work on your system.
+echo --
+echo Continue if ok, or abort and edit the response files.
+pause
+msdos\borland\bcc30\mk.bat
+goto end
+
+:mkbcc30swp
+cls
+echo WARNING:
+echo The default response files:
+echo msdos\borland\bcc30\objswp.rsp
+echo msdos\borland\bcc30\libswp.rsp
+echo contain absolute paths to Borland C++ runtime startup objects, and to
+echo the standard libraries. You should check that these files contain
+echo the correct path names for your installation of Borland C++ before
+echo proceeding further. Also check that the mkdir command at the start
+echo of the response file and the copy command at the end of the response
+echo file will work on your system.
+echo --
+echo Continue if ok, or abort and edit the response files.
+pause
+msdos\borland\bcc30\mkswp.bat
+goto end
+
+rem This is the script that makes dmake using Borland C++ 4.0.
+:mkbcc40
+cls
+echo WARNING:
+echo The default response files:
+echo msdos\borland\bcc40\obj.rsp
+echo msdos\borland\bcc40\lib.rsp
+echo contain absolute paths to Borland C++ runtime startup objects, and to
+echo the standard libraries. You should check that these files contain
+echo the correct path names for your installation of Borland C++ before
+echo proceeding further. Also check that the mkdir command at the start
+echo of the response file and the copy command at the end of the response
+echo file will work on your system.
+echo --
+echo Continue if ok, or abort and edit the response files.
+pause
+msdos\borland\bcc40\mk.bat
+goto end
+
+:mkbcc40swp
+cls
+echo WARNING:
+echo The default response files:
+echo msdos\borland\bcc40\objswp.rsp
+echo msdos\borland\bcc40\libswp.rsp
+echo contain absolute paths to Borland C++ runtime startup objects, and to
+echo the standard libraries. You should check that these files contain
+echo the correct path names for your installation of Borland C++ before
+echo proceeding further. Also check that the mkdir command at the start
+echo of the response file and the copy command at the end of the response
+echo file will work on your system.
+echo --
+echo Continue if ok, or abort and edit the response files.
+pause
+msdos\borland\bcc40\mkswp.bat
+goto end
+
+rem This is the script that makes dmake using Borland C++ 4.5.
+:mkbcc45
+cls
+echo WARNING:
+echo The default response files:
+echo msdos\borland\bcc45\obj.rsp
+echo msdos\borland\bcc45\lib.rsp
+echo contain absolute paths to Borland C++ runtime startup objects, and to
+echo the standard libraries. You should check that these files contain
+echo the correct path names for your installation of Borland C++ before
+echo proceeding further. Also check that the mkdir command at the start
+echo of the response file and the copy command at the end of the response
+echo file will work on your system.
+echo --
+echo Continue if ok, or abort and edit the response files.
+pause
+msdos\borland\bcc45\mk.bat
+goto end
+
+:mkbcc45swp
+cls
+echo WARNING:
+echo The default response files:
+echo msdos\borland\bcc45\objswp.rsp
+echo msdos\borland\bcc45\libswp.rsp
+echo contain absolute paths to Borland C++ runtime startup objects, and to
+echo the standard libraries. You should check that these files contain
+echo the correct path names for your installation of Borland C++ before
+echo proceeding further. Also check that the mkdir command at the start
+echo of the response file and the copy command at the end of the response
+echo file will work on your system.
+echo --
+echo Continue if ok, or abort and edit the response files.
+pause
+msdos\borland\bcc45\mkswp.bat
+goto end
+
+rem This is the script that makes dmake using Borland C++ 5.0.
+:mkbcc50
+cls
+echo WARNING:
+echo The default response files:
+echo msdos\borland\bcc50\obj.rsp
+echo msdos\borland\bcc50\lib.rsp
+echo contain absolute paths to Borland C++ runtime startup objects, and to
+echo the standard libraries. You should check that these files contain
+echo the correct path names for your installation of Borland C++ before
+echo proceeding further. Also check that the mkdir command at the start
+echo of the response file and the copy command at the end of the response
+echo file will work on your system.
+echo --
+echo Continue if ok, or abort and edit the response files.
+pause
+msdos\borland\bcc50\mk.bat
+goto end
+
+:mkbcc50swp
+cls
+echo WARNING:
+echo The default response files:
+echo msdos\borland\bcc50\objswp.rsp
+echo msdos\borland\bcc50\libswp.rsp
+echo contain absolute paths to Borland C++ runtime startup objects, and to
+echo the standard libraries. You should check that these files contain
+echo the correct path names for your installation of Borland C++ before
+echo proceeding further. Also check that the mkdir command at the start
+echo of the response file and the copy command at the end of the response
+echo file will work on your system.
+echo --
+echo Continue if ok, or abort and edit the response files.
+pause
+msdos\borland\bcc50\mkswp.bat
+goto end
+
+rem This is the script that makes 32-bit dmake using Borland C++ 5.0.
+:mkw32b50
+cls
+echo WARNING:
+echo The default response files:
+echo win95\borland\bcc50\obj.rsp
+echo win95\borland\bcc50\lib.rsp
+echo contain absolute paths to Borland C++ runtime startup objects, and to
+echo the standard libraries. You should check that these files contain
+echo the correct path names for your installation of Borland C++ before
+echo proceeding further. Also check that the mkdir command at the start
+echo of the response file and the copy command at the end of the response
+echo file will work on your system.
+echo --
+echo Continue if ok, or abort and edit the response files.
+pause
+win95\borland\bcc50\mk.bat
+goto end
+
+rem All done!
+:end
diff --git a/dmake/make.c b/dmake/make.c
new file mode 100644
index 000000000000..2586e58c28ba
--- /dev/null
+++ b/dmake/make.c
@@ -0,0 +1,1412 @@
+/* RCS $Id: make.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Perform the update of all outdated targets.
+--
+-- DESCRIPTION
+-- This is where we traverse the make graph looking for targets that
+-- are out of date, and we try to infer how to make them if we can.
+-- The usual make macros are understood, as well as some new ones:
+--
+-- $$ - expands to $
+-- $@ - full target name
+-- $* - target name with no suffix, same as $(@:db)
+-- or, the value of % in % meta rule recipes
+-- $? - list of out of date prerequisites
+-- $< - all prerequisites associated with rules line
+-- $& - all prerequisites associated with target
+-- $> - library name for target (if any)
+-- $^ - out of date prerequisites taken from value of $<
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+#include "sysintf.h"
+
+typedef struct cell {
+ char *datum;
+ struct cell *next;
+ size_t len;
+} LISTCELL, *LISTCELLPTR;
+
+typedef struct {
+ LISTCELLPTR first;
+ LISTCELLPTR last;
+ size_t len;
+} LISTSTRING, *LISTSTRINGPTR;
+
+
+static void _drop_mac ANSI((HASHPTR));
+static void _set_recipe ANSI((char*, int));
+static void _set_tmd ANSI(());
+static void _append_file ANSI((STRINGPTR, FILE*, char*, int));
+static LINKPTR _dup_prq ANSI((LINKPTR));
+static LINKPTR _expand_dynamic_prq ANSI(( LINKPTR, LINKPTR, char * ));
+static char* _prefix ANSI((char *, char *));
+static char* _pool_lookup ANSI((char *));
+
+#define RP_GPPROLOG 0
+#define RP_RECIPE 1
+#define RP_GPEPILOG 2
+#define NUM_RECIPES 3
+
+static STRINGPTR _recipes[NUM_RECIPES];
+static LISTCELLPTR _freelist=NULL;
+
+static LISTCELLPTR
+get_cell()
+{
+ LISTCELLPTR cell;
+
+ if (!_freelist) {
+ if ((cell=MALLOC(1,LISTCELL)) == NULL)
+ No_ram();
+ }
+ else {
+ cell = _freelist;
+ _freelist = cell->next;
+ }
+
+ return(cell);
+}
+
+
+static void
+free_cell(LISTCELLPTR cell)
+{
+ cell->next = _freelist;
+ _freelist = cell;
+}
+
+
+static void
+free_list(LISTCELLPTR c)
+{
+ if(c) {
+ free_list(c->next);
+ free_cell(c);
+ }
+}
+
+
+static void
+list_init(LISTSTRINGPTR s)
+{
+ s->first = NULL;
+ s->last = NULL;
+ s->len = 0;
+}
+
+
+static void
+list_add(LISTSTRINGPTR s, char *str)
+{
+ LISTCELLPTR p;
+ int l;
+
+ if ((l = strlen(str)) == 0)
+ return;
+
+ p = get_cell();
+ p->datum = str;
+ p->next = NULL;
+ p->len = l;
+
+ if(s->first == NULL)
+ s->first = p;
+ else
+ s->last->next = p;
+
+ s->last = p;
+ s->len += l+1;
+}
+
+
+static char *
+list_string(LISTSTRINGPTR s)
+{
+ LISTCELLPTR next, cell;
+ int len;
+ char *result;
+ char *p;
+
+ if(s->len == 0)
+ return(NIL(char));
+
+ if((p = result = MALLOC(s->len, char)) == NULL) No_ram();
+
+ for (cell=s->first; cell; cell=next) {
+ memcpy((void *)p, (void *)cell->datum, len=cell->len);
+ p += len;
+ *p++ = ' ';
+ next = cell->next;
+ free_cell(cell);
+ }
+
+ *--p = '\0';
+ list_init(s);
+
+ return(result);
+}
+
+
+PUBLIC int
+Make_targets()/*
+================
+ Actually go and make the targets on the target list */
+{
+ LINKPTR lp;
+ int done = 0;
+
+ DB_ENTER( "Make_targets" );
+
+ Read_state();
+ _set_recipe( ".GROUPPROLOG", RP_GPPROLOG );
+ _set_recipe( ".GROUPEPILOG", RP_GPEPILOG );
+
+ /* Prevent recipe inference for .ROOT */
+ if ( Root->ce_recipe == NIL(STRING) ) {
+ TALLOC( Root->ce_recipe, 1, STRING );
+ Root->ce_recipe->st_string = "";
+ }
+
+ /* Prevent recipe inference for .TARGETS */
+ if ( Targets->ce_recipe == NIL(STRING) ) {
+ TALLOC( Targets->ce_recipe, 1, STRING );
+ Targets->ce_recipe->st_string = "";
+ }
+
+ /* Make sure that user defined targets are marked as root targets */
+ for( lp = Targets->ce_prq; lp != NIL(LINK); lp = lp->cl_next )
+ lp->cl_prq->ce_attr |= A_ROOT;
+
+ while( !done ) {
+ int rval;
+
+ if( (rval = Make(Root, NIL(CELL))) == -1 )
+ DB_RETURN(1);
+ else
+ done = Root->ce_flag & F_MADE;
+
+ if( !rval && !done ) Wait_for_child( FALSE, -1 );
+ }
+
+ for( lp = Targets->ce_prq; lp != NIL(LINK); lp = lp->cl_next ) {
+ CELLPTR tgt = lp->cl_prq;
+ if( !(tgt->ce_attr & A_UPDATED) )
+ printf( "`%s' is up to date\n", tgt->CE_NAME );
+ }
+
+ DB_RETURN( 0 );
+}
+
+
+
+PUBLIC int
+Make( cp, setdirroot )/*
+======================== Make a specified target */
+CELLPTR cp;
+CELLPTR setdirroot;
+{
+ register LINKPTR dp, prev,next;
+ register CELLPTR tcp;
+ CELLPTR nsetdirroot;
+ char *name, *lib;
+ HASHPTR m_at, m_q, m_b, m_g, m_l, m_bb, m_up;
+ LISTSTRING all_list, imm_list, outall_list, inf_list;
+ char *all = NIL(char);
+ char *inf = NIL(char);
+ char *outall = NIL(char);
+ char *imm = NIL(char);
+ int rval = 0;
+ int push = 0;
+ int made = F_MADE;
+ int ignore;
+ time_t otime = (time_t) 1L;
+ time_t ttime = (time_t) 1L;
+ int mark_made = FALSE;
+
+ DB_ENTER( "Make" );
+ DB_PRINT( "mem", ("%s:-> mem %ld", cp->CE_NAME, (long) coreleft()) );
+
+ /* Initialize the various temporary storage */
+ m_q = m_b = m_g = m_l = m_bb = m_up = NIL(HASH);
+ list_init(&all_list);
+ list_init(&imm_list);
+ list_init(&outall_list);
+ list_init(&inf_list);
+
+ if (cp->ce_set && cp->ce_set != cp) {
+ if( Verbose & V_MAKE )
+ printf( "%s: Building .UPDATEALL representative [%s]\n", Pname,
+ cp->ce_set->CE_NAME );
+ cp = cp->ce_set;
+ }
+
+ /* If we are supposed to change directories for this target then do so.
+ * If we do change dir, then modify the setdirroot variable to reflect
+ * that fact for all of the prerequisites that we will be making. */
+
+ nsetdirroot = setdirroot;
+ ignore = (((cp->ce_attr|Glob_attr)&A_IGNORE) != 0);
+ m_at = Def_macro( "@", cp->ce_fname, M_MULTI );
+
+ if( cp->ce_attr & A_SETDIR ) {
+ /* Change directory only if the previous .SETDIR is a different
+ * directory from the current one. ie. all cells with the same .SETDIR
+ * attribute are assumed to come from the same directory. */
+
+ if( (setdirroot == NIL(CELL) || setdirroot->ce_dir != cp->ce_dir) &&
+ (push = Push_dir(cp->ce_dir,cp->CE_NAME,ignore)) != 0 )
+ setdirroot = cp;
+ }
+
+ DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
+ if( cp->ce_recipe == NIL(STRING) ) {
+ char *dir = cp->ce_dir;
+
+ if( Verbose & V_MAKE )
+ printf( "%s: Infering prerequisite(s) and recipe for [%s]\n", Pname,
+ cp->CE_NAME );
+
+ Infer_recipe( cp, setdirroot );
+
+ /* See if the directory has changed, if it has then make sure we
+ * push it. */
+ if( dir != cp->ce_dir ) {
+ if( push ) Pop_dir(FALSE);
+ push = Push_dir( cp->ce_dir, cp->CE_NAME, ignore );
+ setdirroot = cp;
+ }
+ }
+
+ for(dp=CeMeToo(cp); dp; dp=dp->cl_next) {
+ tcp = dp->cl_prq;
+ if( push ) {
+ if( !(tcp->ce_attr & A_POOL) && tcp->ce_dir ) FREE( tcp->ce_dir );
+ tcp->ce_dir = _pool_lookup(Pwd);
+ tcp->ce_attr |= A_SETDIR|A_POOL;
+ }
+ tcp->ce_setdir = nsetdirroot;
+ }
+
+ DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
+ /* If we have not yet statted the target then do so. */
+ if( !(cp->ce_flag & F_STAT) && !(cp->ce_attr&A_PHONY) ) {
+ time_t itime = cp->ce_time;
+
+ if (cp->ce_parent && (cp->ce_parent->ce_flag & F_MULTI)) {
+ /* Inherit the stat info from the parent. */
+ cp->ce_time = cp->ce_parent->ce_time;
+ cp->ce_flag |= F_STAT;
+ cp->ce_attr |= cp->ce_parent->ce_attr & A_PRECIOUS;
+ }
+ else {
+ for(dp=CeMeToo(cp); dp; dp=dp->cl_next) {
+ tcp = dp->cl_prq;
+ Stat_target( tcp, TRUE, FALSE );
+
+ if( tcp->ce_time == (time_t)0L ) {
+ if( tcp->ce_flag & F_INFER )
+ tcp->ce_time = itime;
+ }
+ else {
+ /* File exists so don't remove it later. */
+ tcp->ce_attr |= A_PRECIOUS;
+ }
+
+ if( Verbose & V_MAKE )
+ printf("%s: Time stamp of [%s] is %ld\n",Pname,tcp->CE_NAME,
+ tcp->ce_time);
+ }
+ }
+ }
+
+ DB_PRINT( "make", ("(%s, %ld, 0x%08x, 0x%04x)", cp->CE_NAME,
+ cp->ce_time, cp->ce_attr, cp->ce_flag) );
+
+ if( !(cp->ce_flag & F_TARGET) && (cp->ce_time == (time_t) 0L) )
+ if( Makemkf ) {
+ rval = -1;
+ goto stop_making_it;
+ }
+ else if( cp->ce_prq != NIL(LINK)
+ || (STOBOOL(Augmake) && (cp->ce_flag&F_EXPLICIT)))
+ /* Assume an empty recipe for a target that we have run inference on
+ * but do not have a set of rules for but for which we have inferred
+ * a list of prerequisites. */
+ cp->ce_flag |= F_RULES;
+ else
+ Fatal( "`%s' not found, and can't be made", cp->CE_NAME );
+
+ DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
+
+ /* set value of $* if we have not infered a recipe, in this case $* is
+ * the same as $(@:db), this allows us to be compatible with BSD make */
+ if( cp->ce_per == NIL(char) ) cp->ce_per = "$(@:db)";
+
+ /* Search the prerequisite list for dynamic prerequisites and if we find
+ * them copy the list of prerequisites for potential later re-use. */
+ if ( cp->ce_prqorg == NIL(LINK) ) {
+ for( dp = cp->ce_prq; dp != NIL(LINK); dp = dp->cl_next )
+ if ( strchr(dp->cl_prq->CE_NAME, '$') != NULL )
+ break;
+
+ if (dp != NIL(LINK)) {
+ cp->ce_prqorg = _dup_prq(cp->ce_prq);
+ }
+ }
+
+ m_at = Def_macro("@", cp->ce_fname, M_MULTI);
+
+ /* Define conditional macros if any, note this is done BEFORE we process
+ * prerequisites for the current target. Thus the making of a prerequisite
+ * is done using the current value of the conditional macro. */
+ for(dp=CeMeToo(cp); dp; dp=dp->cl_next) {
+ tcp=dp->cl_prq;
+ if (tcp->ce_cond != NIL(STRING)) {
+ STRINGPTR sp;
+
+ tcp->ce_pushed = NIL(HASH);
+ for(sp=tcp->ce_cond; sp; sp=sp->st_next) {
+ if(Parse_macro(sp->st_string,M_MULTI|M_PUSH)) {
+ HASHPTR hp;
+
+ hp = GET_MACRO(LastMacName);
+ hp->ht_link = tcp->ce_pushed;
+ tcp->ce_pushed = hp;
+ }
+ else {
+ Error("Invalid conditional macro expression [%s]",sp->st_string);
+ }
+ }
+ }
+ }
+
+ for( prev=NULL,dp=cp->ce_prq; dp != NIL(LINK); prev=dp, dp=next ) {
+ int seq;
+ int nesting_count;
+
+ /* This is the only macro that needs to be reset while building
+ * prerequisites since it is set when we make each prerequisite. */
+ if (m_at->ht_value == NIL(char)) {
+ m_at = Def_macro("@", cp->ce_fname, M_MULTI);
+ }
+
+ /* Make the prerequisite, note that if the current target has the
+ * .LIBRARY attribute set we pass on to the prerequisite the .LIBRARYM
+ * attribute and pass on the name of the current target as the library
+ * name, and we take it away when we are done. */
+ next = dp->cl_next;
+
+ tcp = dp->cl_prq;
+ seq = (((cp->ce_attr | Glob_attr) & A_SEQ) != 0);
+
+ if( tcp->ce_flag & F_VISITED )
+ if( _explode_graph(tcp, dp, setdirroot) == 0 ) {
+ /* didn't blow it up so see if we need to wait for it. */
+ if( tcp->ce_flag & F_MADE ) {
+ if( tcp->ce_time > ttime ) ttime = tcp->ce_time;
+ continue;
+ }
+ else
+ goto stop_making_it;
+ }
+ else
+ tcp = dp->cl_prq;
+
+ if( seq && !made ) goto stop_making_it;
+
+ nesting_count = 0;
+ while ( tcp
+ && strchr(tcp->CE_NAME, '$')
+ ) {
+ if ( nesting_count++ > DynamicNestLevel ) {
+ Fatal( "Dynamic Macro nesting level exceeded [%s]",
+ cp->CE_NAME );
+ }
+ /* Make this prerequisite link point at the real prerequisite we
+ * are after, ie figure out what the dynamic one is and point at it.*/
+
+ name = Expand( tcp->CE_NAME );
+ if( strcmp(name,cp->CE_NAME) == 0 )
+ Fatal("Detected circular dynamic dependency; generated '%s'",name);
+
+ dp = _expand_dynamic_prq( cp->ce_prq, dp, name );
+ FREE( name );
+
+ tcp = dp->cl_prq;
+ if ( tcp ) {
+ next = dp->cl_next;
+ }
+ }
+
+ /* Dynamic expansion results in a NULL cell only when the the new
+ * prerequisite is already in the prerequisite list. In this case
+ * delete the cell and continue. */
+ if ( tcp == NIL(CELL) ) {
+ FREE(dp);
+ if ( prev == NIL(LINK) ) {
+ cp->ce_prq = next;
+ }
+ else {
+ prev->cl_next = next;
+ }
+ continue;
+ }
+
+ if( cp->ce_attr & A_LIBRARY ) {
+ tcp->ce_attr |= A_LIBRARYM;
+ tcp->ce_lib = cp->ce_fname;
+ }
+
+ if( (tcp->ce_flag & (F_INFER|F_STAT))==F_INFER && cp->ce_time >= ttime )
+ tcp->ce_time = cp->ce_time;
+
+ /* Propagate the parent's F_REMOVE and F_INFER flags to the children.
+ * Make certain to do this AFTER propagating the time, since the
+ * time propagation test above uses the F_INFER flag to decide if
+ * it should do so. */
+ tcp->ce_flag |= cp->ce_flag & (F_REMOVE|F_INFER);
+
+ /* Propagate parents A_ROOT attribute to a child if the parent is a
+ * F_MULTI target. */
+ if( (cp->ce_flag & F_MULTI) && (cp->ce_attr & A_ROOT) )
+ tcp->ce_attr |= A_ROOT;
+
+ tcp->ce_parent = cp;
+ rval |= Make(tcp, setdirroot);
+
+ if( cp->ce_attr & A_LIBRARY )
+ tcp->ce_attr ^= A_LIBRARYM;
+
+ if( rval == -1 || (seq && (rval==1)) )
+ goto stop_making_it;
+
+ if( tcp->ce_time > ttime ) ttime = tcp->ce_time;
+ made &= tcp->ce_flag & F_MADE;
+ }
+
+
+ /* Do the loop again. We are most definitely going to make the current
+ * cell now. NOTE: doing this loop here also results in a reduction
+ * in peak memory usage by the algorithm. */
+
+ for( dp = cp->ce_prq; dp != NIL(LINK); dp = dp->cl_next ) {
+ int tgflg;
+ tcp = dp->cl_prq;
+ name = tcp->ce_fname;
+
+ /* make certain that all prerequisites are made prior to advancing. */
+ if( !(tcp->ce_flag & F_MADE) ) goto stop_making_it;
+
+ /* If the target is a library, then check to make certain that a member
+ * is newer than an object file sitting on disk. If the disk version
+ * is newer then set the time stamps so that the archived member is
+ * replaced. */
+ if( cp->ce_attr & A_LIBRARY )
+ if( tcp->ce_time < cp->ce_time ) {
+ time_t mtime = Do_stat( name, tcp->ce_lib, NIL(char *), FALSE );
+ if( mtime < tcp->ce_time ) tcp->ce_time = cp->ce_time+1L;
+ }
+
+ if( tcp->ce_time > otime ) otime = tcp->ce_time;
+
+ list_add(&all_list, name);
+ if( (tgflg = (dp->cl_flag & F_TARGET)) != 0 )
+ list_add(&inf_list, name);
+
+ if((cp->ce_time<tcp->ce_time) || ((tcp->ce_flag & F_TARGET) && Force)) {
+ list_add(&outall_list, name);
+ if( tgflg )
+ list_add(&imm_list, name);
+ }
+ }
+
+ all = list_string(&all_list);
+ imm = list_string(&imm_list);
+ outall = list_string(&outall_list);
+ inf = list_string(&inf_list);
+
+ DB_PRINT( "mem", ("%s:-C mem %ld", cp->CE_NAME, (long) coreleft()) );
+ DB_PRINT( "make", ("I make '%s' if %ld > %ld", cp->CE_NAME, otime,
+ cp->ce_time) );
+
+ if( Verbose & V_MAKE && !(cp->ce_flag & F_MULTI) ) {
+ printf( "%s: >>>> Making ", Pname );
+ if( cp->ce_count != 0 )
+ printf( "[%s::{%d}]\n", cp->CE_NAME, cp->ce_count );
+ else
+ printf( "[%s]\n", cp->CE_NAME );
+ }
+
+ m_at = Def_macro( "@", cp->ce_fname, M_MULTI );
+ m_g = Def_macro( ">", cp->ce_lib, M_MULTI|M_EXPANDED );
+ m_q = Def_macro( "?", outall, M_MULTI|M_EXPANDED );
+ m_b = Def_macro( "<", inf, M_MULTI|M_EXPANDED );
+ m_l = Def_macro( "&", all, M_MULTI|M_EXPANDED );
+ m_up = Def_macro( "^", imm, M_MULTI|M_EXPANDED );
+ m_bb = Def_macro( "*", cp->ce_per, M_MULTI );
+
+ _recipes[ RP_RECIPE ] = cp->ce_recipe;
+
+ /* We attempt to make the target if
+ * 1. it has a newer prerequisite
+ * 2. It is a target and Force is set
+ * 3. It's set of recipe lines has changed.
+ */
+ if( Check_state(cp, _recipes, NUM_RECIPES )
+ || (cp->ce_time < otime)
+ || ((cp->ce_flag & F_TARGET) && Force)
+ ) {
+
+ /* Only checking so stop as soon as we determine we will make
+ * something */
+ if( Check ) {
+ rval = -1;
+ goto stop_making_it;
+ }
+
+ if( Verbose & V_MAKE )
+ printf( "%s: Updating [%s], (%ld > %ld)\n", Pname,
+ cp->CE_NAME, otime, cp->ce_time );
+
+ if( Touch ) {
+ name = cp->ce_fname;
+ lib = cp->ce_lib;
+
+ if( (!(Glob_attr & A_SILENT) || !Trace) && !(cp->ce_attr & A_PHONY) )
+ if( lib == NIL(char) )
+ printf("touch(%s)", name );
+ else if( cp->ce_attr & A_SYMBOL )
+ printf("touch(%s((%s)))", lib, name );
+ else
+ printf("touch(%s(%s))", lib, name );
+
+ if( !Trace && !(cp->ce_attr & A_PHONY) )
+ if( Do_touch( name, lib,
+ (cp->ce_attr & A_SYMBOL) ? &name : NIL(char *) ) != 0 )
+ printf( " not touched - non-existant" );
+
+ if( (!(Glob_attr & A_SILENT) || !Trace) && !(cp->ce_attr & A_PHONY) )
+ printf( "\n" );
+
+ Update_time_stamp( cp );
+ }
+ else if( cp->ce_recipe != NIL(STRING) ) {
+ if( !(cp->ce_flag & F_SINGLE) )
+ rval = Exec_commands( cp );
+ else {
+ TKSTR tk;
+
+ _drop_mac( m_q );
+
+ if( outall && *outall ) {
+ SET_TOKEN( &tk, outall );
+
+ Doing_bang = TRUE;
+ name = Get_token( &tk, "", FALSE );
+ do {
+ m_q->ht_value = name;
+
+ Wait_for_completion = TRUE; /* Reset in Exec_commands */
+ rval = Exec_commands( cp );
+ Unlink_temp_files(cp);
+ }
+ while( *(name = Get_token( &tk, "", FALSE )) != '\0' );
+ Doing_bang = FALSE;
+ }
+
+ Update_time_stamp( cp );
+ m_q->ht_value = NIL(char);
+ }
+ }
+ else if( !(cp->ce_flag & F_RULES) && !(cp->ce_flag & F_STAT) &&
+ (!(cp->ce_attr & A_ROOT) || !(cp->ce_flag & F_EXPLICIT)) )
+ Fatal( "Don't know how to make `%s'",cp->CE_NAME );
+ else {
+ /* Empty recipe, set the flag as MADE and update the time stamp */
+ Update_time_stamp( cp );
+ }
+ }
+ else {
+ mark_made = TRUE;
+ }
+
+ /* Make sure everyone gets remade if Force is set */
+ for(dp=CeMeToo(cp); dp; dp=dp->cl_next) {
+ tcp=dp->cl_prq;
+
+ if( !(tcp->ce_flag & F_TARGET) && Force ) tcp->ce_time = Do_time();
+ if( mark_made ) {
+ tcp->ce_flag |= F_MADE;
+ if( tcp->ce_flag & F_MULTI ) {
+ LINKPTR tdp;
+ for( tdp = tcp->ce_prq; tdp != NIL(LINK); tdp = tdp->cl_next )
+ tcp->ce_attr |= tdp->cl_prq->ce_attr & A_UPDATED;
+ }
+ }
+
+ tcp->ce_flag |= F_VISITED;
+
+ /* Note: If the prerequisite was made using a .SETDIR= attribute
+ * directory then we will include the directory in the fname
+ * of the target. */
+ if( push ) {
+ char *dir = nsetdirroot ? nsetdirroot->ce_dir : Makedir;
+ char *pref = _prefix(dir,tcp->ce_dir);
+ char *nname = Build_path(pref, tcp->ce_fname);
+
+ FREE(pref);
+ if( (tcp->ce_attr & A_FFNAME) && (tcp->ce_fname != NIL(char)) )
+ FREE( tcp->ce_fname );
+
+ tcp->ce_fname = DmStrDup(nname);
+ tcp->ce_attr |= A_FFNAME;
+ }
+ }
+
+stop_making_it:
+ _drop_mac( m_g );
+ _drop_mac( m_q );
+ _drop_mac( m_b );
+ _drop_mac( m_l );
+ _drop_mac( m_bb );
+ _drop_mac( m_up );
+ _drop_mac( m_at );
+
+ /* undefine conditional macros if any */
+ for(dp=CeMeToo(cp); dp; dp=dp->cl_next) {
+ tcp=dp->cl_prq;
+
+ while (tcp->ce_pushed != NIL(HASH)) {
+ HASHPTR cur = tcp->ce_pushed;
+ tcp->ce_pushed = cur->ht_link;
+
+ Pop_macro(cur);
+ FREE(cur->ht_name);
+ if(cur->ht_value)
+ FREE(cur->ht_value);
+ FREE(cur);
+ }
+ }
+
+ while( push-- )
+ Pop_dir(FALSE);
+
+ /* Undefine the strings that we used for constructing inferred
+ * prerequisites. */
+ if( inf != NIL(char) ) FREE( inf );
+ if( all != NIL(char) ) FREE( all );
+ if( imm != NIL(char) ) FREE( imm );
+ if( outall != NIL(char) ) FREE( outall );
+ free_list(all_list.first);
+ free_list(imm_list.first);
+ free_list(outall_list.first);
+ free_list(inf_list.first);
+
+ DB_PRINT( "mem", ("%s:-< mem %ld", cp->CE_NAME, (long) coreleft()) );
+ DB_RETURN(rval);
+}
+
+
+static char *
+_prefix( pfx, pat )
+char *pfx;
+char *pat;
+{
+ char *cmp1=pfx;
+ char *cmp2=pat;
+ char *result = DmStrDup("");
+ char *up;
+
+ while(*pfx && *pat) {
+ pfx = DmStrSpn(cmp1, DirBrkStr);
+ pat = DmStrSpn(cmp2, DirBrkStr);
+
+ cmp1 = DmStrPbrk(pfx, DirBrkStr);
+ cmp2 = DmStrPbrk(pat, DirBrkStr);
+
+ if ( (cmp1-pfx) != (cmp2-pat) || strncmp(pfx,pat,cmp1-pfx) != 0 )
+ break;
+ }
+
+ up = DmStrJoin("..",DirSepStr,-1,FALSE);
+ cmp1 = pfx;
+ while ( *(pfx=DmStrSpn(cmp1,DirBrkStr)) != '\0' ) {
+ cmp1 = DmStrPbrk(pfx,DirBrkStr);
+ result = DmStrJoin(result,up,-1,TRUE);
+ }
+
+ cmp2 = pat;
+ while ( *(pat=DmStrSpn(cmp2,DirBrkStr)) != '\0' ) {
+ char *tmp;
+ char *x;
+ cmp2 = DmStrPbrk(pat, DirBrkStr);
+ tmp = DmStrDup(Build_path(result,x=DmSubStr(pat,cmp2)));
+ FREE(result);
+ FREE(x);
+ result = tmp;
+ }
+
+ return(result);
+}
+
+
+static LINKPTR
+_dup_prq( lp )
+LINKPTR lp;
+{
+ LINKPTR tlp;
+
+ if( lp == NIL(LINK) ) return(lp);
+
+ TALLOC(tlp, 1, LINK);
+ tlp->cl_prq = lp->cl_prq;
+ tlp->cl_flag = lp->cl_flag;
+ tlp->cl_next = _dup_prq( lp->cl_next );
+
+ return(tlp);
+}
+
+
+static LINKPTR
+_expand_dynamic_prq( head, lp, name )
+LINKPTR head;
+LINKPTR lp;
+char *name;
+{
+ CELLPTR cur = lp->cl_prq;
+
+ if ( strchr(name, ' ') == NIL(char) ) {
+ CELLPTR prq = Def_cell(name);
+ LINKPTR tmp;
+
+ for(tmp=head;tmp != NIL(LINK) && tmp->cl_prq != prq;tmp=tmp->cl_next);
+
+ if ( !tmp )
+ lp->cl_prq = prq;
+ }
+ else {
+ LINKPTR tlp = lp;
+ LINKPTR next = lp->cl_next;
+ TKSTR token;
+ char *p;
+ int first=TRUE;
+
+ SET_TOKEN(&token, name);
+ while (*(p=Get_token(&token, "", FALSE)) != '\0') {
+ CELLPTR prq = Def_cell(p);
+ LINKPTR tmp;
+
+ for(tmp=head;tmp != NIL(LINK) && tmp->cl_prq != prq;tmp=tmp->cl_next);
+ if ( tmp ) continue;
+
+ if ( first ) {
+ first = FALSE;
+ }
+ else {
+ TALLOC(tlp->cl_next,1,LINK);
+ tlp = tlp->cl_next;
+ tlp->cl_flag |= F_TARGET;
+ tlp->cl_next = next;
+ }
+
+ tlp->cl_prq = prq;
+ }
+ CLEAR_TOKEN( &token );
+ }
+
+ if ( lp->cl_prq == cur ) {
+ lp->cl_prq = NIL(CELL);
+ lp->cl_flag = 0;
+ }
+
+ return(lp);
+}
+
+
+static void
+_drop_mac( hp )/*
+================ set a macro value to zero. */
+HASHPTR hp;
+{
+ if( hp && hp->ht_value != NIL(char) ) {
+ FREE( hp->ht_value );
+ hp->ht_value = NIL(char);
+ }
+}
+
+
+
+int
+_explode_graph( cp, parent, setdirroot )/*
+==========================================
+ Check to see if we have made the node already. If so then don't do
+ it again, except if the cell's ce_setdir field is set to something other
+ than the value of setdirroot. If they differ then, and we have made it
+ already, then make it again and set the cell's stat bit to off so that
+ we do the stat again. */
+CELLPTR cp;
+LINKPTR parent;
+CELLPTR setdirroot;
+{
+ static CELLPTR removecell = NIL(CELL);
+
+ if ( removecell == NIL(CELL) )
+ removecell = Def_cell(".REMOVE");
+
+ /* we may return if we made it already from the same setdir location,
+ * or if it is not a library member whose lib field is non NULL. (if
+ * it is such a member then we have a line of the form:
+ * lib1 lib2 .LIBRARY : member_list...
+ * and we have to make sure all members are up to date in both libs. */
+
+ if ( setdirroot == removecell )
+ return( 0 );
+
+ if( cp->ce_setdir == setdirroot &&
+ !((cp->ce_attr & A_LIBRARYM) && (cp->ce_lib != NIL(char))) )
+ return( 0 );
+
+ /* We check to make sure that we are comming from a truly different
+ * directory, ie. ".SETDIR=joe : a.c b.c d.c" are all assumed to come
+ * from the same directory, even though setdirroot is different when
+ * making dependents of each of these targets. */
+
+ if( cp->ce_setdir != NIL(CELL) &&
+ setdirroot != NIL(CELL) &&
+ cp->ce_dir &&
+ setdirroot->ce_dir &&
+ !strcmp(cp->ce_dir, setdirroot->ce_dir) )
+ return( 0 );
+
+ if( Max_proc > 1 ) {
+ LINKPTR dp;
+
+ TALLOC(parent->cl_prq, 1, CELL);
+ *parent->cl_prq = *cp;
+ cp = parent->cl_prq;
+ cp->ce_prq = _dup_prq(cp->ce_prqorg);
+ cp->ce_all.cl_prq = cp;
+ CeNotMe(cp) = _dup_prq(CeNotMe(cp));
+
+ for(dp=CeNotMe(cp);dp;dp=dp->cl_next) {
+ CELLPTR tcp = dp->cl_prq;
+ TALLOC(dp->cl_prq,1,CELL);
+ *dp->cl_prq = *tcp;
+ dp->cl_prq->ce_flag &= ~(F_STAT|F_VISITED|F_MADE);
+ dp->cl_prq->ce_set = cp;
+ }
+ }
+ cp->ce_flag &= ~(F_STAT|F_VISITED|F_MADE);
+
+ /* Indicate that we exploded the graph and that the current node should
+ * be made. */
+ return(1);
+}
+
+
+
+PUBLIC int
+Exec_commands( cp )/*
+=====================
+ Execute the commands one at a time that are pointed to by the rules pointer
+ of the target cp. If a group is indicated, then the ce_attr determines
+ .IGNORE and .SILENT treatment for the group.
+
+ The function returns 0, if the command is executed and has successfully
+ returned, and returns 1 if the command is executing but has not yet
+ returned (for parallel makes).
+
+ The F_MADE bit in the cell is guaranteed set when the command has
+ successfully completed. */
+CELLPTR cp;
+{
+ static HASHPTR useshell = NIL(HASH);
+ static HASHPTR command = NIL(HASH);
+ static int read_cmnd = 0;
+ register STRINGPTR rp;
+ STRINGPTR orp;
+ char *cmnd;
+ char *groupfile;
+ FILE *tmpfile;
+ int do_it;
+ t_attr attr;
+ int group;
+ int trace;
+ int rval = 0;
+
+ DB_ENTER( "Exec_commands" );
+
+ attr = Glob_attr | cp->ce_attr;
+ trace = Trace || !(attr & A_SILENT);
+ group = cp->ce_flag & F_GROUP;
+
+ /* Do it again here for those that call us from places other than Make()
+ * above. */
+ orp = _recipes[ RP_RECIPE ];
+ _recipes[ RP_RECIPE ] = cp->ce_recipe;
+
+ if( group ) {
+ /* Leave this assignment of Current_target here. It is needed just
+ * incase the user hits ^C after the tempfile for the group recipe
+ * has been opened. */
+ Current_target = cp;
+ trace = Trace || !(attr & A_SILENT);
+
+ if( !Trace ) tmpfile = Start_temp( Grp_suff, cp, &groupfile );
+ if( trace ) fputs( "[\n", stdout );
+
+ /* Emit group prolog */
+ if( attr & A_PROLOG )
+ _append_file( _recipes[RP_GPPROLOG], tmpfile, cp->CE_NAME, trace );
+ }
+
+ if( !useshell )
+ useshell=Def_macro("USESHELL",NIL(char),M_MULTI|M_EXPANDED);
+
+ if( !read_cmnd ) {
+ command = GET_MACRO("COMMAND");
+ read_cmnd = 1;
+ }
+
+ /* Process commands in recipe. If in group, merely append to file.
+ * Otherwise, run them. */
+ for( rp=_recipes[RP_RECIPE]; rp != NIL(STRING); rp=rp->st_next,FREE(cmnd)){
+ t_attr a_attr = A_DEFAULT;
+ t_attr l_attr;
+ char *p;
+ int new_attr = FALSE;
+ int shell;
+
+ /* Reset it for each recipe line otherwise tempfiles don't get removed.
+ * Since processing of $(mktmp ...) depends on Current_target being
+ * correctly set. */
+ Current_target = cp;
+
+ /* Only check for +,-,%,@ if the recipe line begins with a '$' macro
+ * expansion. Otherwise there is no way it is going to find these
+ * now. */
+ if( *rp->st_string == '$' && !group ) {
+ t_attr s_attr = Glob_attr;
+ Glob_attr |= A_SILENT;
+ Suppress_temp_file = TRUE;
+ cmnd = Expand(rp->st_string);
+ Suppress_temp_file = FALSE;
+ a_attr |= Rcp_attribute(cmnd);
+ FREE(cmnd);
+ ++new_attr;
+ Glob_attr = s_attr;
+ }
+
+ l_attr = attr|a_attr|rp->st_attr;
+ shell = ((l_attr & A_SHELL) != 0);
+ useshell->ht_value = (group||shell)?"yes":"no";
+
+ cmnd = Expand( rp->st_string );
+
+ if( new_attr && (p = DmStrSpn(cmnd," \t\n+-@%")) != cmnd )
+ strcpy(cmnd,p);
+
+ /* COMMAND macro is set to "$(CMNDNAME) $(CMNDARGS)" by default, it is
+ * possible for the user to reset it to, for example
+ * COMMAND = $(CMNDNAME) @$(mktmp $(CMNDARGS))
+ * in order to get a different interface for his command execution. */
+ if( command != NIL(HASH) && !group ) {
+ char *cname = cmnd;
+ char cmndbuf[30];
+
+ if ( *(p=DmStrPbrk(cmnd," \t\n")) != '\0' ) {
+ *p = '\0';
+ (void)Def_macro("CMNDARGS",DmStrSpn(p+1," \t\n"),M_MULTI|M_EXPANDED);
+ }
+ else
+ (void) Def_macro("CMNDARGS","",M_MULTI|M_EXPANDED);
+
+ (void) Def_macro("CMNDNAME",cname,M_MULTI|M_EXPANDED);
+
+ strcpy(cmndbuf, "$(COMMAND)");
+ cmnd = Expand(cmndbuf);
+ FREE(cname); /* cname == cmnd at this point. */
+
+ /* Collect up any new attributes */
+ l_attr |= Rcp_attribute(cmnd);
+ shell = ((l_attr & A_SHELL) != 0);
+
+ /* clean up the attributes that we may have just added. */
+ if( (p = DmStrSpn(cmnd," \t\n+-@%")) != cmnd )
+ strcpy(cmnd,p);
+ }
+
+ Swap_on_exec = ((l_attr & A_SWAP) != 0); /* Swapping for DOS only */
+ do_it = !Trace;
+
+ /* We force execution of the recipe if we are tracing and the .EXECUTE
+ * attribute was given or if the it is not a group recipe and the
+ * recipe line contains the string $(MAKE). */
+ if( Trace
+ && ((l_attr & A_EXECUTE)||(!group && DmStrStr(rp->st_string,"$(MAKE)")))
+ ) {
+ Wait_for_completion |= Trace;
+ do_it = TRUE;
+ }
+
+ if( group )
+ Append_line( cmnd, TRUE, tmpfile, cp->CE_NAME, trace, 0 );
+ else {
+ if( *DmStrSpn(cmnd, " \t") != '\0' )
+ Print_cmnd(cmnd, !(do_it && (l_attr & A_SILENT)), 0);
+ else
+ do_it = FALSE;
+
+ rval=Do_cmnd(cmnd,FALSE,do_it,cp,(l_attr&A_IGNORE)!=0, shell,
+ rp->st_next == NIL(STRING) );
+ }
+ }
+
+ /* If it is a group then output the EPILOG if required and possibly
+ * execute the command */
+ if( group && !(cp->ce_attr & A_ERROR) ) {
+ if( attr & A_EPILOG ) /* emit epilog */
+ _append_file( _recipes[RP_GPEPILOG], tmpfile, cp->CE_NAME, trace );
+
+ if( trace ) fputs("]\n", stdout);
+
+ do_it = !Trace;
+ if( do_it )
+ {
+ Close_temp( cp, tmpfile );
+#if defined(UNIX)
+
+ chmod(groupfile,0700);
+#endif
+ }
+ rval = Do_cmnd(groupfile, TRUE, do_it, cp, (attr & A_IGNORE)!=0,
+ TRUE, TRUE);
+ }
+
+ Wait_for_completion = FALSE;
+ _recipes[ RP_RECIPE ] = orp;
+ cp->ce_attr &= ~A_ERROR;
+ DB_RETURN( rval );
+}
+
+
+PUBLIC void
+Print_cmnd( cmnd, echo, map )/*
+================================
+ This routine is called to print out the command to stdout. If echo is
+ false the printing to stdout is supressed, but the new lines in the command
+ are still deleted. */
+char *cmnd;
+int echo;
+int map;
+{
+ register char *p;
+ register char *n;
+ char tmp[3];
+
+ DB_ENTER( "Print_cmnd" );
+
+ if( echo ) {
+ printf( "%s\n", cmnd );
+ fflush(stdout);
+ }
+
+ tmp[0] = ESCAPE_CHAR;
+ tmp[1] = CONTINUATION_CHAR;
+ tmp[2] = '\0';
+
+ for( p=cmnd; *(n = DmStrPbrk(p,tmp)) != '\0'; )
+ if(*n == CONTINUATION_CHAR && n[1] == '\n') {
+ DB_PRINT( "make", ("fixing [%s]", p) );
+ strcpy( n, n+2 );
+ p = n;
+ }
+ else {
+ if( *n == ESCAPE_CHAR && map ) Map_esc( n );
+ p = n+1;
+ }
+
+ DB_VOID_RETURN;
+}
+
+
+
+/* These routines are used to maintain a stack of directories when making
+ * the targets. If a target cd's to the directory then it is assumed that
+ * it will undo it when it is finished making itself. */
+
+static STRINGPTR dir_stack = NIL(STRING);
+
+PUBLIC int
+Push_dir( dir, name, ignore )/*
+===============================
+ Change the current working directory to dir and save the current
+ working directory on the stack so that we can come back.
+
+ If ignore is TRUE then do not complain about _ch_dir if not possible.*/
+char *dir;
+char *name;
+int ignore;
+{
+ STRINGPTR new_dir;
+ int freedir=FALSE;
+
+ DB_ENTER( "Push_dir" );
+
+ if( dir == NIL(char) || *dir == '\0' ) dir = Pwd;
+ if( *dir == '\'' && dir[strlen(dir)-1] == '\'' ) {
+ dir = DmStrDup(dir+1);
+ dir[strlen(dir)-1]='\0';
+ freedir=TRUE;
+ }
+ else if (strchr(dir,'$') != NIL(char)) {
+ dir = Expand(dir);
+ freedir=TRUE;
+ }
+ else
+ dir = DmStrDup(dir);
+
+ if( Set_dir(dir) ) {
+ if( !ignore )
+ Fatal( "Unable to change to directory `%s', target is [%s]",
+ dir, name );
+ if (freedir) FREE(dir);
+ DB_RETURN( 0 );
+ }
+
+ DB_PRINT( "dir", ("Push: [%s]", dir) );
+ if( Verbose & V_DIR_SET )
+ printf( "%s: Changed to directory [%s]\n", Pname, dir );
+
+ if (freedir) FREE( dir );
+ TALLOC( new_dir, 1, STRING );
+ new_dir->st_next = dir_stack;
+ dir_stack = new_dir;
+ new_dir->st_string = DmStrDup( Pwd );
+
+ Def_macro( "PWD", Get_current_dir(), M_MULTI | M_EXPANDED );
+ _set_tmd();
+
+ DB_RETURN( 1 );
+}
+
+
+
+PUBLIC void
+Pop_dir(ignore)/*
+=================
+ Change the current working directory to the previous saved dir. */
+int ignore;
+{
+ STRINGPTR old_dir;
+ char *dir;
+
+ DB_ENTER( "Pop_dir" );
+
+ if( dir_stack == NIL(STRING) )
+ if( ignore ) {
+ DB_VOID_RETURN;
+ }
+ else
+ Error( "Directory stack empty for return from .SETDIR" );
+
+ if( Set_dir(dir = dir_stack->st_string) )
+ Fatal( "Could not change to directory `%s'", dir );
+
+ Def_macro( "PWD", dir, M_MULTI | M_EXPANDED );
+ DB_PRINT( "dir", ("Pop: [%s]", dir) );
+ if( Verbose & V_DIR_SET )
+ printf( "%s: Changed back to directory [%s]\n", Pname, dir);
+
+ old_dir = dir_stack;
+ dir_stack = dir_stack->st_next;
+
+ FREE( old_dir->st_string );
+ FREE( old_dir );
+ _set_tmd();
+
+ DB_VOID_RETURN;
+}
+
+
+
+static void
+_set_tmd()/*
+============
+ Set the TWD Macro */
+{
+ TKSTR md, pd;
+ char *m, *p;
+ char *tmd;
+ int is_sep;
+ int first = 1;
+
+ SET_TOKEN( &md, Makedir );
+ SET_TOKEN( &pd, Pwd );
+
+ m = Get_token( &md, DirBrkStr, FALSE );
+ (void) Get_token( &pd, DirBrkStr, FALSE );
+ is_sep = (strchr(DirBrkStr, *m) != NIL(char));
+ tmd = DmStrDup( "" );
+
+ do {
+ m = Get_token( &md, DirBrkStr, FALSE );
+ p = Get_token( &pd, DirBrkStr, FALSE );
+
+ if( !is_sep && strcmp(m, p) ) { /* they differ */
+ char *tmp;
+ if( first ) { /* They differ in the first component */
+ tmd = Makedir; /* In this case use the full path */
+ break;
+ }
+
+ if( *p ) tmp = Build_path( "..", tmd );
+ if( *m ) tmp = Build_path( tmd, m );
+ FREE( tmd );
+ tmd = DmStrDup( tmp );
+ }
+
+ is_sep = 1-is_sep;
+ first = 0;
+ } while (*m || *p);
+
+ CLEAR_TOKEN( &md );
+ CLEAR_TOKEN( &pd );
+
+ Def_macro( "TMD", tmd, M_MULTI | M_EXPANDED );
+ if( tmd != Makedir ) FREE( tmd );
+}
+
+
+static void
+_set_recipe( target, ind )/*
+============================
+ Set up the _recipes static variable so that the slot passed in points
+ at the rules corresponding to the target supplied. */
+char *target;
+int ind;
+{
+ CELLPTR cp;
+ HASHPTR hp;
+
+ if( (hp = Get_name(target, Defs, FALSE)) != NIL(HASH) ) {
+ cp = hp->CP_OWNR;
+ _recipes[ ind ] = cp->ce_recipe;
+ }
+ else
+ _recipes[ ind ] = NIL(STRING);
+}
+
+
+
+PUBLIC void
+Append_line( cmnd, newline, tmpfile, name, printit, map )
+char *cmnd;
+int newline;
+FILE *tmpfile;
+char *name;
+int printit;
+int map;
+{
+ Print_cmnd( cmnd, printit, map );
+
+ if( Trace ) return;
+
+ fputs(cmnd, tmpfile);
+ if( newline ) fputc('\n', tmpfile);
+ fflush(tmpfile);
+
+ if( ferror(tmpfile) )
+ Fatal("Write error on temporary file, while processing `%s'", name);
+}
+
+
+
+static void
+_append_file( rp, tmpfile, name, printit )
+register STRINGPTR rp;
+FILE *tmpfile;
+char *name;
+int printit;
+{
+ char *cmnd;
+
+ while( rp != NIL(STRING) ) {
+ Append_line(cmnd = Expand(rp->st_string), TRUE, tmpfile, name, printit,0);
+ FREE(cmnd);
+ rp = rp->st_next;
+ }
+}
+
+
+#define NUM_BUCKETS 20
+
+typedef struct strpool {
+ char *string; /* a pointer to the string value */
+ uint32 keyval; /* the strings hash value */
+ struct strpool *next; /* hash table link pointer */
+} POOL, *POOLPTR;
+
+static POOLPTR strings[ NUM_BUCKETS ];
+
+static char *
+_pool_lookup( str )/*
+=====================
+ Scan down the list of chained strings and see if one of them matches
+ the string we are looking for. */
+char *str;
+{
+ register POOLPTR key;
+ uint32 keyval;
+ uint16 hv;
+ uint16 keyindex;
+ char *string;
+
+ DB_ENTER( "_pool_lookup" );
+
+ if( str == NIL(char) ) DB_RETURN("");
+
+ hv = Hash(str, &keyval);
+ key = strings[ keyindex = (hv % NUM_BUCKETS) ];
+
+ while( key != NIL(POOL) )
+ if( (key->keyval != keyval) || strcmp(str, key->string) )
+ key = key->next;
+ else
+ break;
+
+ if( key == NIL(POOL) ) {
+ DB_PRINT( "pool", ("Adding string [%s]", str) );
+ TALLOC( key, 1, POOL ); /* not found so add string */
+
+ key->string = string = DmStrDup(str);
+ key->keyval = keyval;
+
+ key->next = strings[ keyindex ];
+ strings[ keyindex ] = key;
+ }
+ else {
+ DB_PRINT( "pool", ("Found string [%s], key->string") );
+ string = key->string;
+ }
+
+ DB_RETURN( string );
+}
diff --git a/dmake/make.cmd b/dmake/make.cmd
new file mode 100755
index 000000000000..ba209a24a3c3
--- /dev/null
+++ b/dmake/make.cmd
@@ -0,0 +1,102 @@
+echo off
+cls
+rem *** This is the make command file that is used under OS/2 to make the
+rem *** first version of dmake. It isn't pretty but it does work, assuming
+rem *** the compilers have been correctly setup.
+rem
+
+if %0%1 == %0 goto error
+
+if %1 == os2-ibm goto mkibm
+if %1 == os2-ibm3 goto mkibm3
+if %1 == winnt-bcc40 goto mkwntb40
+if %1 == winnt-bcc45 goto mkwntb45
+if %1 == winnt-bcc50 goto mkwntb50
+if %1 == winnt-vpp40 goto mkwntv40
+
+
+rem label the possible DOS variations for dmake here.
+:error
+echo OS/2 INDEX: You must specify one of:
+echo ------------------
+echo os2-ibm - IBM OS/2 ICC compile.
+echo os2-ibm3 - IBM OS/2 ICC3 compile.
+echo winnt-bcc40 - Windows-NT Borland C++ 4.0 Compile
+echo winnt-bcc45 - Windows-NT Borland C++ 4.5 Compile
+echo winnt-bcc50 - Windows-NT Borland C++ 5.0 Compile
+echo winnt-vpp40 - Windows-NT Microsoft VC++ 4.0 Compile
+goto end
+
+rem This is the script that bilds OS/2 dmake using IBM ICC Compiler
+:mkibm
+os2\ibm\icc\mk.cmd
+goto end
+
+:mkibm3
+os2\ibm\icc3\mk.cmd
+goto end
+
+rem This is the script that makes 32-bit dmake using Borland C++ 4.0.
+:mkwntb40
+cls
+echo WARNING:
+echo The default response files:
+echo winnt\borland\bcc40\obj.rsp
+echo winnt\borland\bcc40\lib.rsp
+echo contain absolute paths to Borland C++ runtime startup objects, and to
+echo the standard libraries. You should check that these files contain
+echo the correct path names for your installation of Borland C++ before
+echo proceeding further. Also check that the mkdir command at the start
+echo of the response file and the copy command at the end of the response
+echo file will work on your system.
+echo --
+echo Continue if ok, or abort and edit the response files.
+pause
+winnt\borland\bcc40\mk.bat
+goto end
+
+rem This is the script that makes 32-bit dmake using Borland C++ 4.5.
+:mkwntb45
+cls
+echo WARNING:
+echo The default response files:
+echo winnt\borland\bcc45\obj.rsp
+echo winnt\borland\bcc45\lib.rsp
+echo contain absolute paths to Borland C++ runtime startup objects, and to
+echo the standard libraries. You should check that these files contain
+echo the correct path names for your installation of Borland C++ before
+echo proceeding further. Also check that the mkdir command at the start
+echo of the response file and the copy command at the end of the response
+echo file will work on your system.
+echo --
+echo Continue if ok, or abort and edit the response files.
+pause
+winnt\borland\bcc45\mk.bat
+goto end
+
+rem All done!
+rem This is the script that makes 32-bit dmake using Borland C++ 5.0.
+:mkwntb50
+cls
+echo WARNING:
+echo The default response files:
+echo winnt\borland\bcc50\obj.rsp
+echo winnt\borland\bcc50\lib.rsp
+echo contain absolute paths to Borland C++ runtime startup objects, and to
+echo the standard libraries. You should check that these files contain
+echo the correct path names for your installation of Borland C++ before
+echo proceeding further. Also check that the mkdir command at the start
+echo of the response file and the copy command at the end of the response
+echo file will work on your system.
+echo --
+echo Continue if ok, or abort and edit the response files.
+pause
+winnt\borland\bcc50\mk.bat
+goto end
+
+:mkwntv40
+winnt\microsft\vpp40\mk.bat
+goto end
+
+rem All done!
+:end
diff --git a/dmake/makefile.mk b/dmake/makefile.mk
new file mode 100644
index 000000000000..17c0a75e3815
--- /dev/null
+++ b/dmake/makefile.mk
@@ -0,0 +1,429 @@
+# //// Makefile for DMAKE. \\\\
+# The target system is characterized by the following macros imported from
+# the environment.
+#
+# OS - gives the class of operating system
+# OSRELEASE - optionally specifies the particular release of the OS
+# OSENVIRONMENT - optionally specifies the environment under which the
+# OS and OSENVIRONMENT are running.
+#
+# For valid values for the above macros consult the readme/* files or type
+# 'make' by itself to get a summary of what is available.
+
+# First target in the makefile, do this so that targets declared in the
+# included files are never marked as being the first *default* target.
+first : all ;
+
+#Enable keeping of state for future compiles
+.KEEP_STATE *:= _state.mk
+
+# Define $(PUBLIC)
+_osenv := $(OSENVIRONMENT)$/
+_osre := $(OSRELEASE)$/$(!null,$(OSENVIRONMENT) $(_osenv))
+ENVDIR = $(OS)$/$(!null,$(OSRELEASE) $(_osre))
+PUBLIC = $(ENVDIR)public.h
+MKCONFIG := startup/config.mk
+
+# Define the source files
+SRC =\
+ infer.c make.c stat.c expand.c dmstring.c hash.c dag.c dmake.c\
+ path.c imacs.c sysintf.c parse.c getinp.c quit.c state.c\
+ dmdump.c macparse.c rulparse.c percent.c function.c
+
+# Common Include files.
+HDR = dmake.h extern.h struct.h vextern.h patchlvl.h version.h
+
+# Define the TARGET we are making, and where the OBJECT files go.
+OBJDIR := objects
+TARGET = dmake$E
+CFLAGS += $(SWITCHAR)I.
+
+# Meta rule for making .o's from .c's (give our own so we can move object
+# to objects directory in a portable, compiler independent way)
+# Define it before the .INCLUDE so that different OS combinations can redefine
+# it.
+%$O : %.c
+.IF $(SHELL) == mpw
+ %$(CC) $(CFLAGS) -o :$(OBJDIR:s,/,:,):$@ $<
+.ELSE
+ %$(CC) $(SWITCHAR)c $(CFLAGS) $<
+.IF $(SHELL) != $(COMSPEC)
+ mv $(@:f) $(OBJDIR)
+.ELSE
+ +copy $(@:f) $(OBJDIR)
+ +del $(@:f)
+.ENDIF
+.ENDIF
+
+# Pull in the proper configuration files, based on the value of OS.
+.INCLUDE : $(OS)/config.mk
+.INCLUDE : dbug/dbug.mk
+
+# Set the .SOURCE targets so that we look for things in the right place.
+.SOURCE.c :^ .NULL
+.SOURCE.h :^ .NULL
+.SOURCE$O :^ $(OBJDIR)
+.PRECIOUS : $(HDR)
+
+# Must come after the above INCLUDE so that it gets ALL objects.
+OBJECTS := {$(ASRC:b) $(SRC:b)}$O
+
+# The main target, make sure the objects directory exists first.
+# LDARGS is defined in config.mk file of each OS/OSRELEASE combination.
+all : $(TARGET) $(MKCONFIG);
+$(TARGET) : $(OBJDIR)
+$(TARGET) : $(OBJECTS);$(LD) $(LDARGS)
+
+# Use this for install targets
+.IF $(SHELL) == mpw
+ $(MKCONFIG) : template.mk
+ duplicate :$(<:s,/,:,) $@
+.ELSE
+ $(MKCONFIG) : template.mk
+ $(eq,$(SHELL),$(COMSPEC) +copy cp) $< $@
+.ENDIF
+
+# how to make public.h
+public .PHONY : $(PUBLIC);
+$(PUBLIC) .GROUP .NOSTATE: $(SRC)
+ genpub -n DMAKE $< >$@
+# drcsclean ./rcsclean.awk $@ > /dev/null
+
+# Other obvious targets...
+.IF $(SHELL) == mpw
+ $(OBJDIR):;-newfolder $@
+.ELSE
+ $(OBJDIR):;-$(eq,$(SHELL),$(COMSPEC) +md mkdir) $@
+.ENDIF
+
+# remaining dependencies should be automatically generated
+sysintf$O : sysintf.h
+ruletab$O : startup.h #khc 01NOV90 - dependency was missing
+$(OBJECTS) : $(HDR)
+
+clean:;+- $(RM:f) -rf dmake$E dbdmake$E objects* _*state*.mk startup/config.mk
+
+# Rules for making the manual pages.
+man .SETDIR=man : dmake.nc dmake.uue ;
+dmake.nc : dmake.p ; scriptfix < $< > $@
+dmake.p : dmake.tf; groff -man -Tascii $< > $@
+dmake.uue : dmake.p
+ compress -b 12 dmake.p
+ mv dmake.p.Z dmake.Z
+ uuencode dmake.Z dmake.Z >dmake.uue
+ /bin/rm -f dmake.Z
+
+template.mk ".SETDIR=$(ENVDIR)" .USESHELL .MKDIR : $$(TMD)startup/template.mk
+ cat $< |\
+ sed -e 's/xxOSxx/$(OS)/' |\
+ sed -e 's/xxOSRELEASExx/$(OSRELEASE)/' |\
+ sed -e 's/xxOSENVIRONMENTxx/$(OSENVIRONMENT)/' > $@
+
+#--------------------------------------------------------------------------
+# Make the various archives for shipping the thing around.
+#
+archives : zip tar
+ $(RM) -rf src-list dmake
+
+zip .PHONY : dmake.zip ;
+shar .PHONY : dmake.shar;
+tar .PHONY : dmake.tar;
+
+dmake.zip : dir-copy
+ zip -r $(@:b) $(@:b)
+
+dmake.shar : dir-copy
+ find dmake -type f -print >src-list
+ xshar -vc -o$@ -L40 `cat src-list`
+
+dmake.tar : dir-copy
+ tar cf $@ dmake
+
+dir-copy .PHONY : src-list
+[
+ echo 'tmp.tar .SILENT :$$(ALLSRC) ;tar -cf tmp.tar $$(ALLSRC)' >> $<
+ $(MAKECMD) -f $< tmp.tar
+ mkdir dmake
+ cd dmake
+ tar xf ../tmp.tar; chmod -R u+rw .
+ cd ..
+ /bin/rm -f tmp.tar
+]
+
+src-list : clean
+ echo 'MAXLINELENGTH := 65536' > $@
+ echo 'ALLSRC = \' >>$@
+ find . -type f -print |\
+ sed -e 's/,v//'\
+ -e 's/$$/\\/'\
+ -e 's/^\.\// /'|\
+ sort -u |\
+ grep -v tst | grep -v $@ | grep -v license |\
+ grep -v CVS | grep -v RCS |\
+ grep -v '\.zip' | grep -v '\.tar'| grep -v '\.shar' >> $@
+ echo ' readme/license.txt' >> $@
+
+#--------------------------------------------------------------------------
+# This section can be used to make the necessary script files so that dmake
+# can be bootstrapped.
+#
+# dmake scripts -- makes all the script files at once.
+#
+FIX-SH = $(SH:s,fix/,,)
+FIX95-SH = $(SH:s,fix95nt/,,)
+SH = $(SH_n:s/c40d/cd/:s/c50d/cd/:s/c51d/cd/:s/c60d/cd/)
+SH_n = $(@:s/swp-/-/:s,-,/,:s/scripts/${SCRIPTFILE}/)
+MS = MAKESTARTUP=startup/startup.mk
+FS := "SHELL := $(SHELL)" "SHELLFLAGS := -ce"
+SET-TMP:= TMPDIR:=/tmp
+
+scripts: unix-scripts\
+ atari-tos-scripts apple-mac-scripts qssl-qnx-scripts\
+ msdos-scripts win95-scripts os2-scripts;
+
+# To add a new environment for UNIX, simply create the appropriate entry
+# in the style below for the macro which contains the OS, OSRELEASE and
+# OSENVIRONMENT flags. Then add the entry as a recipe line for the target
+# unix-scripts.
+#
+unix-bsd43-scripts-flags = OS=unix OSRELEASE=bsd43 OSENVIRONMENT=
+unix-linux-gnu-scripts-flags = OS=unix OSRELEASE=linux OSENVIRONMENT=gnu
+unix-solaris-scripts-flags = OS=unix OSRELEASE=solaris OSENVIRONMENT=
+unix-solaris-gnu-scripts-flags = OS=unix OSRELEASE=solaris OSENVIRONMENT=gnu
+unix-bsd43-uw-scripts-flags= OS=unix OSRELEASE=bsd43 OSENVIRONMENT=uw
+unix-bsd43-vf-scripts-flags= OS=unix OSRELEASE=bsd43 OSENVIRONMENT=vf
+unix-sysvr4-scripts-flags = OS=unix OSRELEASE=sysvr4 OSENVIRONMENT=
+unix-sysvr3-scripts-flags = OS=unix OSRELEASE=sysvr3 OSENVIRONMENT=
+unix-sysvr3-pwd-scripts-flags = OS=unix OSRELEASE=sysvr3 OSENVIRONMENT=pwd
+unix-xenix-scripts-flags = OS=unix OSRELEASE=xenix OSENVIRONMENT=
+unix-xenix-pwd-scripts-flags = OS=unix OSRELEASE=xenix OSENVIRONMENT=pwd
+unix-sysvr1-scripts-flags = OS=unix OSRELEASE=sysvr1 OSENVIRONMENT=
+unix-386ix-scripts-flags = OS=unix OSRELEASE=386ix OSENVIRONMENT=
+unix-coherent-ver40-scripts-flags= OS=unix OSRELEASE=coherent OSENVIRONMENT=ver40
+unix-coherent-ver42-scripts-flags= OS=unix OSRELEASE=coherent OSENVIRONMENT=ver42
+unix-macosx-gnu-scripts-flags = OS=unix OSRELEASE=macosx OSENVIRONMENT=gnu
+qssl--scripts-flags = OS=qssl OSRELEASE= OSENVIRONMENT=
+tos--scripts-flags = OS=tos OSRELEASE= OSENVIRONMENT=
+mac--scripts-flags = OS=mac OSRELEASE= OSENVIRONMENT=
+
+unix-scripts .SWAP : clean
+ $(MAKE) SCRIPTFILE=make.sh unix-bsd43-scripts
+ $(MAKE) SCRIPTFILE=make.sh unix-bsd43-uw-scripts
+ $(MAKE) SCRIPTFILE=make.sh unix-bsd43-vf-scripts
+ $(MAKE) SCRIPTFILE=make.sh unix-linux-gnu-scripts
+ $(MAKE) SCRIPTFILE=make.sh unix-solaris-scripts
+ $(MAKE) SCRIPTFILE=make.sh unix-solaris-gnu-scripts
+ $(MAKE) SCRIPTFILE=make.sh unix-sysvr4-scripts
+ $(MAKE) SCRIPTFILE=make.sh unix-sysvr3-scripts
+ $(MAKE) SCRIPTFILE=make.sh unix-sysvr3-pwd-scripts
+ $(MAKE) SCRIPTFILE=make.sh unix-xenix-scripts
+ $(MAKE) SCRIPTFILE=make.sh unix-xenix-pwd-scripts
+ $(MAKE) SCRIPTFILE=make.sh unix-sysvr1-scripts
+ $(MAKE) SCRIPTFILE=make.sh unix-386ix-scripts
+ $(MAKE) SCRIPTFILE=make.sh unix-coherent-ver40-scripts
+ $(MAKE) SCRIPTFILE=make.sh unix-coherent-ver42-scripts
+ $(MAKE) SCRIPTFILE=make.sh unix-macosx-gnu-scripts
+
+atari-tos-scripts .SWAP : clean
+ $(MAKE) SCRIPTFILE=make.sh tos--scripts
+
+qssl-qnx-scripts .SWAP : clean
+ $(MAKE) SCRIPTFILE=make.sh qssl--scripts
+
+apple-mac-scripts .SWAP : clean
+ $(MAKE) SCRIPTFILE=make.sh mac--scripts
+
+unix-%-scripts .SWAP :
+ $(MAKECMD) -su $($@-flags) .KEEP_STATE:= $(FS) public template.mk
+ $(MAKECMD) -ns .KEEP_STATE:= $(MS) $($@-flags) >/tmp/dmscr
+ dfold </tmp/dmscr >$(SH)
+
+qssl-%-scripts .SWAP :
+ $(MAKECMD) -su $($@-flags) .KEEP_STATE:= $(FS) public template.mk
+ $(MAKECMD) -ns .KEEP_STATE:= $(MS) $($@-flags) >/tmp/dmscr
+ dfold </tmp/dmscr >$(SH)
+
+tos-%-scripts .SWAP :
+ $(MAKECMD) -su $($@-flags) .KEEP_STATE:= $(FS) public template.mk
+ $(MAKECMD) -ns .KEEP_STATE:= $(MS) $($@-flags) >/tmp/dmscr
+ dfold </tmp/dmscr >$(SH)
+
+mac-%-scripts .SWAP :
+ $(MAKECMD) -su $($@-flags) .KEEP_STATE:= $(FS) public template.mk
+ $(MAKECMD) -ns .KEEP_STATE:= $(MS) $($@-flags) >$(SH)
+ sed 's/ mac\/\(.*\)$$/ :mac:\1/' <$(SH) | dfold >/tmp/dmscr
+ /bin/mv /tmp/dmscr $(SH)
+
+# We make the standard dos scripts here, but we have to go and fix up the
+# mkXX.bat file since it contains names of temporary files for the response
+# files required by the linker. We need to also construct the response file
+# contents. These two functions are performed by the fix-msdos-%-scripts
+# meta-target.
+#
+# To add a new DOS environment just do what is described for adding a new
+# unix environment, and then make certain that the fix-msdos-%-scripts target
+# performs the correct function for the new environment.
+msdos-cf = OS=msdos
+win95-cf = OS=win95
+winnt-cf = OS=winnt
+
+msdos-borland-tcc20swp-scripts-flags = $(msdos-cf) OSRELEASE=borland OSENVIRONMENT=tcc20
+msdos-borland-bcc30-scripts-flags = $(msdos-cf) OSRELEASE=borland OSENVIRONMENT=bcc30 SWAP=n
+msdos-borland-bcc30swp-scripts-flags = $(msdos-cf) OSRELEASE=borland OSENVIRONMENT=bcc30
+msdos-borland-bcc40swp-scripts-flags = $(msdos-cf) OSRELEASE=borland OSENVIRONMENT=bcc40
+msdos-borland-bcc45swp-scripts-flags = $(msdos-cf) OSRELEASE=borland OSENVIRONMENT=bcc45
+msdos-borland-bcc50swp-scripts-flags = $(msdos-cf) OSRELEASE=borland OSENVIRONMENT=bcc50
+msdos-borland-bcc32-scripts-flags = $(msdos-cf) OSRELEASE=borland OSENVIRONMENT=bcc32 SWAP=n
+msdos-microsft-msc51-scripts-flags= $(msdos-cf) OSRELEASE=microsft SWAP=n MSC_VER=5.1 OSENVIRONMENT=msc51
+msdos-microsft-msc51swp-scripts-flags = $(msdos-cf) OSRELEASE=microsft MSC_VER=5.1 OSENVIRONMENT=msc51
+msdos-microsft-msc60-scripts-flags= $(msdos-cf) OSRELEASE=microsft SWAP=n MSC_VER=6.0 OSENVIRONMENT=msc60
+msdos-microsft-msc60swp-scripts-flags = $(msdos-cf) OSRELEASE=microsft MSC_VER=6.0 OSENVIRONMENT=msc60
+msdos-zortech-scripts-flags= $(msdos-cf) OSRELEASE=zortech SWAP=n OSENVIRONMENT=
+msdos-zortechswp-scripts-flags= $(msdos-cf) OSRELEASE=zortech OSENVIRONMENT=
+win95-borland-bcc50-scripts-flags = $(win95-cf) OSRELEASE=borland OSENVIRONMENT=bcc50 SWAP=n
+win95-microsft-vpp40-scripts-flags = $(win95-cf) OSRELEASE=microsft OSENVIRONMENT=vpp40 SWAP=n
+
+winnt-borland-bcc50-scripts-flags = $(winnt-cf) OSRELEASE=borland OSENVIRONMENT=bcc50 SWAP=n
+winnt-microsft-vpp40-scripts-flags = $(winnt-cf) OSRELEASE=microsft OSENVIRONMENT=vpp40 SWAP=n
+
+
+msdos-scripts: clean\
+ msdos-borland-turbo-scripts\
+ msdos-borland-c++-scripts\
+ msdos-microsoft-scripts;
+
+win95-scripts: clean\
+ win95-borland-c++-scripts\
+ win95-microsft-vc++-scripts;
+
+winnt-scripts: clean\
+ winnt-borland-c++-scripts\
+ winnt-microsft-vc++-scripts;
+
+msdos-borland-turbo-scripts .SWAP :
+ $(MAKECMD) SCRIPTFILE=mkswp.bat msdos-borland-tcc20swp-scripts
+
+msdos-borland-c++-scripts .SWAP :! 30 40 45 50
+ $(MAKECMD) SCRIPTFILE=mkswp.bat msdos-borland-bcc$?swp-scripts
+
+msdos-microsoft-scripts .SWAP :! 51 60
+ $(MAKECMD) SCRIPTFILE=mk.bat msdos-microsft-msc$?-scripts
+ $(MAKECMD) SCRIPTFILE=mkswp.bat msdos-microsft-msc$?swp-scripts
+
+msdos-zortech-scripts .SWAP :
+ $(MAKECMD) SCRIPTFILE=mk.bat msdos-zortech-scripts
+ $(MAKECMD) SCRIPTFILE=mkswp.bat msdos-zortechswp-scripts
+
+win95-borland-c++-scripts .SWAP :! 50
+ $(MAKECMD) SCRIPTFILE=mk.bat win95-borland-bcc$?-scripts
+
+win95-microsft-vc++-scripts .SWAP :! 40
+ $(MAKECMD) SCRIPTFILE=mk.bat win95-microsft-vpp$?-scripts
+
+winnt-borland-c++-scripts .SWAP :! 50
+ $(MAKECMD) SCRIPTFILE=mk.cmd winnt-borland-bcc$?-scripts
+
+winnt-microsft-vc++-scripts .SWAP :! 40
+ $(MAKECMD) SCRIPTFILE=mk.cmd winnt-microsft-vpp$?-scripts
+
+msdos-%-scripts .SWAP .SILENT:
+ $(MAKECMD) -su $($@-flags) .KEEP_STATE:= $(FS) public template.mk
+ $(MAKECMD) -ns DIRSEPSTR:=$(DIRSEPSTR) SHELL=command.com COMSPEC=command.com .KEEP_STATE:= $(MS) $($@-flags) >$(SH)
+ $(MAKECMD) -s $(MAKEMACROS) $(MS) $($@-flags) $(SET-TMP) fix-msdos-$*-scripts
+
+win95-borland-%-scripts .SWAP .SILENT:
+ $(MAKECMD) -u $($@-flags) .KEEP_STATE:= $(FS) public template.mk
+ $(MAKECMD) -n DIRSEPSTR:=$(DIRSEPSTR) SHELL=command.com COMSPEC=command.com .KEEP_STATE:= $(MS) $($@-flags) >$(SH)
+ $(MAKECMD) -s $(MAKEMACROS) $(MS) $($@-flags) $(SET-TMP) fix-win95-borland-$*-scripts
+
+win95-microsft-%-scripts .SWAP .SILENT:
+ $(MAKECMD) -su $($@-flags) .KEEP_STATE:= $(FS) public template.mk
+ $(MAKECMD) -ns DIRSEPSTR:=$(DIRSEPSTR) SHELL=command.com COMSPEC=command.com .KEEP_STATE:= $(MS) $($@-flags) >$(SH)
+ $(MAKECMD) -s $(MAKEMACROS) $(MS) $($@-flags) $(SET-TMP) fix95nt-win95-microsft-$*-scripts
+
+winnt-borland-%-scripts .SWAP .SILENT:
+ $(MAKECMD) -su $($@-flags) .KEEP_STATE:= $(FS) public template.mk
+ $(MAKECMD) -ns DIRSEPSTR:=$(DIRSEPSTR) SHELL=cmd.exe COMSPEC=cmd.exe .KEEP_STATE:= $(MS) $($@-flags) >$(SH)
+ $(MAKECMD) -s $(MAKEMACROS) $(MS) $($@-flags) $(SET-TMP) fix-winnt-borland-$*-scripts
+
+winnt-microsft-%-scripts .SWAP .SILENT:
+ $(MAKECMD) -su $($@-flags) .KEEP_STATE:= $(FS) public template.mk
+ $(MAKECMD) -ns DIRSEPSTR:=$(DIRSEPSTR) SHELL=cmd.exe COMSPEC=cmd.exe .KEEP_STATE:= $(MS) $($@-flags) >$(SH)
+ $(MAKECMD) -s $(MAKEMACROS) $(MS) $($@-flags) $(SET-TMP) fix95nt-winnt-microsft-$*-scripts
+
+
+# We make the standard OS/2 scripts here, but we have to go and fix up the
+# mkXX.cmd file since it contains names of temporary files for the response
+# files required by the linker. We need to also construct the response file
+# contents. These two functions are performed by the fix-msdos-%-scripts
+# meta-target.
+#
+# To add a new OS/2 environment just do what is described for adding a new
+# unix environment, and then make certain that the fix-msdos-%-scripts target
+# performs the correct function for the new environment.
+os2-cf = OS=os2
+os2-ibm-icc-scripts-flags= $(os2-cf) OSRELEASE=ibm OSENVIRONMENT=icc
+
+os2-scripts: clean os2-ibm-scripts;
+
+os2-ibm-scripts .SWAP :! icc
+ $(MAKECMD) SCRIPTFILE=mk.cmd os2-ibm-$?-scripts
+
+os2-%-scripts .SWAP :
+ $(MAKECMD) -su $($@-flags) .KEEP_STATE:= $(FS) public template.mk
+ $(MAKECMD) -ns DIRSEPSTR:=$(DIRSEPSTR) SHELL=cmd.exe COMSPEC=cmd.exe .KEEP_STATE:= $(MS) SWITCHAR:=- $($@-flags) >$(SH)
+ $(MAKECMD) -s $(MAKEMACROS) $(MS) $($@-flags) $(SET-TMP) fix-os2-$*-scripts
+ cat $(SH) | sed -e 's, -, /,g' >tmp-out
+ mv tmp-out $(SH)
+
+# Signify NULL targets for the various Compiler versions.
+icc 30 40 45 50 51 60 .PHONY:;
+
+# Go over the created script file and make sure all the '/' that are in
+# filenames are '\', and make sure the final link command line looks
+# reasonable.
+MAPOBJ = obj$(SWAP:s/y/swp/:s/n//).rsp
+MAPLIB = lib$(SWAP:s/y/swp/:s/n//).rsp
+OBJRSP = $(SH:s,fix/,,:s,${SCRIPTFILE},${MAPOBJ},)
+LIBRSP = $(SH:s,fix/,,:s,${SCRIPTFILE},${MAPLIB},)
+OBJRSP95 = $(SH:s,fix95nt/,,:s,${SCRIPTFILE},${MAPOBJ},)
+LIBRSP95 = $(SH:s,fix95nt/,,:s,${SCRIPTFILE},${MAPLIB},)
+DOSOBJ = $(CSTARTUP) $(OBJDIR)/{$(OBJECTS)}
+
+# Use group recipes, as SHELL has an invalid value in some platform instances.
+fix-%-scripts .GROUP:
+ tac $(FIX-SH) >tmp-sh-r
+ tail +3 tmp-sh-r | sed -e 's,/,\\,g' >tmp-out
+ tac tmp-out|\
+ sed -e 's,\\nologo,/nologo,g' >$(FIX-SH)
+ head -2 tmp-sh-r |\
+ sed -e 's,\\tmp\\mkA[a-zA-Z0-9]*,$(OBJRSP:s,/,\\),'\
+ -e 's,\\tmp\\mkB[a-zA-Z0-9]*,$(LIBRSP:s,/,\\),'\
+ -e 's,\\tmp\\mk[0-9]*a[a-z]*,$(OBJRSP:s,/,\\),'\
+ -e 's,\\tmp\\mk[0-9]*b[a-z]*,$(LIBRSP:s,/,\\),'\
+ -e 's,/,\\,g'\
+ -e 's,\\nologo,/nologo,g'\
+ -e 's,-,/,g' |\
+ tac >>$(FIX-SH)
+ rm -f tmp-sh-r tmp-out
+ mv <+$(DOSOBJ:s,/,\\,:t"+\n")\n+> $(OBJRSP)
+ mv <+$(LDLIBS:s,/,\\,:t"+\n")\n+> $(LIBRSP)
+
+# Use group recipes, as SHELL has an invalid value in some platform instances.
+fix95nt-%-scripts .GROUP:
+ tac $(FIX95-SH) >tmp-sh-r
+ tail +3 tmp-sh-r | sed -e 's,/,\\,g' >tmp-out
+ tac tmp-out|\
+ sed -e 's,\\nologo,/nologo,g' >$(FIX95-SH)
+ head -2 tmp-sh-r |\
+ sed -e 's,\\tmp\\mkA[a-zA-Z0-9]*,$(OBJRSP95:s,/,\\),'\
+ -e 's,\\tmp\\mkB[a-zA-Z0-9]*,$(LIBRSP95:s,/,\\),'\
+ -e 's,\\tmp\\mk[0-9]*a[a-z]*,$(OBJRSP95:s,/,\\),'\
+ -e 's,\\tmp\\mk[0-9]*b[a-z]*,$(LIBRSP95:s,/,\\),'\
+ -e 's,/,\\,g'\
+ -e 's,\\nologo,/nologo,g'\
+ -e 's,-,/,g' |\
+ tac >>$(FIX95-SH)
+ rm -f tmp-sh-r tmp-out
+ mv <+$(DOSOBJ:s,/,\\,:t"\n")\n+> $(OBJRSP95)
+ mv <+$(LDLIBS:s,/,\\,:t"\n")\n+> $(LIBRSP95)
diff --git a/dmake/man/dmake.nc b/dmake/man/dmake.nc
new file mode 100644
index 000000000000..ea3c579a2881
--- /dev/null
+++ b/dmake/man/dmake.nc
@@ -0,0 +1,3696 @@
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+NAME
+ dmake - maintain program groups, or interdependent files
+
+SYNOPSIS
+ dmake [-P#] [-{f|C|K} file] [-{w|W} target ...]
+ [macro[[!][*][+][:]]=value ...] [-v{cdfimtw}]
+ [-ABcdeEghiknpqrsStTuVxX] [target ...]
+
+DESCRIPTION
+ dmake is a re-implementation of the UNIX Make utility with
+ significant enhancements. dmake executes commands found
+ in an external file called a makefile to update one or
+ more target names. Each target may depend on zero or more
+ prerequisite targets. If any of the target's prerequi-
+ sites is newer than the target or if the target itself
+ does not exist, then dmake will attempt to make the tar-
+ get.
+
+ If no -f command line option is present then dmake
+ searches for an existing makefile from the list of prereq-
+ uisites specified for the special target .MAKEFILES (see
+ the STARTUP section for more details). If "-" is the name
+ of the file specified to the -f flag then dmake uses stan-
+ dard input as the source of the makefile text.
+
+ Any macro definitions (arguments with embedded "=" signs)
+ that appear on the command line are processed first and
+ supercede definitions for macros of the same name found
+ within the makefile. In general it is impossible for def-
+ initions found inside the makefile to redefine a macro
+ defined on the command line, see the MACROS section for
+ exceptions.
+
+ If no target names are specified on the command line, then
+ dmake uses the first non-special target found in the make-
+ file as the default target. See the SPECIAL TARGETS sec-
+ tion for the list of special targets and their function.
+ Makefiles written for most previous versions of Make will
+ be handled correctly by dmake. Known differences between
+ dmake and other versions of make are discussed in the COM-
+ PATIBILITY section found at the end of this document.
+ dmake returns 0 if no errors were detected and a non-zero
+ result if an error occurred.
+
+OPTIONS
+ -A Enable AUGMAKE special inference rule transforma-
+ tions (see the "PERCENT(%) RULES" section), these
+ are set to off by default.
+
+ -B Enable the use of spaces instead of <tabs> to begin
+ recipe lines. This flag equivalent to the .NOTABS
+ special macro and is further described below.
+
+ -c Use non-standard comment stripping. If you specify
+
+
+
+Version 4.01 PL0 UW 1
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ -c then dmake will treat any # character as a start
+ of comment character wherever it may appear unless
+ it is escaped by a \.
+
+ -C [+]file
+ This option writes to file a copy of standard out-
+ put and standard error from any child processes and
+ from the dmake process itself. If you specify a +
+ prior to the file name then the text is appended to
+ the previous contents of file. This option is
+ active in the MSDOS implementation only and is
+ ignored by non-MSDOS versions of dmake.
+
+ -d Disable the use of the directory cache. Normally
+ dmake caches directories as it checks file times-
+ tamps. Giving this flag is equivalent to the
+ .DIRCACHE attribute or macro being set to no.
+
+ -E Read the environment and define all strings of the
+ form 'ENV-VAR=evalue' defined within as macros
+ whose name is ENV-VAR, and whose value is 'evalue'.
+ The environment is processed prior to processing
+ the user specified makefile thereby allowing defi-
+ nitions in the makefile to override definitions in
+ the environment.
+
+ -e Same as -E, except that the environment is pro-
+ cessed after the user specified makefile has been
+ processed (thus definitions in the environment
+ override definitions in the makefile). The -e and
+ -E options are mutually exclusive. If both are
+ given the latter takes effect.
+
+ -f file
+ Use file as the source for the makefile text. Only
+ one -f option is allowed.
+
+ -g Globally disable group recipe parsing, equivalent
+ to the .IGNOREGROUP attribute or macro being set to
+ yes at the start of the makefile.
+
+ -h Print the command summary for dmake.
+
+ -i Tells dmake to ignore errors, and continue making
+ other targets. This is equivalent to the .IGNORE
+ attribute or macro.
+
+ -K file
+ Turns on .KEEP_STATE state tracking and tells dmake
+ to use file as the state file.
+
+ -k Causes dmake to ignore errors caused by command
+ execution and to make all targets not depending on
+ targets that could not be made. Ordinarily dmake
+
+
+
+Version 4.01 PL0 UW 2
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ stops after a command returns a non-zero status,
+ specifying -k causes dmake to ignore the error and
+ continue to make as much as possible.
+
+ -n Causes dmake to print out what it would have exe-
+ cuted, but does not actually execute the commands.
+ A special check is made for the string "$(MAKE)"
+ inside a recipe line, if it is found, the line is
+ expanded and invoked, thereby enabling recursive
+ makes to give a full description of all that they
+ will do. This check is disabled inside group
+ recipes.
+
+ -p Print out a version of the digested makefile in
+ human readable form. (useful for debugging, but
+ cannot be re-read by dmake)
+
+ -P# On systems that support multi-processing cause
+ dmake to use # concurrent child processes to make
+ targets. See the "MULTI PROCESSING" section for
+ more information.
+
+ -q Check and see if the target is up to date. Exits
+ with code 0 if up to date, 1 otherwise.
+
+ -r Tells dmake not to read the initial startup make-
+ file, see STARTUP section for more details.
+
+ -s Tells dmake to do all its work silently and not
+ echo the commands it is executing to stdout (also
+ suppresses warnings). This is equivalent to the
+ .SILENT attribute or macro.
+
+ -S Force sequential execution of recipes on architec-
+ tures which support concurrent makes. For backward
+ compatibility with old makefiles that have nasty
+ side-effect prerequisite dependencies.
+
+ -t Causes dmake to touch the targets and bring them up
+ to date without executing any commands. Note that
+ targets will not be created if they do not already
+ exist.
+
+ -T Tells dmake to not perform transitive closure on
+ the inference graph.
+
+ -u Force an unconditional update. (ie. do everything
+ that would be done if everything that a target
+ depended on was out of date)
+
+ -v[dfimtw]
+ Verbose flag, when making targets print to stdout
+ what we are going to make and what we think its
+ time stamp is. The optional flags [dfimt] can be
+
+
+
+Version 4.01 PL0 UW 3
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ used to restrict the information that is displayed.
+ In the absence of any optional flags all are
+ assumed to be given (ie. -v is equivalent to
+ -vdfimt). The meanings of the optional flags are:
+
+ c Notify of directory cache operations only.
+
+ d Notify of change directory operations only.
+
+ f Notify of file I/O operations only.
+
+ i Notify of inference algorithm operation
+ only.
+
+ m Notify of target update operations only.
+
+ t Keep any temporary files created; normally
+ they are automatically deleted.
+
+ w Notify of non-essential warnings (these are
+ historical).
+
+ -V Print the version of dmake, and values of builtin
+ macros.
+
+ -W target
+ Run dmake pretending that target is out of date.
+
+ -w target
+ What if? Show what would be made if target were out
+ of date.
+
+ -x Upon processing the user makefile export all non-
+ internally defined macros to the user's environ-
+ ment. This option together with the -e option
+ allows SYSV AUGMAKE recursive makes to function as
+ expected.
+
+ -X Inhibit the execution of #! lines found at the
+ beginning of a makefile. The use of this flag pre-
+ vents non-termination of recursive make invoca-
+ tions.
+
+INDEX
+ Here is a list of the sections that follow and a short
+ description of each. Perhaps you won't have to read the
+ entire man page to find what you need.
+
+ STARTUP Describes dmake initialization.
+
+ SYNTAX Describes the syntax of makefile
+ expressions.
+
+ ATTRIBUTES Describes the notion of attributes and
+
+
+
+Version 4.01 PL0 UW 4
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ how they are used when making targets.
+
+ MACROS Defining and expanding macros.
+
+ RULES AND TARGETS How to define targets and their prereq-
+ uisites.
+
+ RECIPES How to tell dmake how to make a target.
+
+ TEXT DIVERSIONS How to use text diversions in recipes
+ and macro expansions.
+
+ SPECIAL TARGETS Some targets are special.
+
+ SPECIAL MACROS Macros used by dmake to alter the pro-
+ cessing of the makefile, and those
+ defined by dmake for the user.
+
+ CONTROL MACROS Itemized list of special control
+ macros.
+
+ RUNTIME MACROS Discussion of special run-time macros
+ such as $@ and $<.
+
+ FUNCTION MACROS GNU style function macros, only $(mktmp
+ ...) for now.
+
+ CONDITIONAL MACROS Target specific conditional macros.
+
+ DYNAMIC PREREQUISITES
+ Processing of prerequisites which con-
+ tain macro expansions in their name.
+
+ BINDING TARGETS The rules that dmake uses to bind a
+ target to an existing file in the file
+ system.
+
+ PERCENT(%) RULES Specification of recipes to be used by
+ the inference algorithm.
+
+ MAKING INFERENCES The rules that dmake uses when infer-
+ ring how to make a target which has no
+ explicit recipe. This and the previous
+ section are really a single section in
+ the text.
+
+ MAKING TARGETS How dmake makes targets other than
+ libraries.
+
+ MAKING LIBRARIES How dmake makes libraries.
+
+ KEEP STATE A discussion of how .KEEP_STATE works.
+
+ MULTI PROCESSING Discussion of dmake's parallel make
+
+
+
+Version 4.01 PL0 UW 5
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ facilities for architectures that sup-
+ port them.
+
+ CONDITIONALS Conditional expressions which control
+ the processing of the makefile.
+
+ EXAMPLES Some hopefully useful examples.
+
+ COMPATIBILITY How dmake compares with previous ver-
+ sions of make.
+
+ LIMITS Limitations of dmake.
+
+ PORTABILITY Comments on writing portable makefiles.
+
+ FILES Files used by dmake.
+
+ SEE ALSO Other related programs, and man pages.
+
+ AUTHOR The guy responsible for this thing.
+
+ BUGS Hope not.
+
+STARTUP
+ When dmake begins execution it first processes the command
+ line and then processes an initial startup-makefile. This
+ is followed by an attempt to locate and process a user
+ supplied makefile. The startup file defines the default
+ values of all required control macros and the set of
+ default rules for making targets and inferences. When
+ searching for the startup makefile, dmake searches the
+ following locations, in the order specified, until a
+ startup file is located:
+
+
+ 1. The location given as the value of the macro
+ MAKESTARTUP defined on the command line.
+
+ 2. The location given as the value of the envi-
+ ronment variable MAKESTARTUP defined in the
+ current environment.
+
+ 3. The location given as the value of the macro
+ MAKESTARTUP defined internally within dmake.
+
+ The above search is disabled by specifying the -r option
+ on the command line. An error is issued if a startup
+ makefile cannot be found and the -r option was not speci-
+ fied. A user may substitute a custom startup file by
+ defining the MAKESTARTUP environment variable or by
+ redefining the MAKESTARTUP macro on the command line. To
+ determine where dmake looks for the default startup file,
+ check your environment or issue the command "dmake -V".
+
+
+
+
+Version 4.01 PL0 UW 6
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ A similar search is performed to locate a default user
+ makefile when no -f command line option is specified. By
+ default, the prerequisite list of the special target
+ .MAKEFILES specifies the names of possible makefiles and
+ the search order that dmake should use to determine if one
+ exists. A typical definition for this target is:
+
+ .MAKEFILES : makefile.mk Makefile makefile
+
+ dmake will first look for makefile.mk and then the others.
+ If a prerequisite cannot be found dmake will try to make
+ it before going on to the next prerequisite. For example,
+ makefile.mk can be checked out of an RCS file if the
+ proper rules for doing so are defined in the startup file.
+
+ If the first line of the user makefile is of the form:
+
+
+ then dmake will expand and run the command prior to read-
+ ing any additional input. If the return code of the com-
+ mand is zero then dmake will continue on to process the
+ remainder of the user makefile, if the return code is non-
+ zero then dmake will exit.
+
+ dmake builds the internal dependency graph as it parses a
+ user specified makefile. The graph is rooted at the spe-
+ cial target .ROOT. .ROOT is the top level target that
+ dmake builds when it starts to build targets. All user
+ specified targets (those from the command line or taken as
+ defaults from the makefile) are made prerequisites of the
+ special target .TARGETS. dmake by default creates the
+ relationship that .ROOT depends on .TARGETS and as a
+ result everything is made. This approach allows the user
+ to customize, within their makefile, the order and which,
+ target, is built first. For example the default makefiles
+ come with settings for .ROOT that specify:
+
+ .ROOT .PHONY .NOSTATE .SEQUENTIAL : .INIT .TARGETS
+ .DONE
+
+ with .INIT and .DONE defined as:
+
+ .INIT .DONE .PHONY:;
+
+ which nicely emulates the behaviour of Sun's make exten-
+ sions. The building of .ROOT's prerequisites is always
+ forced to be sequential. However, this definition is
+ trivially chaned by supplying the definition:
+
+ .ROOT : .TARGETS
+
+ which skips the preamble and postamble phases of building
+ .TARGETS.
+
+
+
+
+Version 4.01 PL0 UW 7
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+SYNTAX
+ This section is a summary of the syntax of makefile state-
+ ments. The description is given in a style similar to
+ BNF, where { } enclose items that may appear zero or more
+ times, and [ ] enclose items that are optional. Alterna-
+ tive productions for a left hand side are indicated by
+ '->', and newlines are significant. All symbols in bold
+ type are text or names representing text supplied by the
+ user.
+
+
+
+ Makefile -> { Statement }
+
+ Statement -> Macro-Definition
+ -> Conditional-Macro-Definition
+ -> Conditional
+ -> Rule-Definition
+ -> Attribute-Definition
+
+ Macro-Definition -> MACRO = LINE
+ -> MACRO [!]*= LINE
+ -> MACRO [!]:= LINE
+ -> MACRO [!]*:= LINE
+ -> MACRO [!]+= LINE
+ -> MACRO [!]+:= LINE
+
+ Conditional-Macro-Definition -> TARGET ?= Macro-Definition
+
+ Conditional -> .IF expression
+ Makefile
+ [ .ELIF expression
+ Makefile ]
+ [ .ELSE
+ Makefile ]
+ .END
+
+ expression -> LINE
+ -> STRING == LINE
+ -> STRING != LINE
+
+ Rule-Definition -> target-definition
+ [ recipe ]
+
+ target-definition -> targets [attrs] op { PREREQUISITE } [; rcp-line]
+
+ targets -> target { targets }
+ -> "target" { targets }
+
+ target -> special-target
+ -> TARGET
+
+ attrs -> attribute { attrs }
+ -> "attribute" { attrs }
+
+
+
+Version 4.01 PL0 UW 8
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ op -> : { modifier }
+
+ modifier -> :
+ -> ^
+ -> !
+ -> -
+ -> |
+
+ recipe -> { TAB rcp-line }
+ -> [@][%][-] [
+ { LINE }
+ ]
+
+ rcp-line -> [@][%][-][+] LINE
+
+ Attribute-Definition -> attrs : targets
+
+ attribute -> .EPILOG
+ -> .ERRREMOVE
+ -> .EXECUTE
+ -> .GROUP
+ -> .IGNORE
+ -> .IGNOREGROUP
+ -> .LIBRARY
+ -> .MKSARGS
+ -> .NOINFER
+ -> .NOSTATE
+ -> .PHONY
+ -> .PRECIOUS
+ -> .PROLOG
+ -> .SETDIR=path
+ -> .SILENT
+ -> .SEQUENTIAL
+ -> .SWAP
+ -> .USESHELL
+ -> .SYMBOL
+ -> .UPDATEALL
+
+ special-target -> .ERROR
+ -> .EXIT
+ -> .EXPORT
+ -> .GROUPEPILOG
+ -> .GROUPPROLOG
+ -> .IMPORT
+ -> .INCLUDE
+ -> .INCLUDEDIRS
+ -> .MAKEFILES
+ -> .REMOVE
+ -> .SOURCE
+ -> .SOURCE.suffix
+ -> .suffix1.suffix2
+
+
+ Where, TAB represents a <tab> character, STRING represents
+
+
+
+Version 4.01 PL0 UW 9
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ an arbitrary sequence of characters, and LINE represents a
+ possibly empty sequence of characters terminated by a non-
+ escaped (not immediately preceded by a backslash '\') new-
+ line character. MACRO, PREREQUISITE, and TARGET each rep-
+ resent a string of characters not including space or tab
+ which respectively form the name of a macro, prerequisite
+ or target. The name may itself be a macro expansion
+ expression. A LINE can be continued over several physical
+ lines by terminating it with a single backslash character.
+ Comments are initiated by the pound # character and extend
+ to the end of line. All comment text is discarded, a '#'
+ may be placed into the makefile text by escaping it with
+ '\' (ie. \# translates to # when it is parsed). An excep-
+ tion to this occurs when a # is seen inside a recipe line
+ that begins with a <tab> or is inside a group recipe. If
+ you specify the -c command line switch then this behavior
+ is disabled and dmake will treat all # characters as start
+ of comment indicators unless they are escaped by \. A set
+ of continued lines may be commented out by placing a sin-
+ gle # at the start of the first line. A continued line
+ cannot span more than one makefile.
+
+ white space is defined to be any combination of <space>,
+ <tab>, and the sequence \<nl> when \<nl> is used to termi-
+ nate a LINE. When processing macro definition lines, any
+ amount of white space is allowed on either side of the
+ macro operator and white space is stripped from both
+ before and after the macro value string. The sequence
+ \<nl> is treated as white space during recipe expansion
+ and is deleted from the final recipe string. You must
+ escape the \<nl> with another \ in order to get a \ at the
+ end of a recipe line. The \<nl> sequence is deleted from
+ macro values when they are expanded.
+
+ When processing target definition lines, the recipe for a
+ target must, in general, follow the first definition of
+ the target (See the RULES AND TARGETS section for an
+ exception), and the recipe may not span across multiple
+ makefiles. Any targets and prerequisites found on a tar-
+ get definition line are taken to be white space separated
+ tokens. The rule operator (op in SYNTAX section) is also
+ considered to be a token but does not require white space
+ to precede or follow it. Since the rule operator begins
+ with a `:', traditional versions of make do not allow the
+ `:' character to form a valid target name. dmake allows
+ `:' to be present in target/prerequisite names as long as
+ the entire target/prerequisite name is quoted. For exam-
+ ple:
+
+ a:fred : test
+
+ would be parsed as TARGET = a, PREREQUISITES={fred, :,
+ test}, which is not what was intended. To fix this you
+ must write:
+
+
+
+Version 4.01 PL0 UW 10
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ "a:fred" : test
+
+ Which will be parsed as expected. Quoted target and pre-
+ requisite specifications may also contain white space
+ thereby allowing the use of complex function macro expres-
+ sions.. See the EXAMPLES section for how to apply " quot-
+ ing to a list of targets.
+
+ATTRIBUTES
+ dmake defines several target attributes. Attributes may
+ be assigned to a single target, a group of targets, or to
+ all targets in the makefile. Attributes are used to mod-
+ ify dmake actions during target update. The recognized
+ attributes are:
+
+
+ .EPILOG Insert shell epilog code when executing a
+ group recipe associated with any target having
+ this attribute set.
+
+ .ERRREMOVE Always remove any target having this attribute
+ if an error is encountered while making them.
+ Setting this attribute overrides the .PRECIOUS
+ attribute.
+
+ .EXECUTE If the -n flag was given then execute the
+ recipe associated with any target having this
+ attribute set.
+
+ .FIRST Used in conjunction with .INCLUDE. Terminates
+ the inclusion with the first successfully
+ included prerequisite.
+
+ .GROUP Force execution of a target's recipe as a
+ group recipe.
+
+ .IGNORE Ignore an error when trying to make any target
+ with this attribute set.
+
+ .IGNOREGROUP
+ Disable the special meaning of '[' to initiate
+ a group recipe.
+
+ .LIBRARY Target is a library.
+
+ .MKSARGS If running in an MSDOS environment then use
+ MKS extended argument passing conventions to
+ pass arguments to commands. Non-MSDOS envi-
+ ronments ignore this attribute.
+
+ .NOINFER Any target with this attribute set will not be
+ subjected to transitive closure if it is
+ inferred as a prerequisite of a target whose
+ recipe and prerequisites are being inferred.
+
+
+
+Version 4.01 PL0 UW 11
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ (i.e. the inference algorithm will not use any
+ prerequisite with this attribute set, as a
+ target) If specified as '.NOINFER:' (ie. with
+ no prerequisites or targets) then the effect
+ is equivalent to specifying -T on the command
+ line.
+
+ .NOSTATE Any target with this attribute set will not
+ have command line flag information stored in
+ the state file if .KEEP_STATE has been
+ enabled.
+
+ .PHONY Any target with this attribute set will have
+ its recipe executed each time the target is
+ made even if a file matching the target name
+ can be located. Any targets that have a
+ .PHONY attributed target as a prerequisite
+ will be made each time the .PHONY attributed
+ prerequisite is made.
+
+ .PRECIOUS Do not remove associated target under any cir-
+ cumstances. Set by default for any targets
+ whose corresponding files exist in the file
+ system prior to the execution of dmake.
+
+ .PROLOG Insert shell prolog code when executing a
+ group recipe associated with any target having
+ this attribute set.
+
+ .SEQUENTIAL Force a sequential make of the associated tar-
+ get's prerequisites.
+
+ .SETDIR Change current working directory to specified
+ directory when making the associated target.
+ You must specify the directory at the time the
+ attribute is specified. To do this simply
+ give .SETDIR=path as the attribute. path is
+ expanded and the result is used as the value
+ of the directory to change to. If path con-
+ tains $$@ then the name of the target to be
+ built is used in computing the path to change
+ directory to. If path is surrounded by single
+ quotes then path is not expanded, and is used
+ literally as the directory name. If the path
+ contains any `:' characters then the entire
+ attribute string must be quoted using ". If a
+ target having this attribute set also has the
+ .IGNORE attribute set then if the change to
+ the specified directory fails it will be
+ ignored, and no error message will be issued.
+
+ .SILENT Do not echo the recipe lines when making any
+ target with this attribute set, and do not
+ issue any warnings.
+
+
+
+Version 4.01 PL0 UW 12
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ .SWAP Under MSDOS when making a target with this
+ attribute set swap the dmake executable to
+ disk prior to executing the recipe line. Also
+ see the '%' recipe line flag defined in the
+ RECIPES section.
+
+ .SYMBOL Target is a library member and is an entry
+ point into a module in the library. This
+ attribute is used only when searching a
+ library for a target. Targets of the form
+ lib((entry)) have this attribute set automati-
+ cally.
+
+ .USESHELL Force each recipe line of a target to be exe-
+ cuted using a shell. Specifying this
+ attribute is equivalent to specifying the '+'
+ character at the start of each line of a non-
+ group recipe.
+
+ .UPDATEALL Indicates that all the targets listed in this
+ rule are updated by the execution of the
+ accompanying recipe. A common example is the
+ production of the y.tab.c and y.tab.h files by
+ yacc when it is run on a grammar. Specifying
+ .UPDATEALL in such a rule prevents the running
+ of yacc twice, once for the y.tab.c file and
+ once for the y.tab.h file. .UPDATEALL targets
+ that are specified in a single rule are
+ treated as a single target and all timestamps
+ are updated whenever any target in the set is
+ made. As a side-effect, dmake internally
+ sorts such targets in ascending alphabetical
+ order and the value of $@ is always the first
+ target in the sorted set.
+
+ All attributes are user setable and except for .UPDATEALL,
+ .SETDIR and .MKSARGS may be used in one of two forms. The
+ .MKSARGS attribute is restricted to use as a global
+ attribute, and the use of the .UPDATEALL and .SETDIR
+ attributes is restricted to rules of the second form only.
+
+ ATTRIBUTE_LIST : targets
+
+ assigns the attributes specified by ATTRIBUTE_LIST to each
+ target in targets or
+
+ targets ATTRIBUTE_LIST : ...
+
+ assigns the attributes specified by ATTRIBUTE_LIST to each
+ target in targets. In the first form if targets is empty
+ (ie. a NULL list), then the list of attributes will apply
+ to all targets in the makefile (this is equivalent to the
+ common Make construct of ".IGNORE :" but has been modified
+ to the notion of an attribute instead of a special
+
+
+
+Version 4.01 PL0 UW 13
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ target). Not all of the attributes have global meaning.
+ In particular, .LIBRARY, .NOSTATE, .PHONY, .SETDIR, .SYM-
+ BOL and .UPDATEALL have no assigned global meaning.
+
+ Any attribute may be used with any target, even with the
+ special targets. Some combinations are useless (e.g.
+ .INCLUDE .PRECIOUS: ... ), while others are useful (e.g.
+ .INCLUDE .IGNORE : "file.mk" will not complain if file.mk
+ cannot be found using the include file search rules, see
+ the section on SPECIAL TARGETS for a description of
+ .INCLUDE). If a specified attribute will not be used with
+ the special target a warning is issued and the attribute
+ is ignored.
+
+MACROS
+ dmake supports six forms of macro assignment.
+
+
+ MACRO = LINE This is the most common and familiar form
+ of macro assignment. It assigns LINE lit-
+ erally as the value of MACRO. Future
+ expansions of MACRO recursively expand its
+ value.
+
+ MACRO *= LINE This form behaves exactly as the simple
+ '=' form with the exception that if MACRO
+ already has a value then the assignment is
+ not performed.
+
+ MACRO := LINE This form differs from the simple '=' form
+ in that it expands LINE prior to assigning
+ it as the value of MACRO. Future expan-
+ sions of MACRO do not recursively expand
+ its value.
+
+ MACRO *:= LINE This form behaves exactly as the ':=' form
+ with the exception that if MACRO already
+ has a value then the assignment and expan-
+ sion are not performed.
+
+ MACRO += LINE This form of macro assignment allows macro
+ values to grow. It takes the literal
+ value of LINE and appends it to the previ-
+ ous value of MACRO separating the two by a
+ single space. Future expansions of MACRO
+ recursively expand its value.
+
+ MACRO +:= LINE This form is similar to the '+=' form
+ except that the value of LINE is expanded
+ prior to being added to the value of
+ MACRO.
+
+ Macro expressions specified on the command line allow the
+ macro value to be redefined within the makefile only if
+
+
+
+Version 4.01 PL0 UW 14
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ the macro is defined using the '+=' and '+:=' operators.
+ Other operators will define a macro that cannot be further
+ modified.
+
+ Each of the preceeding macro assignment operators may be
+ prefixed by ! to indicate that the assignment should be
+ forced and that no warnings should be issued. Thus, spec-
+ ifying ! has the effect of silently forcing the specified
+ macro assignment.
+
+ When dmake defines a non-environment macro it strips lead-
+ ing and trailing white space from the macro value. Macros
+ imported from the environment via either the .IMPORT spe-
+ cial target (see the SPECIAL TARGETS section), or the -e,
+ or -E flags are an exception to this rule. Their values
+ are always taken literally and white space is never
+ stripped. In addition, named macros defined using the
+ .IMPORT special target do not have their values expanded
+ when they are used within a makefile. In contrast, envi-
+ ronment macros that are imported due to the specification
+ of the -e or -E flags are subject to expansion when used.
+
+ To specify a macro expansion enclose the name in () or {}
+ and precede it with a dollar sign $. Thus $(TEST) repre-
+ sents an expansion of the macro variable named TEST. If
+ TEST is defined then $(TEST) is replaced by its expanded
+ value. If TEST is not defined then $(TEST) expands to the
+ NULL string (this is equivalent to defining a macro as
+ 'TEST=' ). A short form may be used for single character
+ named macros. In this case the parentheses are optional,
+ and $(I) is equivalent to $I. Macro expansion is recur-
+ sive, hence, if the value string contains an expression
+ representing a macro expansion, the expansion is per-
+ formed. Circular macro expansions are detected and cause
+ an error to be issued.
+
+ When defining a macro the given macro name is first
+ expanded before being used to define the macro. Thus it
+ is possible to define macros whose names depend on values
+ of other macros. For example, suppose CWD is defined as
+
+ CWD = $(PWD:b)
+
+ then the value of $(CWD) is the name of the current direc-
+ tory. This can be used to define macros specific to this
+ directory, for example:
+
+ _$(CWD).prt = list of files to print...
+
+ The actual name of the defined macro is a function of the
+ current directory. A construct such as this is useful
+ when processing a hierarchy of directories using .SETDIR
+ attributed targets and a collection of small distributed
+ makefile stubs.
+
+
+
+Version 4.01 PL0 UW 15
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ Macro variables may be defined within the makefile, on the
+ command line, or imported from the environment.
+
+ dmake supports several non-standard macro expansions: The
+ first is of the form:
+
+ $(macro_name:modifier_list:modifier_list:...)
+
+ where modifier_list is chosen from the set { B or b, D or
+ d, E or e, F or f, I or i, L or l, S or s, T or t, U or u,
+ ^, +, 1 } and
+
+ b - file (not including suffix) portion of path names
+ d - directory portion of all path names
+ e - suffix portion of path names
+ f - file (including suffix) portion of path names
+ i - inferred names of targets
+ l - macro value in lower case
+ s - simple pattern substitution
+ t - tokenization.
+ u - macro value in upper case
+ ^ - prepend a prefix to each token
+ + - append a suffix to each token
+ 1 - return the first white space separated token from value
+
+ Thus if we have the example:
+ test = d1/d2/d3/a.out f.out d1/k.out
+ The following macro expansions produce the values on the
+ right of '->' after expansion.
+
+ $(test:d) -> d1/d2/d3/ d1/
+ $(test:b) -> a f k
+ $(test:f) -> a.out f.out k.out
+ ${test:db} -> d1/d2/d3/a f d1/k
+ ${test:s/out/in/:f} -> a.in f.in k.in
+ $(test:f:t"+") -> a.out+f.out+k.out
+ $(test:e) -> .out .out .out
+ $(test:u) -> D1/D2/D3/A.OUT F.OUT D1/K.OUT
+ $(test:1) -> d1/d2/d3/a.out
+
+ If a token ends in a string composed from the value of the
+ macro DIRBRKSTR (ie. ends in a directory separator string,
+ e.g. '/' in UNIX) and you use the :d modifier then the
+ expansion returns the directory name less the final direc-
+ tory separator string. Thus successive pairs of :d modi-
+ fiers each remove a level of directory in the token
+ string.
+
+ The tokenization modifier takes all white space separated
+ tokens from the macro value and separates them by the
+ quoted separator string. The separator string may contain
+ the following escape codes \a => <bel>, \b => <backspace>,
+ \f => <formfeed>, \n => <nl>, \r => <cr>, \t => <tab>, \v
+ => <vertical tab>, \" => ", and \xxx => <xxx> where xxx is
+
+
+
+Version 4.01 PL0 UW 16
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ the octal representation of a character. Thus the expan-
+ sion:
+
+ $(test:f:t"+\n")
+ produces:
+ a.out+
+ f.out+
+ k.out
+
+ The prefix operator ^ takes all white space separated
+ tokens from the macro value and prepends string to each.
+
+ $(test:f:^mydir/)
+ produces:
+ mydir/a.out mydir/f.out mydir/k.out
+
+ The suffix operator + takes all white space separated
+ tokens from the macro value and appends string to each.
+
+ $(test:b:+.c)
+ produces:
+ a.c f.c k.c
+
+ The next non-standard form of macro expansion allows for
+ recursive macros. It is possible to specify a
+ $(macro_name) or ${macro_name} expansion where macro_name
+ contains more $( ... ) or ${ ... } macro expansions
+ itself.
+
+ For example $(CC$(_HOST)$(_COMPILER)) will first expand
+ CC$(_HOST)$(_COMPILER) to get a result and use that result
+ as the name of the macro to expand. This is useful for
+ writing a makefile for more than one target environment.
+ As an example consider the following hypothetical case.
+ Suppose that _HOST and _COMPILER are imported from the
+ environment and are set to represent the host machine type
+ and the host compiler respectively.
+
+ CFLAGS_VAX_CC = -c -O # _HOST == "_VAX", _COMPILER == "_CC"
+ CFLAGS_PC_MSC = -c -ML # _HOST == "_PC", _COMPILER == "_MSC"
+
+ # redefine CFLAGS macro as:
+
+ CFLAGS := $(CFLAGS$(_HOST)$(_COMPILER))
+
+ This causes CFLAGS to take on a value that corresponds to
+ the environment in which the make is being invoked.
+
+ The final non-standard macro expansion is of the form:
+
+ string1{token_list}string2
+
+ where string1, string2 and token_list are expanded. After
+ expansion, string1 is prepended to each token found in
+
+
+
+Version 4.01 PL0 UW 17
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ token_list and string2 is appended to each resulting token
+ from the previous prepend. string1 and string2 are not
+ delimited by white space whereas the tokens in token_list
+ are. A null token in the token list is specified using
+ "". Thus using another example we have:
+
+ test/{f1 f2}.o --> test/f1.o test/f2.o
+ test/ {f1 f2}.o --> test/ f1.o f2.o
+ test/{f1 f2} .o --> test/f1 test/f2 .o
+ test/{"f1" ""}.o --> test/f1.o test/.o
+
+ and
+
+ test/{d1 d2}/{f1 f2}.o --> test/d1/f1.o test/d1/f2.o
+ test/d2/f1.o test/d2/f2.o
+
+ This last expansion is activated only when the first char-
+ acters of token_list appear immediately after the opening
+ '{' with no intervening white space. The reason for this
+ restriction is the following incompatibility with Bourne
+ Shell recipes. The line
+
+ { echo hello;}
+
+ is valid /bin/sh syntax; while
+
+ {echo hello;}
+
+ is not. Hence the latter triggers the enhanced macro
+ expansion while the former causes it to be suppressed.
+ See the SPECIAL MACROS section for a description of the
+ special macros that dmake defines and understands.
+
+RULES AND TARGETS
+ A makefile contains a series of entries that specify
+ dependencies. Such entries are called target/prerequisite
+ or rule definitions. Each rule definition is optionally
+ followed by a set of lines that provide a recipe for
+ updating any targets defined by the rule. Whenever dmake
+ attempts to bring a target up to date and an explicit
+ recipe is provided with a rule defining the target, that
+ recipe is used to update the target. A rule definition
+ begins with a line having the following syntax:
+
+ <targets> [<attributes>] <ruleop> [<prerequisites>] [;<recipe>]
+
+ targets is a non-empty list of targets. If the target is
+ a special target (see SPECIAL TARGETS section below) then
+ it must appear alone on the rule line. For example:
+
+ .IMPORT .ERROR : ...
+
+ is not allowed since both .IMPORT and .ERROR are special
+ targets. Special targets are not used in the construction
+
+
+
+Version 4.01 PL0 UW 18
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ of the dependency graph and will not be made.
+
+ attributes is a possibly empty list of attributes. Any
+ attribute defined in the ATTRIBUTES section above may be
+ specified. All attributes will be applied to the list of
+ named targets in the rule definition. No other targets
+ will be affected.
+
+
+ NOTE: As stated earlier, if both the target list and
+ prerequisite list are empty but the attributes
+ list is not, then the specified attributes affect
+ all targets in the makefile.
+
+
+ ruleop is a separator which is used to identify the tar-
+ gets from the prerequisites. Optionally it also provides
+ a facility for modifying the way in which dmake handles
+ the making of the associated targets. In its simplest
+ form the operator is a single ':', and need not be sepa-
+ rated by white space from its neighboring tokens. It may
+ additionally be followed by any of the modifiers { !, ^,
+ -, :, | }, where:
+
+
+ ! says execute the recipe for the associated targets
+ once for each out of date prerequisite. Ordinarily
+ the recipe is executed once for all out of date
+ prerequisites at the same time.
+
+ ^ says to insert the specified prerequisites, if any,
+ before any other prerequisites already associated
+ with the specified targets. In general, it is not
+ useful to specify ^ with an empty list of prerequi-
+ sites.
+
+ - says to clear the previous list of prerequisites
+ before adding the new prerequisites. Thus,
+
+ .SUFFIXES :
+ .SUFFIXES : .a .b
+
+ can be replaced by
+
+ .SUFFIXES :- .a .b
+
+ however the old form still works as expected.
+ NOTE: .SUFFIXES is ignored by dmake it is used
+ here simply as an example.
+
+ : When the rule operator is not modified by a second
+ ':' only one set of rules may be specified for mak-
+ ing a target. Multiple definitions may be used to
+ add to the list of prerequisites that a target
+
+
+
+Version 4.01 PL0 UW 19
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ depends on. However, if a target is multiply
+ defined only one definition may specify a recipe
+ for making the target.
+
+ When a target's rule operator is modified by a sec-
+ ond ':' (:: for example) then this definition may
+ not be the only definition with a recipe for the
+ target. There may be other :: target definition
+ lines that specify a different set of prerequisites
+ with a different recipe for updating the target.
+ Any such target is made if any of the definitions
+ find it to be out of date with respect to the
+ related prerequisites and the corresponding recipe
+ is used to update the target. By definition all
+ '::' recipes that are found to be out of date for
+ are executed.
+
+ In the following simple example, each rule has a
+ `::' ruleop. In such an operator we call the first
+ `:' the operator, and the second `:' the modifier.
+
+ a.o :: a.c b.h
+ first recipe for making a.o
+
+ a.o :: a.y b.h
+ second recipe for making a.o
+
+ If a.o is found to be out of date with respect to
+ a.c then the first recipe is used to make a.o. If
+ it is found out of date with respect to a.y then
+ the second recipe is used. If a.o is out of date
+ with respect to b.h then both recipes are invoked
+ to make a.o. In the last case the order of invoca-
+ tion corresponds to the order in which the rule
+ definitions appear in the makefile.
+
+ | Is defined only for PERCENT rule target defini-
+ tions. When specified it indicates that the fol-
+ lowing construct should be parsed using the old
+ semantinc meaning:
+
+ %.o :| %.c %.r %.f ; some rule
+
+ is equivalent to:
+
+ %.o : %.c ; some rule
+ %.o : %.r ; some rule
+ %.o : %.f ; some rule
+
+ Targets defined using a single `:' operator with a recipe
+ may be redefined again with a new recipe by using a `:'
+ operator with a `:' modifier. This is equivalent to a
+ target having been initially defined with a rule using a
+ `:' modifier. Once a target is defined using a `:'
+
+
+
+Version 4.01 PL0 UW 20
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ modifier it may not be defined again with a recipe using
+ only the `:' operator with no `:' modifier. In both cases
+ the use of a `:' modifier creates a new list of prerequi-
+ sites and makes it the current prerequisite list for the
+ target. The `:' operator with no recipe always modifies
+ the current list of prerequisites. Thus assuming each of
+ the following definitions has a recipe attached, then:
+
+ joe : fred ... (1)
+ joe :: more ... (2)
+
+ and
+
+ joe :: fred ... (3)
+ joe :: more ... (4)
+
+ are legal and mean: add the recipe associated with (2),
+ or (4) to the set of recipes for joe, placing them after
+ existing recipes for making joe. The constructs:
+
+ joe :: fred ... (5)
+ joe : more ... (6)
+
+ and
+
+ joe : fred ... (7)
+ joe : more ... (8)
+
+ are errors since we have two sets of perfectly good
+ recipes for making the target.
+
+ prerequisites is a possibly empty list of targets that
+ must be brought up to date before making the current tar-
+ get.
+
+ recipe is a short form and allows the user to specify
+ short rule definitions on a single line. It is taken to
+ be the first recipe line in a larger recipe if additional
+ lines follow the rule definition. If the semi-colon is
+ present but the recipe line is empty (ie. null string)
+ then it is taken to be an empty rule. Any target so
+ defined causes the Don't know how to make ... error mes-
+ sage to be suppressed when dmake tries to make the target
+ and fails. This silence is maintained for rules that are
+ terminated by a semicolon and have no following recipe
+ lines, for targets listed on the command line, for the
+ first target found in the makefile, and for any target
+ having no recipe but containing a list of prerequisites
+ (see the COMPATIBILITY section for an exception to this
+ rule if the AUGMAKE (-A) flag was specified.
+
+RECIPES
+ The traditional format used by most versions of Make
+ defines the recipe lines as arbitrary strings that may
+
+
+
+Version 4.01 PL0 UW 21
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ contain macro expansions. They follow a rule definition
+ line and may be spaced apart by comment or blank lines.
+ The list of recipe lines defining the recipe is terminated
+ by a new target definition, a macro definition, or end-of-
+ file. Each recipe line MUST begin with a <TAB> character
+ which may optionally be followed with one or all of the
+ characters '@%+-'. The '-' indicates that non-zero exit
+ values (ie. errors) are to be ignored when this recipe
+ line is executed, the '+' indicates that the current
+ recipe line is to be executed using the shell, the '%'
+ indicates that dmake should swap itself out to secondary
+ storage (MSDOS only) before running the recipe and the '@'
+ indicates that the recipe line should NOT be echoed to the
+ terminal prior to being executed. Each switch is off by
+ default (ie. by default, errors are significant, commands
+ are echoed, no swapping is done and a shell is used only
+ if the recipe line contains a character found in the value
+ of the SHELLMETAS macro). Global settings activated via
+ command line options or special attribute or target names
+ may also affect these settings. An example recipe:
+
+ target :
+ first recipe line
+ second recipe line, executed independent of first.
+ @a recipe line that is not echoed
+ -and one that has errors ignored
+ %and one that causes dmake to swap out
+ +and one that is executed using a shell.
+
+ The second and new format of the recipe block begins the
+ block with the character '[' (the open group character) in
+ the last non-white space position of a line, and termi-
+ nates the block with the character ']' (the close group
+ character) in the first non-white space position of a
+ line. In this form each recipe line need not have a lead-
+ ing TAB. This is called a recipe group. Groups so
+ defined are fed intact as a single unit to a shell for
+ execution whenever the corresponding target needs to be
+ updated. If the open group character '[' is preceded by
+ one or all of -, @ or % then they apply to the entire
+ group in the same way that they apply to single recipe
+ lines. You may also specify '+' but it is redundant as a
+ shell is already being used to run the recipe. See the
+ MAKING TARGETS section for a description of how dmake
+ invokes recipes. Here is an example of a group recipe:
+
+ target :
+ [
+ first recipe line
+ second recipe line
+ tall of these recipe lines are fed to a
+ single copy of a shell for execution.
+ ]
+
+
+
+
+Version 4.01 PL0 UW 22
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+TEXT DIVERSIONS
+ dmake supports the notion of text diversions. If a recipe
+ line contains the macro expression
+
+ $(mktmp[,[file][,text]] data)
+
+ then all text contained in the data expression is expanded
+ and is written to a temporary file. The return value of
+ the macro is the name of the temporary file.
+
+ data can be any text and must be separated from the
+ 'mktmp' portion of the macro name by white-space. The
+ only restriction on the data text is that it must contain
+ a balanced number of parentheses of the same kind as are
+ used to initiate the $(mktmp ...) expression. For exam-
+ ple:
+
+ $(mktmp $(XXX))
+
+ is legal and works as expected, but:
+
+ $(mktmp text (to dump to file)
+
+ is not legal. You can achieve what you wish by either
+ defining a macro that expands to '(' or by using {} in the
+ macro expression; like this:
+
+ ${mktmp text (to dump to file}
+
+ Since the temporary file is opened when the macro contain-
+ ing the text diversion expression is expanded, diversions
+ may be nested and any diversions that are created as part
+ of ':=' macro expansions persist for the duration of the
+ dmake run. The diversion text may contain the same escape
+ codes as those described in the MACROS section. Thus if
+ the data text is to contain new lines they must be
+ inserted using the \n escape sequence. For example the
+ expression:
+
+ all:
+ cat $(mktmp this is a\n\
+ test of the text diversion\n)
+
+ is replaced by:
+
+ cat /tmp/mk12294AA
+
+ where the temporary file contains two lines both of which
+ are terminated by a new-line. If the data text spans mul-
+ tiple lines in the makefile then each line must be contin-
+ ued via the use of a \. A second more illustrative exam-
+ ple generates a response file to an MSDOS link command:
+
+ OBJ = fred.obj mary.obj joe.obj
+
+
+
+Version 4.01 PL0 UW 23
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ all : $(OBJ)
+ link @$(mktmp $(^:t"+\n")\n)
+
+ The result of making `all' in the second example is the
+ command:
+
+ link @/tmp/mk02394AA
+
+ where the temporary file contains:
+
+ fred.obj+
+ mary.obj+
+ joe.obj
+
+ The last line of the file is terminated by a new-line
+ which is inserted due to the \n found at the end of the
+ data string.
+
+ If the optional file specifier is present then its
+ expanded value is the name of the temporary file to cre-
+ ate. Whenever a $(mktmp ...) macro is expanded the macro
+ $(TMPFILE) is set to a new temporary file name. Thus the
+ construct:
+
+ $(mktmp,$(TMPFILE) data)
+
+ is completely equivalent to not specifying the $(TMPFILE)
+ optional argument. Another example that would be useful
+ for MSDOS users with a Turbo-C compiler
+
+ $(mktmp,turboc.cfg $(CFLAGS))
+
+ will place the contents of CFLAGS into a local turboc.cfg
+ file. The second optional argument, text, if present
+ alters the name of the value returned by the $(mktmp ...)
+ macro.
+
+ Under MS-DOS text diversions may be a problem. Many DOS
+ tools require that path names which contain directories
+ use the \ character to delimit the directories. Some
+ users however wish to use the '/' to delimit pathnames and
+ use environments that allow them to do so. The macro USE-
+ SHELL is set to "yes" if the current recipe is forced to
+ use a shell via the .USESHELL or '+' directives, otherwise
+ its value is "no". The dmake startup files define the
+ macro DIVFILE whose value is either the value of TMPFILE
+ or the value of TMPFILE edited to replace any '/' charac-
+ ters to the appropriate value based on the current shell
+ and whether it will be used to execute the recipe.
+
+ Previous versions of dmake defined text diversions using
+ <+, +> strings, where <+ started a text diversion and +>
+ terminated one. dmake is backward compatible with this
+ construct only if the <+ and +> appear literally on the
+
+
+
+Version 4.01 PL0 UW 24
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ same recipe line or in the same macro value string. In
+ such instances the expression:
+
+ <+data+>
+
+ is mapped to:
+
+ $(mktmp data)
+
+ which is fully output compatible with the earlier con-
+ struct. <+, +> constructs whose text spans multiple lines
+ must be converted by hand to use $(mktmp ...).
+
+ If the environment variable TMPDIR is defined then the
+ temporary file is placed into the directory specified by
+ that variable. A makefile can modify the location of tem-
+ porary files by defining a macro named TMPDIR and export-
+ ing it using the .EXPORT special target.
+
+SPECIAL TARGETS
+ This section describes the special targets that are recog-
+ nized by dmake. Some are affected by attributes and oth-
+ ers are not.
+
+ .ERROR If defined then the recipe associated with
+ this target is executed whenever an error
+ condition is detected by dmake. All
+ attributes that can be used with any other
+ target may be used with this target. Any
+ prerequisites of this target will be brought
+ up to date during its processing. NOTE:
+ errors will be ignored while making this
+ target, in extreme cases this may cause some
+ problems.
+
+ .EXIT If this target is encountered while parsing
+ a makefile then the parsing of the makefile
+ is immediately terminated at that point.
+
+ .EXPORT All prerequisites associated with this tar-
+ get are assumed to correspond to macro names
+ and they and their values are exported to
+ the environment as environment strings at
+ the point in the makefile at which this tar-
+ get appears. Any attributes specified with
+ this target are ignored. Only macros which
+ have been assigned a value in the makefile
+ prior to the export directive are exported,
+ macros as yet undefined or macros whose
+ value contains any of the characters "+=:*"
+ are not exported. is suppre
+
+ .IMPORT Prerequisite names specified for this target
+ are searched for in the environment and
+
+
+
+Version 4.01 PL0 UW 25
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ defined as macros with their value taken
+ from the environment. If the special name
+ .EVERYTHING is used as a prerequisite name
+ then all environment variables defined in
+ the environment are imported. The function-
+ ality of the -E flag can be forced by plac-
+ ing the construct .IMPORT : .EVERYTHING at
+ the start of a makefile. Similarly, by
+ placing the construct at the end, one can
+ emulate the effect of the -e command line
+ flag. If a prerequisite name cannot be
+ found in the environment an error message is
+ issued. .IMPORT accepts the .IGNORE
+ attribute. When given, it causes dmake to
+ ignore the above error. See the MACROS sec-
+ tion for a description of the processing of
+ imported macro values.
+
+ .INCLUDE Parse another makefile just as if it had
+ been located at the point of the .INCLUDE in
+ the current makefile. The list of prerequi-
+ sites gives the list of makefiles to try to
+ read. If the list contains multiple make-
+ files then they are read in order from left
+ to right. The following search rules are
+ used when trying to locate the file. If the
+ filename is surrounded by " or just by
+ itself then it is searched for in the cur-
+ rent directory. If it is not found it is
+ then searched for in each of the directories
+ specified as prerequisites of the
+ .INCLUDEDIRS special target. If the file
+ name is surrounded by < and >, (ie.
+ <my_spiffy_new_makefile>) then it is
+ searched for only in the directories given
+ by the .INCLUDEDIRS special target. In both
+ cases if the file name is a fully qualified
+ name starting at the root of the file system
+ then it is only searched for once, and the
+ .INCLUDEDIRS list is ignored. If .INCLUDE
+ fails to find the file it invokes the infer-
+ ence engine to try to infer and hence make
+ the file to be included. In this way the
+ file can be checked out of an RCS repository
+ for example. .INCLUDE accepts the .IGNORE,
+ .SETDIR, and .NOINFER attributes. If the
+ .IGNORE attribute is given and the file can-
+ not be found then dmake continues process-
+ ing, otherwise an error message is gener-
+ ated. If the .NOINFER attribute is given
+ and the file cannot be found then dmake will
+ not attempt to infer and make the file. The
+ .SETDIR attribute causes dmake to change
+ directories to the specified directory prior
+
+
+
+Version 4.01 PL0 UW 26
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ to attempting the include operation. If all
+ fails dmake attempts to make the file to be
+ included. If making the file fails then
+ dmake terminates unless the .INCLUDE direc-
+ tive also specified the .IGNORE attribute.
+ If .FIRST is specified along with .INCLUDE
+ then dmake attempts to include each named
+ prerequisite and will terminate the inclu-
+ sion with the first prerequisite that
+ results in a successful inclusion.
+
+ .INCLUDEDIRS The list of prerequisites specified for this
+ target defines the set of directories to
+ search when trying to include a makefile.
+
+ .KEEP_STATE This special target is a synonym for the
+ macro definition
+
+ .KEEP_STATE := _state.mk
+
+ It's effect is to turn on STATE keeping and
+ to define _state.mk as the state file.
+
+ .MAKEFILES The list of prerequisites is the set of
+ files to try to read as the default make-
+ file. By default this target is defined as:
+
+ .MAKEFILES : makefile.mk Makefile makefile
+
+
+ .SOURCE The prerequisite list of this target defines
+ a set of directories to check when trying to
+ locate a target file name. See the section
+ on BINDING of targets for more information.
+
+ .SOURCE.suff The same as .SOURCE, except that the
+ .SOURCE.suff list is searched first when
+ trying to locate a file matching the a tar-
+ get whose name ends in the suffix .suff.
+
+ .REMOVE The recipe of this target is used whenever
+ dmake needs to remove intermediate targets
+ that were made but do not need to be kept
+ around. Such targets result from the appli-
+ cation of transitive closure on the depen-
+ dency graph.
+
+ In addition to the special targets above, several other
+ forms of targets are recognized and are considered spe-
+ cial, their exact form and use is defined in the sections
+ that follow.
+
+SPECIAL MACROS
+ dmake defines a number of special macros. They are
+
+
+
+Version 4.01 PL0 UW 27
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ divided into three classes: control macros, run-time
+ macros, and function macros. The control macros are used
+ by dmake to configure its actions, and are the preferred
+ method of doing so. In the case when a control macro has
+ the same function as a special target or attribute they
+ share the same name as the special target or attribute.
+ The run-time macros are defined when dmake makes targets
+ and may be used by the user inside recipes. The function
+ macros provide higher level functions dealing with macro
+ expansion and diversion file processing.
+
+CONTROL MACROS
+ To use the control macros simply assign them a value just
+ like any other macro. The control macros are divided into
+ three groups: string valued macros, character valued
+ macros, and boolean valued macros.
+
+ The following are all of the string valued macros. This
+ list is divided into two groups. The first group gives
+ the string valued macros that are defined internally and
+ cannot be directly set by the user.
+
+ INCDEPTH This macro's value is a string of digits
+ representing the current depth of makefile
+ inclusion. In the first makefile level
+ this value is zero.
+
+ MFLAGS Is the list of flags that were given on
+ the command line including a leading
+ switch character. The -f flag is not
+ included in this list.
+
+ MAKECMD Is the name with which dmake was invoked.
+
+ MAKEDIR Is the full path to the initial directory
+ in which dmake was invoked.
+
+ MAKEFILE Contains the string "-f makefile" where,
+ makefile is the name of initial user make-
+ file that was first read.
+
+ MAKEFLAGS Is the same as $(MFLAGS) but has no lead-
+ ing switch character. (ie. MFLAGS =
+ -$(MAKEFLAGS))
+
+ MAKEMACROS Contains the complete list of macro
+ expressions that were specified on the
+ command line.
+
+ MAKETARGETS Contains the name(s) of the target(s), if
+ any, that were specified on the command
+ line.
+
+ MAKEVERSION Contains a string indicating the current
+
+
+
+Version 4.01 PL0 UW 28
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ dmake version number.
+
+ MAXPROCESSLIMIT Is a numeric string representing the maxi-
+ mum number of processes that dmake can use
+ when making targets using parallel mode.
+
+ NULL Is permanently defined to be the NULL
+ string. This is useful when comparing a
+ conditional expression to an NULL value.
+
+ PWD Is the full path to the current directory
+ in which make is executing.
+
+ TMPFILE Is set to the name of the most recent tem-
+ porary file opened by dmake. Temporary
+ files are used for text diversions and for
+ group recipe processing.
+
+ TMD Stands for "To Make Dir", and is the path
+ from the present directory (value of
+ $(PWD)) to the directory that dmake was
+ started up in (value of $(MAKEDIR)). This
+ macro is modified when .SETDIR attributes
+ are processed.
+
+ USESHELL The value of this macro is set to "yes" if
+ the current recipe is forced to use a
+ shell for its execution via the .USESHELL
+ or '+' directives, its value is "no" oth-
+ erwise.
+
+
+ The second group of string valued macros control dmake
+ behavior and may be set by the user.
+
+ .DIRCACHE If set to "yes" enables the directory
+ cache (this is the default). If set to
+ "no" disables the directory cache (equiva-
+ lent to -d command-line flag).
+
+ .DIRCACHERESPCASE
+ If set to "yes" causes the directory
+ cache, if enabled, to respect file case,
+ if set to "no" facilities of the native OS
+ are used to match file case.
+
+ .NAMEMAX Defines the maximum length of a filename
+ component. The value of the variable is
+ initialized at startup to the value of the
+ compiled macro NAME_MAX. On some systems
+ the value of NAME_MAX is too short by
+ default. Setting a new value for .NAMEMAX
+ will override the compiled value.
+
+
+
+
+Version 4.01 PL0 UW 29
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ .NOTABS When set to "yes" enables the use of
+ spaces as well as <tabs> to begin recipe
+ lines. By default a non-group recipe is
+ terminated by a line without any leading
+ white-space or by a line not beggining
+ with a <tab> character. Enabling this
+ mode modifies the first condition of the
+ above termination rule to terminate a
+ non-group recipe with a line that contains
+ only white-space. This mode does not
+ effect the parsing of group recipes brack-
+ eted by [].
+
+ AUGMAKE If set to "yes" value will enable the
+ transformation of special meta targets to
+ support special AUGMAKE inferences (See
+ the COMPATIBILITY section).
+
+ DIRBRKSTR Contains the string of chars used to ter-
+ minate the name of a directory in a path-
+ name. Under UNIX its value is "/", under
+ MSDOS its value is "/\:".
+
+ DIRSEPSTR Contains the string that is used to sepa-
+ rate directory components when path names
+ are constructed. It is defined with a
+ default value at startup.
+
+ DIVFILE Is defined in the startup file and gives
+ the name that should be returned for the
+ diversion file name when used in $(mktmp
+ ...) expansions, see the TEXT DIVERSION
+ section for details.
+
+ DYNAMICNESTINGLEVEL
+ Specifies the maximum number of recursive
+ dynamic macro expansions. Its initial
+ value is 100.
+
+ .KEEP_STATE Assigning this macro a value tells dmake
+ the name of the state file to use and
+ turns on the keeping of state information
+ for any targets that are brought up to
+ date by the make.
+
+ GROUPFLAGS This macro gives the set of flags to pass
+ to the shell when invoking it to execute a
+ group recipe. The value of the macro is
+ the list of flags with a leading switch
+ indicator. (ie. `-' under UNIX)
+
+ GROUPSHELL This macro defines the full path to the
+ executable image to be used as the shell
+ when processing group recipes. This macro
+
+
+
+Version 4.01 PL0 UW 30
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ must be defined if group recipes are used.
+ It is assigned a default value in the
+ startup makefile. Under UNIX this value
+ is /bin/sh.
+
+ GROUPSUFFIX If defined, this macro gives the string to
+ use as a suffix when creating group recipe
+ files to be handed to the command inter-
+ preter. For example, if it is defined as
+ .sh, then all temporary files created by
+ dmake will end in the suffix .sh. Under
+ MSDOS if you are using command.com as your
+ GROUPSHELL, then this suffix must be set
+ to .bat in order for group recipes to
+ function correctly. The setting of GROUP-
+ SUFFIX and GROUPSHELL is done automati-
+ cally for command.com in the startup.mk
+ files.
+
+ MAKE Is defined in the startup file by default.
+ Initially this macro is defined to have
+ the value "$(MAKECMD) $(MFLAGS)". The
+ string $(MAKE) is recognized when using
+ the -n switch.
+
+ MAKESTARTUP This macro defines the full path to the
+ initial startup makefile. Use the -V com-
+ mand line option to discover its initial
+ value.
+
+ MAXLINELENGTH This macro defines the maximum size of a
+ single line of makefile input text. The
+ size is specified as a number, the default
+ value is defined internally and is shown
+ via the -V option. A buffer of this size
+ plus 2 is allocated for reading makefile
+ text. The buffer is freed before any tar-
+ gets are made, thereby allowing files con-
+ taining long input lines to be processed
+ without consuming memory during the actual
+ make. This macro can only be used to
+ extend the line length beyond it's default
+ minimum value.
+
+ MAXPROCESS Specify the maximum number of child pro-
+ cesses to use when making targets. The
+ default value of this macro is "1" and its
+ value cannot exceed the value of the macro
+ MAXPROCESSLIMIT. Setting the value of
+ MAXPROCESS on the command line or in the
+ makefile is equivalent to supplying a cor-
+ responding value to the -P flag on the
+ command line.
+
+
+
+
+Version 4.01 PL0 UW 31
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ PREP This macro defines the number of itera-
+ tions to be expanded automatically when
+ processing % rule definitions of the form:
+
+ % : %.suff
+
+ See the sections on PERCENT(%) RULES for
+ details on how PREP is used.
+
+ SHELL This macro defines the full path to the
+ executable image to be used as the shell
+ when processing single line recipes. This
+ macro must be defined if recipes requiring
+ the shell for execution are to be used.
+ It is assigned a default value in the
+ startup makefile. Under UNIX this value
+ is /bin/sh.
+
+ SHELLFLAGS This macro gives the set of flags to pass
+ to the shell when invoking it to execute a
+ single line recipe. The value of the
+ macro is the list of flags with a leading
+ switch indicator. (ie. `-' under UNIX)
+
+ SHELLMETAS Each time dmake executes a single recipe
+ line (not a group recipe) the line is
+ searched for any occurrence of a character
+ defined in the value of SHELLMETAS. If
+ such a character is found the recipe line
+ is defined to require a shell to ensure
+ its correct execution. In such instances
+ a shell is used to invoke the recipe line.
+ If no match is found the recipe line is
+ executed without the use of a shell.
+
+
+ There is only one character valued macro defined by dmake:
+ SWITCHAR contains the switch character used to introduce
+ options on command lines. For UNIX its value is `-', and
+ for MSDOS its value may be `/' or `-'. The macro is
+ internally defined and is not user setable. The MSDOS
+ version of dmake attempts to first extract SWITCHAR from
+ an environment variable of the same name. If that fails
+ it then attempts to use the undocumented getswitchar sys-
+ tem call, and returns the result of that. Under MSDOS
+ version 4.0 you must set the value of the environment
+ macro SWITCHAR to '/' to obtain predictable behavior.
+
+ All boolean macros currently understood by dmake corre-
+ spond directly to the previously defined attributes.
+ These macros provide a second way to apply global
+ attributes, and represent the preferred method of doing
+ so. They are used by assigning them a value. If the
+ value is not a NULL string then the boolean condition is
+
+
+
+Version 4.01 PL0 UW 32
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ set to on. If the value is a NULL string then the condi-
+ tion is set to off. There are five conditions defined and
+ they correspond directly to the attributes of the same
+ name. Their meanings are defined in the ATTRIBUTES sec-
+ tion above. The macros are: .EPILOG, .IGNORE, .MKSARGS,
+ .NOINFER, .PRECIOUS, .PROLOG, .SEQUENTIAL, .SILENT, .SWAP,
+ and .USESHELL. Assigning any of these a non NULL value
+ will globally set the corresponding attribute to on.
+
+RUNTIME MACROS
+ These macros are defined when dmake is making targets, and
+ may take on different values for each target. $@ is
+ defined to be the full target name, $? is the list of all
+ out of date prerequisites, $& is the list of all prerequi-
+ sites, $> is the name of the library if the current target
+ is a library member, and $< is the list of prerequisites
+ specified in the current rule. If the current target had
+ a recipe inferred then $< is the name of the inferred pre-
+ requisite even if the target had a list of prerequisites
+ supplied using an explicit rule that did not provide a
+ recipe. In such situations $& gives the full list of pre-
+ requisites.
+
+ $* is defined as $(@:db) when making targets with explicit
+ recipes and is defined as the value of % when making tar-
+ gets whose recipe is the result of an inference. In the
+ first case $* is the target name with no suffix, and in
+ the second case, is the value of the matched % pattern
+ from the associated %-rule. $^ expands to the set of out
+ of date prerequisites taken from the current value of $<.
+ In addition to these, $$ expands to $, {{ expands to {, }}
+ expands to }, and the strings <+ and +> are recognized as
+ respectively starting and terminating a text diversion
+ when they appear literally together in the same input
+ line.
+
+ The difference between $? and $^ can best be illustrated
+ by an example, consider:
+
+ fred.out : joe amy hello
+ rules for making fred
+
+ fred.out : my.c your.h his.h her.h # more prerequisites
+
+ Assume joe, amy, and my.c are newer then fred.out. When
+ dmake executes the recipe for making fred.out the values
+ of the following macros will be:
+
+ $@ --> fred.out
+ $* --> fred
+ $? --> joe amy my.c # note output of $? vs $^
+ $^ --> joe amy
+ $< --> joe amy hello
+ $& --> joe amy hello my.c your.h his.h her.h
+
+
+
+Version 4.01 PL0 UW 33
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+FUNCTION MACROS
+ dmake supports a full set of functional macros. One of
+ these, the $(mktmp ...) macro, is discussed in detail in
+ the TEXT DIVERSION section and is not covered here.
+
+
+ $(and macroterm ...)
+ expands each macroterm in turn until there
+ are no more or one of them returns an empty
+ string. If all expand to non-empty strings
+ the macro returs the string "t" otherwise it
+ returns an empty string.
+
+
+ $(assign expression)
+ Causes expression to be parsed as a macro
+ assignment expression and results in the
+ specified assignment being made. An error
+ is issued if the assignment is not syntati-
+ cally correct. expression may contain white
+ space. This is in effect a dynamic macro
+ assignment facility and may appear anywhere
+ any other macro may appear. The result of
+ the expanding a dynamic macro assignment
+ expression is the name of the macro that was
+ assigned and $(NULL) if the expression is
+ not a valid macro assignment expression.
+ Some examples are:
+
+ $(assign foo := fred)
+ $(assign $(ind_macro_name) +:= $(morejunk))
+
+ $(echo list)
+ Echo's the value of list. list is not
+ expanded.
+
+ $(eq,text_a,text_b true false)
+ expands text_a and text_b and compares their
+ results. If equal it returns the result of
+ the expansion of the true term, otherwise it
+ returns the expansion of the false term.
+
+ $(!eq,text_a,text_b true false)
+ Behaves identically to the previous macro
+ except that the true string is chosen if the
+ expansions of the two strings are not equal
+
+ $(foreach,var,list data)
+ Implements iterative macro expansion over
+ data using var as the iterator taking on
+ values from list. var and list are expanded
+ and the result is the concatenation of
+ expanding data with var being set to each
+ whitespace separated token from list. For
+
+
+
+Version 4.01 PL0 UW 34
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ example:
+
+ list = a b c
+ all :; echo [$(foreach,i,$(list) [$i])]
+
+ will output
+
+ [[a] [b] [c]]
+
+ The iterator variable is defined as a local
+ variable to this foreach instance. The fol-
+ lowing expression illustrates this:
+
+ $(foreach,i,$(foreach,i,$(sort c a b) root/$i) [$i/f.h])
+
+ when evaluated the result is:
+
+ [root/a/f.h] [root/b/f.h] [root/c/f.h]
+
+ The specification of list must be a valid
+ macro expression, such as:
+
+ $($(assign list=a b c))
+ $(sort d a b c)
+ $(echo a b c)
+
+ and cannot just be the list itself. That
+ is, the following foreach expression:
+
+ $(foreach,i,a b c [$i])
+
+ yields:
+
+ "b c [a]"
+
+ when evaluated.
+
+ $(nil expression)
+ Always returns the value of $(NULL) regard-
+ less of what expression is. This function
+ macro can be used to discard results of
+ expanding macro expressions.
+
+ $(not macroterm)
+ expands macroterm and returs the string "t"
+ if the result of the expansion is the empty
+ string; otherwise, it returns the empty
+ string.
+
+ $(null,text true false)
+ expands the value of text. If it is NULL
+ then the macro returns the value of the
+ expansion of true and the expansion of false
+ otherwise. The terms true, and false must
+
+
+
+Version 4.01 PL0 UW 35
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ be strings containing no white-space.
+
+ $(!null,text true false)
+ Behaves identically to the previous macro
+ except that the true string is chosen if the
+ expansion of text is not NULL.
+
+ $(or macroterm ...)
+ expands each macroterm in turn and returs
+ the empty string if each term expands to the
+ empty string; otherwise, it returs the
+ string "t".
+
+ $(shell command)
+ Runs command as if it were part of a recipe
+ and returns, separated by a single space,
+ all the non-white space terms written to
+ stdout by the command. For example:
+
+ $(shell ls *.c)
+
+ will return "a.c b.c c.c d.c" if the files
+ exist in the current directory. The recipe
+ modification flags [+@%-] are honored if
+ they appear as the first characters in the
+ command. For example:
+
+ $(shell +ls *.c)
+
+ will run the command using the current
+ shell.
+
+ $(shell,expand command)
+ Is an extension to the $(shell... function
+ macro that expands the result of running
+ command.
+
+ $(sort list)
+ Will take all white-space separated tokens
+ in list and will return their sorted equiva-
+ lent list.
+
+ $(strip data)
+ Will replace all strings of white-space in
+ data by a single space.
+
+ $(subst,pat,replacement data)
+ Will search for pat in data and will replace
+ any occurrence of pat with the replacement
+ string. The expansion
+
+ $(subst,.o,.c $(OBJECTS))
+
+ is equivalent to:
+
+
+
+Version 4.01 PL0 UW 36
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ $(OBJECTS:s/.o/.c/)
+
+
+ $(uniq list)
+ Will take all white-space separated tokens
+ in list and will return their sorted equiva-
+ lent list containing no duplicates.
+
+CONDITIONAL MACROS
+ dmake supports conditional macros. These allow the defi-
+ nition of target specific macro values. You can now say
+ the following:
+
+ target ?= MacroName MacroOp Value
+
+ This creates a definition for MacroName whose value is
+ Value only when target is being made. You may use a con-
+ ditional macro assignment anywhere that a regular macro
+ assignment may appear, including as the value of a
+ $(assign ...) macro.
+
+ The new definition is associated with the most recent cell
+ definition for target. If no prior definition exists then
+ one is created. The implications of this are immediately
+ evident in the following example:
+
+ foo := hello
+
+ all : cond;@echo "all done, foo=[$(foo)] bar=[$(bar)]"
+
+ cond ?= bar := global decl
+
+ cond .SETDIR=unix::;@echo $(foo) $(bar)
+ cond ?= foo := hi
+
+ cond .SETDIR=msdos::;@echo $(foo) $(bar)
+ cond ?= foo := hihi
+
+ The first conditional assignment creates a binding for
+ 'bar' that is activated when 'cond' is made. The bindings
+ following the :: definitions are activated when their
+ respective recipe rules are used. Thus the first binding
+ serves to provide a global value for 'bar' while any of
+ the cond :: rules are processed, and the local bindings
+ for 'foo' come into effect when their associated :: rule
+ is processed.
+
+ Conditionals for targets of .UPDATEALL are all activated
+ before the target group is made. Assignments are pro-
+ cessed in order. Note that the value of a conditional
+ macro assignment is NOT AVAILABLE until the associated
+ target is made, thus the construct
+
+ mytarget ?= bar := hello
+
+
+
+Version 4.01 PL0 UW 37
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ mytarget ?= foo := $(bar)
+
+ results in $(foo) expanding to "", if you want the result
+ to be "hello" you must use:
+
+ mytarget ?= bar := hello
+ mytarget ?= foo = $(bar)
+
+ Once a target is made any associated conditional macros
+ are deactivated and their values are no longer available.
+ Activation occurrs after all inference, and .SETDIR direc-
+ tives have been processed and after $@ is assigned, but
+ before prerequisites are processed; thereby making the
+ values of conditional macro definitions available during
+ construction of prerequisites.
+
+ If a %-meta rule target has associated conditional macro
+ assignments, and the rule is chosen by the inference algo-
+ rithm then the conditional macro assignments are inferred
+ together with the associated recipe.
+
+DYNAMIC PREREQUISITES
+ dmake looks for prerequisites whose names contain macro
+ expansions during target processing. Any such prerequi-
+ sites are expanded and the result of the expansion is used
+ as the prerequisite name. As an example the line:
+
+ fred : $$@.c
+
+ causes the $$@ to be expanded when dmake is making fred,
+ and it resolves to the target fred. This enables dynamic
+ prerequisites to be generated. The value of @ may be mod-
+ ified by any of the valid macro modifiers. So you can say
+ for example:
+
+ fred.out : $$(@:b).c
+
+ where the $$(@:b) expands to fred. Note the use of $$
+ instead of $ to indicate the dynamic expansion, this is
+ due to the fact that the rule line is expanded when it is
+ initially parsed, and $$ then returns $ which later trig-
+ gers the dynamic prerequisite expansion. If you really
+ want a $ to be part of a prerequisite name you must use
+ $$$$. Dynamic macro expansion is performed in all user
+ defined rules, and the special targets .SOURCE*, and
+ .INCLUDEDIRS.
+
+ If dynamic macro expansion results in multiple white space
+ separated tokens then these are inserted into the prereq-
+ uisite list inplace of the dynamic prerequisite. If the
+ new list contains additional dynamic prerequisites they
+ will be expanded when they are processed. The level of
+ recursion in this expansion is controlled by the value of
+ the variable DYNAMICNESTINGLEVEL and is set to 100 by
+
+
+
+Version 4.01 PL0 UW 38
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ default.
+
+BINDING TARGETS
+ This operation takes a target name and binds it to an
+ existing file, if possible. dmake makes a distinction
+ between the internal target name of a target and its asso-
+ ciated external file name. Thus it is possible for a tar-
+ get's internal name and its external file name to differ.
+ To perform the binding, the following set of rules is
+ used. Assume that we are trying to bind a target whose
+ name is of the form X.suff, where .suff is the suffix and
+ X is the stem portion (ie. that part which contains the
+ directory and the basename). dmake takes this target name
+ and performs a series of search operations that try to
+ find a suitably named file in the external file system.
+ The search operation is user controlled via the settings
+ of the various .SOURCE targets.
+
+ 1. If target has the .SYMBOL attribute set then
+ look for it in the library. If found,
+ replace the target name with the library
+ member name and continue with step 2. If
+ the name is not found then return.
+
+ 2. Extract the suffix portion (that following
+ the `.') of the target name. If the suffix
+ is not null, look up the special target
+ .SOURCE.<suff> (<suff> is the suffix). If
+ the special target exists then search each
+ directory given in the .SOURCE.<suff> pre-
+ requisite list for the target. If the tar-
+ get's suffix was null (ie. .suff was empty)
+ then perform the above search but use the
+ special target .SOURCE.NULL instead. If at
+ any point a match is found then terminate
+ the search. If a directory in the prerequi-
+ site list is the special name `.NULL ' per-
+ form a search for the full target name with-
+ out prepending any directory portion (ie.
+ prepend the NULL directory).
+
+ 3. The search in step 2. failed. Repeat the
+ same search but this time use the special
+ target .SOURCE. (a default target of
+ '.SOURCE : .NULL' is defined by dmake at
+ startup, and is user redefinable)
+
+ 4. The search in step 3. failed. If the target
+ has the library member attribute (.LIBMEM-
+ BER) set then try to find the target in the
+ library which was passed along with the
+ .LIBMEMBER attribute (see the MAKING
+ LIBRARIES section). The bound file name
+ assigned to a target which is successfully
+
+
+
+Version 4.01 PL0 UW 39
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ located in a library is the same name that
+ would be assigned had the search failed (see
+ 5.).
+
+ 5. The search failed. Either the target was
+ not found in any of the search directories
+ or no applicable .SOURCE special targets
+ exist. If applicable .SOURCE special tar-
+ gets exist, but the target was not found,
+ then dmake assigns the first name searched
+ as the bound file name. If no applicable
+ .SOURCE special targets exist, then the full
+ original target name becomes the bound file
+ name.
+
+ There is potential here for a lot of search operations.
+ The trick is to define .SOURCE.x special targets with
+ short search lists and leave .SOURCE as short as possible.
+ The search algorithm has the following useful side effect.
+ When a target having the .LIBMEMBER (library member)
+ attribute is searched for, it is first searched for as an
+ ordinary file. When a number of library members require
+ updating it is desirable to compile all of them first and
+ to update the library at the end in a single operation.
+ If one of the members does not compile and dmake stops,
+ then the user may fix the error and make again. dmake
+ will not remake any of the targets whose object files have
+ already been generated as long as none of their prerequi-
+ site files have been modified as a result of the fix.
+
+ When dmake constructs target pathnames './' substrings are
+ removed and substrings of the form 'foo/..' are elimi-
+ nated. This may result in somewhat unexpected values of
+ the macro expansion $@, but is infact the corect result.
+
+ When defining .SOURCE and .SOURCE.x targets the construct
+
+
+ is equivalent to
+
+
+ dmake correctly handles the UNIX Make variable VPATH. By
+ definition VPATH contains a list of ':' separated directo-
+ ries to search when looking for a target. dmake maps
+ VPATH to the following special rule:
+
+
+ Which takes the value of VPATH and sets .SOURCE to the
+ same set of directories as specified in VPATH.
+
+PERCENT(%) RULES AND MAKING INFERENCES
+ When dmake makes a target, the target's set of prerequi-
+ sites (if any) must exist and the target must have a
+ recipe which dmake can use to make it. If the makefile
+
+
+
+Version 4.01 PL0 UW 40
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ does not specify an explicit recipe for the target then
+ dmake uses special rules to try to infer a recipe which it
+ can use to make the target. Previous versions of Make
+ perform this task by using rules that are defined by tar-
+ gets of the form .<suffix>.<suffix> and by using the .SUF-
+ FIXES list of suffixes. The exact workings of this mecha-
+ nism were sometimes difficult to understand and often lim-
+ iting in their usefulness. Instead, dmake supports the
+ concept of %-meta rules. The syntax and semantics of
+ these rules differ from standard rule lines as follows:
+
+ <%-target> [<attributes>] <ruleop> [<%-prerequisites>] [;<recipe>]
+
+ where %-target is a target containing exactly a single `%'
+ sign, attributes is a list (possibly empty) of attributes,
+ ruleop is the standard set of rule operators, %-prerequi-
+ sites , if present, is a list of prerequisites containing
+ zero or more `%' signs, and recipe, if present, is the
+ first line of the recipe.
+
+ The %-target defines a pattern against which a target
+ whose recipe is being inferred gets matched. The pattern
+ match goes as follows: all chars are matched exactly from
+ left to right up to but not including the % sign in the
+ pattern, % then matches the longest string from the actual
+ target name not ending in the suffix given after the %
+ sign in the pattern. Consider the following examples:
+
+ %.c matches fred.c but not joe.c.Z
+ dir/%.c matches dir/fred.c but not dd/fred.c
+ fred/% matches fred/joe.c but not f/joe.c
+ % matches anything
+
+ In each case the part of the target name that matched the
+ % sign is retained and is substituted for any % signs in
+ the prerequisite list of the %-meta rule when the rule is
+ selected during inference and dmake constructs the new
+ dependency. As an example the following %-meta rules
+ describe the following:
+
+ %.c : %.y ; recipe...
+
+ describes how to make any file ending in .c if a corre-
+ sponding file ending in .y can be found.
+
+ foo%.o : fee%.k ; recipe...
+
+ is used to describe how to make fooxxxx.o from feexxxx.k.
+
+ %.a :; recipe...
+
+ describes how to make a file whose suffix is .a without
+ inferring any prerequisites.
+
+
+
+
+Version 4.01 PL0 UW 41
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ %.c : %.y yaccsrc/%.y ; recipe...
+
+ is a short form for the construct:
+
+ %.c : %.y ; recipe...
+ %.c : yaccsrc/%.y ; recipe...
+
+ ie. It is possible to specify the same recipe for two
+ %-rules by giving more than one prerequisite in the pre-
+ requisite list. A more interesting example is:
+
+ % : RCS/%,v ; co $<
+
+ which describes how to take any target and check it out of
+ the RCS directory if the corresponding file exists in the
+ RCS directory. The equivalent SCCS rule would be:
+
+ % : s.% ; get $<
+
+
+ The previous RCS example defines an infinite rule, because
+ it says how to make anything from RCS/%,v, and anything
+ also includes RCS/fred.c,v. To limit the size of the
+ graph that results from such rules dmake uses the macro
+ variable PREP (stands for % repetition). By default the
+ value of this variable is 0, which says that no repeti-
+ tions of a %-rule are to be generated. If it is set to
+ something greater than 0, then that many repetitions of
+ any infinite %-rule are allowed. If in the above example
+ PREP was set to 1, then dmake would generate the depen-
+ dency graph:
+
+ % --> RCS/%,v --> RCS/RCS/%,v,v
+
+ Where each link is assigned the same recipe as the first
+ link. PREP should be used only in special cases, since it
+ may result in a large increase in the number of possible
+ prerequisites tested. dmake further assumes that any tar-
+ get that has no suffix can be made from a prerequisite
+ that has at least one suffix.
+
+ dmake supports dynamic prerequisite generation for prereq-
+ uisites of %-meta rules. This is best illustrated by an
+ example. The RCS rule shown above can infer how to check
+ out a file from a corresponding RCS file only if the tar-
+ get is a simple file name with no directory information.
+ That is, the above rule can infer how to find RCS/fred.c,v
+ from the target fred.c, but cannot infer how to find
+ srcdir/RCS/fred.c,v from srcdir/fred.c because the above
+ rule will cause dmake to look for RCS/srcdir/fred.c,v;
+ which does not exist (assume that srcdir has its own RCS
+ directory as is the common case).
+
+ A more versatile formulation of the above RCS check out
+
+
+
+Version 4.01 PL0 UW 42
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ rule is the following:
+
+ % : $$(@:d)RCS/$$(@:f),v : co $@
+
+ This rule uses the dynamic macro $@ to specify the prereq-
+ uisite to try to infer. During inference of this rule the
+ macro $@ is set to the value of the target of the %-meta
+ rule and the appropriate prerequisite is generated by
+ extracting the directory portion of the target name (if
+ any), appending the string RCS/ to it, and appending the
+ target file name with a trailing ,v attached to the previ-
+ ous result.
+
+ dmake can also infer indirect prerequisites. An inferred
+ target can have a list of prerequisites added that will
+ not show up in the value of $< but will show up in the
+ value of $? and $&. Indirect prerequisites are specified
+ in an inference rule by quoting the prerequisite with sin-
+ gle quotes. For example, if you had the explicit depen-
+ dency:
+
+ fred.o : fred.c ; rule to make fred.o
+ fred.o : local.h
+
+ then this can be inferred for fred.o from the following
+ inference rule:
+
+ %.o : %.c 'local.h' ; makes a .o from a .c
+
+ You may infer indirect prerequisites that are a function
+ of the value of '%' in the current rule. The meta-rule:
+
+ %.o : %.c '$(INC)/%.h' ; rule to make a .o from a
+ .c
+
+ infers an indirect prerequisite found in the INC directory
+ whose name is the same as the expansion of $(INC), and the
+ prerequisite name depends on the base name of the current
+ target. The set of indirect prerequisites is attached to
+ the meta rule in which they are specified and are inferred
+ only if the rule is used to infer a recipe for a target.
+ They do not play an active role in driving the inference
+ algorithm. The construct:
+
+ %.o : %.c %.f 'local.h'; recipe
+
+ is equivalent to:
+
+ %.o : %.c 'local.h' : recipe
+
+ while:
+
+ %.o :| %.c %.f 'local.h'; recipe
+
+
+
+
+Version 4.01 PL0 UW 43
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ is equivalent to:
+
+ %.o : %.c 'local.h' : recipe
+ %.o : %.f 'local.h' : recipe
+
+
+ If any of the attributes .SETDIR, .EPILOG, .PROLOG,
+ .SILENT, .USESHELL, .SWAP, .PRECIOUS, .LIBRARY, .NOSTATE
+ and .IGNORE are given for a %-rule then when that rule is
+ bound to a target as the result of an inference, the tar-
+ get's set of attributes is augmented by the attributes
+ from the above set that are specified in the bound %-rule.
+ Other attributes specified for %-meta rules are not inher-
+ ited by the target. The .SETDIR attribute is treated in a
+ special way. If the target already had a .SETDIR
+ attribute set then dmake changes to that directory prior
+ to performing the inference. During inference any .SETDIR
+ attributes for the inferred prerequisite are honored. The
+ directories must exist for a %-meta rule to be selected as
+ a possible inference path. If the directories do not
+ exist no error message is issued, instead the correspond-
+ ing path in the inference graph is rejected.
+
+ dmake also supports the old format special target .<suf-
+ fix>.<suffix> by identifying any rules of this form and
+ mapping them to the appropriate %-rule. So for example if
+ an old makefile contains the construct:
+
+ .c.o :; cc -c $< -o $@
+
+ dmake maps this into the following %-rule:
+
+ %.o : %.c; cc -c $< -o $@
+
+ Furthermore, dmake understands several SYSV AUGMAKE spe-
+ cial targets and maps them into corresponding %-meta
+ rules. These transformation must be enabled by providing
+ the -A flag on the command line or by setting the value of
+ AUGMAKE to non-NULL. The construct
+
+ .suff :; recipe
+
+ gets mapped into:
+
+ % : %.suff; recipe
+
+ and the construct
+
+ .c~.o :; recipe
+
+ gets mapped into:
+
+ %.o : s.%.c ; recipe
+
+
+
+
+Version 4.01 PL0 UW 44
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ In general, a special target of the form .<str>~ is
+ replaced by the %-rule construct s.%.<str>, thereby pro-
+ viding support for the syntax used by SYSV AUGMAKE for
+ providing SCCS support. When enabled, these mappings
+ allow processing of existing SYSV makefiles without modi-
+ fications.
+
+ dmake bases all of its inferences on the inference graph
+ constructed from the %-rules defined in the makefile. It
+ knows exactly which targets can be made from which prereq-
+ uisites by making queries on the inference graph. For
+ this reason .SUFFIXES is not needed and is completely
+ ignored.
+
+ For a %-meta rule to be inferred as the rule whose recipe
+ will be used to make a target, the target's name must
+ match the %-target pattern, and any inferred %-prerequi-
+ site must already exist or have an explicit recipe so that
+ the prerequisite can be made. Without transitive closure
+ on the inference graph the above rule describes precisely
+ when an inference match terminates the search. If transi-
+ tive closure is enabled (the usual case), and a prerequi-
+ site does not exist or cannot be made, then dmake invokes
+ the inference algorithm recursively on the prerequisite to
+ see if there is some way the prerequisite can be manufac-
+ tured. For, if the prerequisite can be made then the cur-
+ rent target can also be made using the current %-meta
+ rule. This means that there is no longer a need to give a
+ rule for making a .o from a .y if you have already given a
+ rule for making a .o from a .c and a .c from a .y. In
+ such cases dmake can infer how to make the .o from the .y
+ via the intermediary .c and will remove the .c when the .o
+ is made. Transitive closure can be disabled by giving the
+ -T switch on the command line.
+
+ A word of caution. dmake bases its transitive closure on
+ the %-meta rule targets. When it performs transitive clo-
+ sure it infers how to make a target from a prerequisite by
+ performing a pattern match as if the potential prerequi-
+ site were a new target. The set of rules:
+
+ %.o : %.c :; rule for making .o from .c
+ %.c : %.y :; rule for making .c from .y
+ % : RCS/%,v :; check out of RCS file
+
+ will, by performing transitive closure, allow dmake to
+ infer how to make a .o from a .y using a .c as an interme-
+ diate temporary file. Additionally it will be able to
+ infer how to make a .y from an RCS file, as long as that
+ RCS file is in the RCS directory and has a name which ends
+ in .y,v. The transitivity computation is performed dynam-
+ ically for each target that does not have a recipe. This
+ has potential to be costly if the %-meta rules are not
+ carefully specified. The .NOINFER attribute is used to
+
+
+
+Version 4.01 PL0 UW 45
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ mark a %-meta node as being a final target during infer-
+ ence. Any node with this attribute set will not be used
+ for subsequent inferences. As an example the node RCS/%,v
+ is marked as a final node since we know that if the RCS
+ file does not exist there likely is no other way to make
+ it. Thus the standard startup makefile contains an entry
+ similar to:
+ .NOINFER : RCS/%,v
+ Thereby indicating that the RCS file is the end of the
+ inference chain. Whenever the inference algorithm deter-
+ mines that a target can be made from more than one prereq-
+ uisite and the inference chains for the two methods are
+ the same length the algorithm reports an ambiguity and
+ prints the ambiguous inference chains.
+
+ dmake tries to remove intermediate files resulting from
+ transitive closure if the file is not marked as being PRE-
+ CIOUS, or the -u flag was not given on the command line,
+ and if the inferred intermediate did not previously exist.
+ Intermediate targets that existed prior to being made are
+ never removed. This is in keeping with the philosophy
+ that dmake should never remove things from the file system
+ that it did not add. If the special target .REMOVE is
+ defined and has a recipe then dmake constructs a list of
+ the intermediate files to be removed and makes them pre-
+ requisites of .REMOVE. It then makes .REMOVE thereby
+ removing the prerequisites if the recipe of .REMOVE says
+ to. Typically .REMOVE is defined in the startup file as:
+
+ .REMOVE :; $(RM) $<
+
+MAKING TARGETS
+ In order to update a target dmake must execute a recipe.
+ When a recipe needs to be executed it is first expanded so
+ that any macros in the recipe text are expanded, and it is
+ then either executed directly or passed to a shell. dmake
+ supports two types of recipes. The regular recipes and
+ group recipes.
+
+ When a regular recipe is invoked dmake executes each line
+ of the recipe separately using a new copy of a shell if a
+ shell is required. Thus effects of commands do not gener-
+ ally persist across recipe lines (e.g. cd requests in a
+ recipe line do not carry over to the next recipe line).
+ This is true even in environments such as MSDOS, where
+ dmake internally sets the current working director to
+ match the directory it was in before the command was exe-
+ cuted.
+
+ The decision on whether a shell is required to execute a
+ command is based on the value of the macro SHELLMETAS or
+ on the specification of '+' or .USESHELL for the current
+ recipe or target respectively. If any character in the
+ value of SHELLMETAS is found in the expanded recipe text-
+
+
+
+Version 4.01 PL0 UW 46
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ line or the use of a shell is requested explicitly via '+'
+ or .USESHELL then the command is executed using a shell,
+ otherwise the command is executed directly. The shell
+ that is used for execution is given by the value of the
+ macro SHELL. The flags that are passed to the shell are
+ given by the value of SHELLFLAGS. Thus dmake constructs
+ the command line:
+
+ $(SHELL) $(SHELLFLAGS) $(expanded_recipe_command)
+
+ Normally dmake writes the command line that it is about to
+ invoke to standard output. If the .SILENT attribute is
+ set for the target or for the recipe line (via @), then
+ the recipe line is not echoed.
+
+ Group recipe processing is similar to that of regular
+ recipes, except that a shell is always invoked. The shell
+ that is invoked is given by the value of the macro GROUP-
+ SHELL, and its flags are taken from the value of the macro
+ GROUPFLAGS. If a target has the .PROLOG attribute set
+ then dmake prepends to the shell script the recipe associ-
+ ated with the special target .GROUPPROLOG, and if the
+ attribute .EPILOG is set as well, then the recipe associ-
+ ated with the special target .GROUPEPILOG is appended to
+ the script file. This facility can be used to always
+ prepend a common header and common trailer to group
+ recipes. Group recipes are echoed to standard output just
+ like standard recipes, but are enclosed by lines beginning
+ with [ and ].
+
+ The recipe flags [+,-,%,@] are recognized at the start of
+ a recipe line even if they appear in a macro. For exam-
+ ple:
+
+ SH = +
+ all:
+ $(SH)echo hi
+
+ is completely equivalent to writing
+
+ SH = +
+ all:
+ +echo hi
+
+
+ The last step performed by dmake prior to running a recipe
+ is to set the macro CMNDNAME to the name of the command to
+ execute (determined by finding the first white-space end-
+ ing token in the command line). It then sets the macro
+ CMNDARGS to be the remainder of the line. dmake then
+ expands the macro COMMAND which by default is set to
+
+ COMMAND = $(CMNDNAME) $(CMNDARGS)
+
+
+
+
+Version 4.01 PL0 UW 47
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ The result of this final expansion is the command that
+ will be executed. The reason for this expansion is to
+ allow for a different interface to the argument passing
+ facilities (esp. under DOS) than that provided by dmake.
+ You can for example define COMMAND to be
+
+ COMMAND = $(CMNDNAME) @$(mktmp $(CMNDARGS))
+
+ which dumps the arguments into a temporary file and runs
+ the command
+
+ $(CMNDNAME) @/tmp/ASAD23043
+
+ which has a much shorter argument list. It is now up to
+ the command to use the supplied argument as the source for
+ all other arguments. As an optimization, if COMMAND is
+ not defined dmake does not perform the above expansion.
+ On systems, such as UNIX, that handle long command lines
+ this provides a slight saving in processing the makefiles.
+
+MAKING LIBRARIES
+ Libraries are easy to maintain using dmake. A library is
+ a file containing a collection of object files. Thus to
+ make a library you simply specify it as a target with the
+ .LIBRARY attribute set and specify its list of prerequi-
+ sites. The prerequisites should be the object members
+ that are to go into the library. When dmake makes the
+ library target it uses the .LIBRARY attribute to pass to
+ the prerequisites the .LIBMEMBER attribute and the name of
+ the library. This enables the file binding mechanism to
+ look for the member in the library if an appropriate
+ object file cannot be found. dmake now supports Elf
+ libraries on systems that support Elf and hence supports,
+ on those systems, long member file names. A small example
+ best illustrates this.
+
+ mylib.a .LIBRARY : mem1.o mem2.o mem3.o
+ rules for making library...
+ # remember to remove .o's when lib is made
+
+ # equivalent to: '%.o : %.c ; ...'
+ .c.o :; rules for making .o from .c say
+
+ dmake will use the .c.o rule for making the library mem-
+ bers if appropriate .c files can be found using the search
+ rules. NOTE: this is not specific in any way to C pro-
+ grams, they are simply used as an example.
+
+ dmake tries to handle the old library construct format in
+ a sensible way. The construct lib(member.o) is separated
+ and the lib portion is declared as a library target. The
+ new target is defined with the .LIBRARY attribute set and
+ the member.o portion of the construct is declared as a
+ prerequisite of the lib target. If the construct
+
+
+
+Version 4.01 PL0 UW 48
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ lib(member.o) appears as a prerequisite of a target in the
+ makefile, that target has the new name of the lib assigned
+ as its prerequisite. Thus the following example:
+
+ a.out : ml.a(a.o) ml.a(b.o); $(CC) -o $@ $<
+
+ .c.o :; $(CC) -c $(CFLAGS) -o $@ $<
+ %.a:
+ ar rv $@ $?
+ ranlib $@
+ rm -rf $?
+
+ constructs the following dependency graph.
+
+ a.out : ml.a; $(CC) -o $@ $<
+ ml.a .LIBRARY : a.o b.o
+
+ %.o : %.c ; $(CC) -c $(CFLAGS) -o $@ $<
+ %.a :
+ ar rv $@ $?
+ ranlib $@
+ rm -rf $?
+
+ and making a.out then works as expected.
+
+ The same thing happens for any target of the form
+ lib((entry)). These targets have an additional feature in
+ that the entry target has the .SYMBOL attribute set auto-
+ matically.
+
+ NOTE: If the notion of entry points is supported by the
+ archive and by dmake (currently not the case) then dmake
+ will search the archive for the entry point and return not
+ only the modification time of the member which defines the
+ entry but also the name of the member file. This name
+ will then replace entry and will be used for making the
+ member file. Once bound to an archive member the .SYMBOL
+ attribute is removed from the target. This feature is
+ presently disabled as there is little standardization
+ among archive formats, and we have yet to find a makefile
+ utilizing this feature (possibly due to the fact that it
+ is unimplemented in most versions of UNIX Make).
+
+ Finally, when dmake looks for a library member it must
+ first locate the library file. It does so by first look-
+ ing for the library relative to the current directory and
+ if it is not found it then looks relative to the current
+ value of $(TMD). This allows commonly used libraries to
+ be kept near the root of a source tree and to be easily
+ found by dmake.
+
+KEEP STATE
+ dmake supports the keeping of state information for tar-
+ gets that it makes whenever the macro .KEEP_STATE is
+
+
+
+Version 4.01 PL0 UW 49
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ assigned a value. The value of the macro should be the
+ name of a state file that will contain the state informa-
+ tion. If state keeping is enabled then each target that
+ does not poses the .NOSTATE attribute will have a record
+ written into the state file indicating the target's name,
+ the current directory, the command used to update the tar-
+ get, and which, if any, :: rule is being used. When you
+ make this target again if any of this information does not
+ match the previous settings and the target is not out
+ dated it will still be re-made. The assumption is that
+ one of the conditions above has changed and that we wish
+ to remake the target. For example, state keeping is used
+ in the maintenance of dmake to test compile different ver-
+ sions of the source using different compilers. Changing
+ the compiler causes the compilation flags to be modified
+ and hence all sources to be recompiled.
+
+ The state file is an ascii file and is portable, however
+ it is not in human readable form as the entries represent
+ hash keys of the above information.
+
+ The Sun Microsystem's Make construct
+
+ .KEEP_STATE :
+
+ is recognized and is mapped to .KEEP_STATE:=_state.mk.
+ The dmake version of state keeping does not include scan-
+ ning C source files for dependencies like Sun Make. This
+ is specific to C programs and it was felt that it does not
+ belong in make. dmake instead provides the tool, cdepend,
+ to scan C source files and to produce depedency informa-
+ tion. Users are free to modify cdepend to produce other
+ dependency files. (NOTE: cdepend does not come with the
+ distribution at this time, but will be available in a
+ patch in the near future)
+
+MULTI PROCESSING
+ If the architecture supports it then dmake is capable of
+ making a target's prerequisites in parallel. dmake will
+ make as much in parallel as it can and use a number of
+ child processes up to the maximum specified by MAXPROCESS
+ or by the value supplied to the -P command line flag. A
+ parallel make is enabled by setting the value of MAXPRO-
+ CESS (either directly or via -P option) to a value which
+ is > 1. dmake guarantees that all dependencies as speci-
+ fied in the makefile are honored. A target will not be
+ made until all of its prerequisites have been made. Note
+ that when you specify -P 4 then four child processes are
+ run concurrently but dmake actually displays the fifth
+ command it will run immediately upon a child process
+ becomming free. This is an artifact of the method used to
+ traverse the dependency graph and cannot be removed. If a
+ parallel make is being performed then the following
+ restrictions on parallelism are enforced.
+
+
+
+Version 4.01 PL0 UW 50
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ 1. Individual recipe lines in a non-group
+ recipe are performed sequentially in the
+ order in which they are specified within the
+ makefile and in parallel with the recipes of
+ other targets.
+
+ 2. If a target contains multiple recipe defini-
+ tions (cf. :: rules) then these are per-
+ formed sequentially in the order in which
+ the :: rules are specified within the make-
+ file and in parallel with the recipes of
+ other targets.
+
+ 3. If a target rule contains the `!' modifier,
+ then the recipe is performed sequentially
+ for the list of outdated prerequisites and
+ in parallel with the recipes of other tar-
+ gets.
+
+ 4. If a target has the .SEQUENTIAL attribute
+ set then all of its prerequisites are made
+ sequentially relative to one another (as if
+ MAXPROCESS=1), but in parallel with other
+ targets in the makefile.
+
+ Note: If you specify a parallel make then the order of
+ target update and the order in which the associated
+ recipes are invoked will not correspond to that displayed
+ by the -n flag.
+
+CONDITIONALS
+ dmake supports a makefile construct called a conditional.
+ It allows the user to conditionally select portions of
+ makefile text for input processing and to discard other
+ portions. This becomes useful for writing makefiles that
+ are intended to function for more than one target host and
+ environment. The conditional expression is specified as
+ follows:
+
+ .IF expression
+ ... if text ...
+ .ELIF expression
+ ... if text ...
+ .ELSE
+ ... else text ...
+ .END
+
+ The .ELSE and .ELIF portions are optional, and the condi-
+ tionals may be nested (ie. the text may contain another
+ conditional). .IF, .ELSE, and .END may appear anywhere in
+ the makefile, but a single conditional expression may not
+ span multiple makefiles.
+
+ expression can be one of the following three forms:
+
+
+
+Version 4.01 PL0 UW 51
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ <text> | <text> == <text> | <text> != <text>
+
+ where text is either text or a macro expression. In any
+ case, before the comparison is made, the expression is
+ expanded. The text portions are then selected and com-
+ pared. White space at the start and end of the text por-
+ tion is discarded before the comparison. This means that
+ a macro that evaluates to nothing but white space is con-
+ sidered a NULL value for the purpose of the comparison.
+ In the first case the expression evaluates TRUE if the
+ text is not NULL otherwise it evaluates FALSE. The
+ remaining two cases both evaluate the expression on the
+ basis of a string comparison. If a macro expression needs
+ to be equated to a NULL string then compare it to the
+ value of the macro $(NULL). You can use the $(shell ...)
+ macro to construct more complex test expressions.
+
+EXAMPLES
+ # A simple example showing how to use make
+ #
+ prgm : a.o b.o
+ cc a.o b.o -o prgm
+ a.o : a.c g.h
+ cc a.c -o $@
+ b.o : b.c g.h
+ cc b.c -o $@
+
+ In the previous example prgm is remade only if a.o and/or
+ b.o is out of date with respect to prgm. These dependen-
+ cies can be stated more concisely by using the inference
+ rules defined in the standard startup file. The default
+ rule for making .o's from .c's looks something like this:
+
+ %.o : %.c; cc -c $(CFLAGS) -o $@ $<
+
+ Since there exists a rule (defined in the startup file)
+ for making .o's from .c's dmake will use that rule for
+ manufacturing a .o from a .c and we can specify our depen-
+ dencies more concisely.
+
+ prgm : a.o b.o
+ cc -o prgm $<
+ a.o b.o : g.h
+
+ A more general way to say the above using the new macro
+ expansions would be:
+
+ SRC = a b
+ OBJ = {$(SRC)}.o
+
+ prgm : $(OBJ)
+ cc -o $@ $<
+
+ $(OBJ) : g.h
+
+
+
+Version 4.01 PL0 UW 52
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ If we want to keep the objects in a separate directory,
+ called objdir, then we would write something like this.
+
+ SRC = a b
+ OBJ = {$(SRC)}.o
+
+ prgm : $(OBJ)
+ cc $< -o $@
+
+ $(OBJ) : g.h
+ %.o : %.c
+ $(CC) -c $(CFLAGS) -o $(@:f) $<
+ mv $(@:f) objdir
+
+ .SOURCE.o : objdir # tell dmake to look here for .o's
+
+ An example of building library members would go something
+ like this: (NOTE: The same rules as above will be used to
+ produce .o's from .c's)
+
+ SRC= a b
+ LIB= lib
+ LIBm= { $(SRC) }.o
+
+ prgm: $(LIB)
+ cc -o $@ $(LIB)
+
+ $(LIB) .LIBRARY : $(LIBm)
+ ar rv $@ $<
+ rm $<
+
+ Finally, suppose that each of the source files in the pre-
+ vious example had the `:' character in their target name.
+ Then we would write the above example as:
+
+ SRC= f:a f:b
+ LIB= lib
+ LIBm= "{ $(SRC) }.o" # put quotes around each token
+
+ prgm: $(LIB)
+ cc -o $@ $(LIB)
+
+ $(LIB) .LIBRARY : $(LIBm)
+ ar rv $@ $<
+ rm $<
+
+COMPATIBILITY
+ There are two notable differences between dmake and the
+ standard version of BSD UNIX 4.2/4.3 Make.
+
+ 1. BSD UNIX 4.2/4.3 Make supports wild card file-
+ name expansion for prerequisite names. Thus if
+ a directory contains a.h, b.h and c.h, then a
+ line like
+
+
+
+Version 4.01 PL0 UW 53
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ target: *.h
+
+ will cause UNIX make to expand the *.h into "a.h
+ b.h c.h". dmake does not support this type of
+ filename expansion.
+
+ 2. Unlike UNIX make, touching a library member
+ causes dmake to search the library for the mem-
+ ber name and to update the library time stamp.
+ This is only implemented in the UNIX version.
+ MSDOS and other versions may not have librarians
+ that keep file time stamps, as a result dmake
+ touches the library file itself, and prints a
+ warning.
+
+ dmake is not compatible with GNU Make. In particular it
+ does not understand GNU Make's macro expansions that query
+ the file system.
+
+ dmake is fully compatible with SYSV AUGMAKE, and supports
+ the following AUGMAKE features:
+
+ 1. GNU Make style include, and if/else/endif direc-
+ tives are allowed in non-group recipes. Thus,
+ the word include appearing at the start of a
+ line that is not part of a gruop recipe will be
+ mapped to the ".INCLUDE" directive that damke
+ uses. Similarly, the words
+ ifeq,ifneq,elif,else, and endif are mapped to
+ their corresponding dmake equivalents.
+
+ 2. The macro modifier expression $(macro:str=sub)
+ is understood and is equivalent to the expres-
+ sion $(macro:s/str/sub), with the restriction
+ that str must match the following regular
+ expression:
+
+ str[ |\t][ |\t]*
+
+ (ie. str only matches at the end of a token
+ where str is a suffix and is terminated by a
+ space, a tab, or end of line) Normally sub is
+ expanded before the substitution is made, if you
+ specify -A on the command line then sub is not
+ expanded.
+
+ 3. The macro % is defined to be $@ (ie. $% expands
+ to the same value as $@).
+
+ 4. The AUGMAKE notion of libraries is handled cor-
+ rectly.
+
+ 5. When defining special targets for the inference
+ rules and the AUGMAKE special target handling is
+
+
+
+Version 4.01 PL0 UW 54
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+ enabled then the special target .X is equivalent
+ to the %-rule "% : %.X".
+
+ 6. Directories are always made if you specify -A.
+ This is consistent with other UNIX versions of
+ Make.
+
+ 7. Makefiles that utilize virtual targets to force
+ making of other targets work as expected if AUG-
+ MAKE special target handling is enabled. For
+ example:
+
+ FRC:
+ myprog.o : myprog.c $(FRC) ; ...
+
+ Works as expected if you issue the command
+
+ 'dmake -A FRC=FRC'
+
+ but fails with a 'don't know how to make FRC'
+ error message if you do not specify AUGMAKE spe-
+ cial target handling via the -A flag (or by set-
+ ting AUGMAKE:=yes internally).
+
+ 8. The MSDOS version of dmake now supports a single
+ buitin runtime command noop, which returns suc-
+ cess if requested and does nothing.
+
+LIMITS
+ In some environments the length of an argument string is
+ restricted. (e.g. MSDOS command line arguments cannot be
+ longer than 128 bytes if you are using the standard com-
+ mand.com command interpreter as your shell, dmake text
+ diversions may help in these situations.)
+
+PORTABILITY
+ To write makefiles that can be moved from one environment
+ to another requires some forethought. In particular you
+ must define as macros all those things that may be differ-
+ ent in the new environment. dmake has two facilities that
+ help to support writing portable makefiles, recursive
+ macros and conditional expressions. The recursive macros,
+ allow one to define environment configurations that allow
+ different environments for similar types of operating sys-
+ tems. For example the same make script can be used for
+ SYSV and BSD but with different macro definitions.
+
+ To write a makefile that is portable between UNIX and
+ MSDOS requires both features since in almost all cases you
+ will need to define new recipes for making targets. The
+ recipes will probably be quite different since the capa-
+ bilities of the tools on each machine are different. Dif-
+ ferent macros will be needed to help handle the smaller
+ differences in the two environments.
+
+
+
+Version 4.01 PL0 UW 55
+
+
+
+
+
+DMAKE(p) Unsupported Free Software DMAKE(p)
+
+
+FILES
+ Makefile, makefile, startup.mk (use dmake -V to tell you
+ where the startup file is)
+
+SEE ALSO
+ sh(1), csh(1), touch(1), f77(1), pc(1), cc(1)
+ S.I. Feldman Make - A Program for Maintaining Computer
+ Programs
+
+AUTHOR
+ Dennis Vadura, dvadura@wticorp.com
+ Many thanks to Carl Seger for his helpful suggestions, and
+ to Trevor John Thompson for his many excellent ideas and
+ informative bug reports. Many thanks also go to those on
+ the NET that have helped in making dmake one of the best
+ Make tools available.
+
+BUGS
+ Some system commands return non-zero status inappropri-
+ ately. Use -i (`-' within the makefile) to overcome the
+ difficulty.
+
+ Some systems do not have easily accessible time stamps for
+ library members (MSDOS, AMIGA, etc) for these dmake uses
+ the time stamp of the library instead and prints a warning
+ the first time it does so. This is almost always ok,
+ except when multiple makefiles update a single library
+ file. In these instances it is possible to miss an update
+ if one is not careful.
+
+ This man page is way too long.
+
+WARNINGS
+ Rules supported by make(1) may not work if transitive clo-
+ sure is turned off (-T, .NOINFER).
+
+ PWD from csh/ksh will cause problems if a cd operation is
+ performed and -e or -E option is used.
+
+ Using internal macros such as COMMAND, may wreak havoc if
+ you don't understand their functionality.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Version 4.01 PL0 UW 56
+
+
diff --git a/dmake/man/dmake.tf b/dmake/man/dmake.tf
new file mode 100644
index 000000000000..582230c10cc1
--- /dev/null
+++ b/dmake/man/dmake.tf
@@ -0,0 +1,3152 @@
+.\" Copyright (c) 1990,...,1995 Dennis Vadura, All rights reserved.
+.\"
+.\" You must use groff to format this man page!!!
+.\"
+.ds TB "0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.2i +0.5i +0.5i +2.0i
+.de Ip
+.sp \\n[PD]u
+.fi
+.nr an-prevailing-indent (n;\w@\\$1 @u)
+.it 1 an-trap
+.if !\\n[an-div?] .di an-div
+.in 0
+.nr an-div? 1
+.nf
+\&\\$1 \\$2
+..
+.de Is
+.nr an-prevailing-indent \w@\\$1@u
+..
+.de Ii
+.fi
+.it 1 an-trap
+.if !\\n[an-div?] .di an-div
+.in 0
+.nr an-div? 1
+.nf
+\&\\$1
+..
+.TH DMAKE p "UW" "Version 4.01 PL0" "Unsupported Free Software"
+.SH NAME
+\fBdmake\fR \- maintain program groups, or interdependent files
+.SH SYNOPSIS
+.B dmake
+[\-P#] [\-{f|C|K} file] [\-{w|W} target ...]
+[macro[[!][*][+][:]]=\fIvalue\fP ...]
+[\-v{cdfimtw}] [\-ABcdeEghiknpqrsStTuVxX] [target ...]
+.SH DESCRIPTION
+.PP
+.B dmake
+is a re-implementation of the UNIX Make utility with significant enhancements.
+.B dmake
+executes commands found in an external file called a
+.I makefile
+to update one or more target names.
+Each target may depend on zero or more prerequisite targets.
+If any of the target's prerequisites is newer than the target or if the target
+itself does not exist, then
+.B dmake
+will attempt to make the target.
+.PP
+If no
+.B \-f
+command line option is present then
+.B dmake
+searches for an existing
+.I makefile
+from the list of prerequisites specified for the special target \fI.MAKEFILES\fR
+(see the STARTUP section for more details).
+If "\-" is the name of the file specified to the
+.B \-f
+flag then \fBdmake\fR uses standard input as the source of the makefile text.
+.PP
+Any macro definitions (arguments with embedded "="
+signs) that appear on the command line are processed first
+and supercede definitions for macros of the same name found
+within the makefile. In general it is impossible for definitions found
+inside the makefile to redefine a macro defined on the command line, see the
+MACROS section for exceptions.
+.PP
+If no
+.I target
+names are specified on the command line, then \fBdmake\fR uses the first
+non-special target found in the makefile as the default target.
+See the
+.B "SPECIAL TARGETS"
+section for the list of special targets and their function.
+Makefiles written for most previous
+versions of
+.I Make
+will be handled correctly by
+.B dmake.
+Known differences between \fBdmake\fR and other versions of make
+are discussed in the
+.B COMPATIBILITY
+section found at the end of this document.
+.B dmake
+returns 0 if no errors were detected and a non-zero result if an error
+occurred.
+.SH OPTIONS
+.IP "\fB\-A\fR"
+Enable AUGMAKE special inference rule transformations
+(see the "PERCENT(%) RULES" section), these are set to off by default.
+.IP "\fB\-B\fR"
+Enable the use of spaces instead of <tabs> to begin recipe lines.
+This flag equivalent to the .NOTABS special macro and is further described
+below.
+.IP "\fB\-c\fR"
+Use non-standard comment stripping. If you specify \fB\-c\fP then
+.B dmake
+will treat any \fB#\fP character as a start of comment character wherever it
+may appear unless it is escaped by a \e.
+.IP "\fB\-C [+]file\fR"
+This option writes to \fIfile\fP a copy of standard output and
+standard error from any child processes and from the
+.B dmake
+process itself. If you specify a \fB+\fP prior to the file name then
+the text is appended to the previous contents of \fIfile\fP.
+This option is active in the MSDOS implementation only and is ignored
+by non-MSDOS versions of
+.B dmake.
+.IP "\fB\-d\fR"
+Disable the use of the directory cache. Normally \fBdmake\fP caches directories
+as it checks file timestamps. Giving this flag is equivalent to the
+\&.DIRCACHE attribute or macro being set to \fIno\fP.
+.IP "\fB\-E\fR"
+Read the environment and define all strings of the
+form '\fBENV\-VAR\fP=\fIevalue\fP'
+defined within as macros whose name is \fBENV\-VAR\fP,
+and whose value is '\fIevalue\fP'.
+The environment is processed prior to processing the user
+specified makefile thereby allowing definitions in the makefile to override
+definitions in the environment.
+.IP "\fB\-e\fR"
+Same as \-E, except that the environment is processed after the
+user specified makefile has been processed
+(thus definitions in the environment override definitions in the makefile).
+The \-e and \-E options are mutually exclusive.
+If both are given the latter takes effect.
+.IP "\fB\-f file\fR"
+Use \fBfile\fR as the source for the makefile text.
+Only one \fB\-f\fR option is allowed.
+.IP "\fB\-g\fR"
+Globally disable group recipe parsing, equivalent to the .IGNOREGROUP
+attribute or macro being set to \fIyes\fP at the start of the makefile.
+.IP "\fB\-h\fR"
+Print the command summary for \fBdmake\fR.
+.IP "\fB\-i\fR"
+Tells \fBdmake\fR to ignore errors, and continue making other targets.
+This is equivalent to the .IGNORE attribute or macro.
+.IP "\fB\-K file\fR"
+Turns on \fB.KEEP_STATE\fP state tracking and tells \fBdmake\fP to use
+\fIfile\fP as the state file.
+.IP "\fB\-k\fR"
+Causes \fBdmake\fR to ignore errors caused by command execution and to make
+all targets not depending on targets that could not be made.
+Ordinarily \fBdmake\fR stops after a command returns a non-zero status,
+specifying \fB\-k\fR causes \fBdmake\fR to ignore the error
+and continue to make as much as possible.
+.IP "\fB\-n\fR"
+Causes \fBdmake\fR to print out what it would have executed,
+but does not actually execute the commands. A special check is made for
+the string "$(MAKE)" inside a recipe line, if it is found,
+the line is expanded and invoked, thereby enabling recursive makes to give a
+full description of all that they will do.
+This check is disabled inside group recipes.
+.IP "\fB\-p\fR"
+Print out a version of the digested makefile in human readable form.
+(useful for debugging, but cannot be re-read by \fBdmake\fP)
+.IP "\fB\-P#\fR"
+On systems that support multi-processing cause \fBdmake\fP to use \fI#\fP
+concurrent child processes to make targets.
+See the "MULTI PROCESSING" section for more information.
+.IP "\fB\-q\fR"
+Check and see if the target is up to date. Exits with code 0 if up to date,
+1 otherwise.
+.IP "\fB\-r\fR"
+Tells \fBdmake\fR not to read the initial startup makefile, see STARTUP
+section for more details.
+.IP "\fB\-s\fR"
+Tells \fBdmake\fR to do all its work silently and not echo the commands it is
+executing to stdout (also suppresses warnings).
+This is equivalent to the .SILENT attribute or macro.
+.IP "\fB\-S\fR"
+Force sequential execution of recipes on architectures which support
+concurrent makes. For backward compatibility with old makefiles that have
+nasty side-effect prerequisite dependencies.
+.IP "\fB\-t\fR"
+Causes \fBdmake\fR to touch the targets and bring them up to date
+without executing any commands.
+Note that targets will not be created if they do not already exist.
+.IP "\fB\-T\fR"
+Tells \fBdmake\fP to not perform transitive closure on the inference graph.
+.IP "\fB\-u\fR"
+Force an unconditional update. (ie. do everything that would
+be done if everything that a target depended on was out of date)
+.IP "\fB\-v[dfimtw]\fR"
+Verbose flag, when making targets print to stdout what we are going to make
+and what we think its time stamp is. The optional flags \fB[dfimt]\fP can be
+used to restrict the information that is displayed. In the absence of any
+optional flags all are assumed to be given (ie. \fB\-v\fP is equivalent to
+\fB\-vdfimt\fP). The meanings of the optional flags are:
+.RS
+.IP "\fBc\fP"
+Notify of directory cache operations only.
+.IP "\fBd\fP"
+Notify of change directory operations only.
+.IP "\fBf\fP"
+Notify of file I/O operations only.
+.IP "\fBi\fP"
+Notify of inference algorithm operation only.
+.IP "\fBm\fP"
+Notify of target update operations only.
+.IP "\fBt\fP"
+Keep any temporary files created; normally they are automatically deleted.
+.IP "\fBw\fP"
+Notify of non-essential warnings (these are historical).
+.RE
+.IP "\fB\-V\fR"
+Print the version of \fBdmake\fR, and values of builtin macros.
+.IP "\fB\-W target\fR"
+Run \fBdmake\fP pretending that \fItarget\fP is out of date.
+.IP "\fB\-w target\fR"
+\fIWhat if?\fP Show what would be made if \fItarget\fP were out of date.
+.IP "\fB\-x\fR"
+Upon processing the user makefile export all non-internally defined macros
+to the user's environment. This option together with the \-e option
+allows SYSV AUGMAKE recursive makes to function as expected.
+.IP "\fB\-X\fR"
+Inhibit the execution of \fB#!\fP lines found at the beginning of a makefile.
+The use of this flag prevents non-termination of recursive make invocations.
+.SH INDEX
+Here is a list of the sections that follow and a short description of each.
+Perhaps you won't have to read the entire man page to find
+what you need.
+.IP \fBSTARTUP\fP 1.9i
+Describes \fBdmake\fP initialization.
+.IP \fBSYNTAX\fP 1.9i
+Describes the syntax of makefile expressions.
+.IP \fBATTRIBUTES\fP 1.9i
+Describes the notion of attributes and how they are used when
+making targets.
+.IP \fBMACROS\fP 1.9i
+Defining and expanding macros.
+.IP "\fBRULES AND TARGETS" 1.9i
+How to define targets and their prerequisites.
+.IP \fBRECIPES\fP 1.9i
+How to tell \fBdmake\fP how to make a target.
+.IP "\fBTEXT DIVERSIONS\fP" 1.9i
+How to use text diversions in recipes and macro expansions.
+.IP "\fBSPECIAL TARGETS\fP" 1.9i
+Some targets are special.
+.IP "\fBSPECIAL MACROS\fP" 1.9i
+Macros used by \fBdmake\fP to alter the processing of the makefile,
+and those defined by \fBdmake\fP for the user.
+.IP "\fBCONTROL MACROS\fP" 1.9i
+Itemized list of special control macros.
+.IP "\fBRUNTIME MACROS\fP" 1.9i
+Discussion of special run-time macros such as $@ and $<.
+.IP "\fBFUNCTION MACROS\fP" 1.9i
+GNU style function macros, only $(mktmp ...) for now.
+.IP "\fBCONDITIONAL MACROS\fP" 1.9i
+Target specific conditional macros.
+.IP "\fBDYNAMIC PREREQUISITES\fP" 1.9i
+Processing of prerequisites which contain macro expansions in their name.
+.IP "\fBBINDING TARGETS\fP" 1.9i
+The rules that \fBdmake\fP uses to bind
+a target to an existing file in the file system.
+.IP "\fBPERCENT(%) RULES\fP" 1.9i
+Specification of recipes to be used by the inference algorithm.
+.IP "\fBMAKING INFERENCES\fP" 1.9i
+The rules that \fBdmake\fP uses when inferring how to make a target which
+has no explicit recipe. This and the previous section are really a single
+section in the text.
+.IP "\fBMAKING TARGETS\fP" 1.9i
+How \fBdmake\fP makes targets other than libraries.
+.IP "\fBMAKING LIBRARIES\fP" 1.9i
+How \fBdmake\fP makes libraries.
+.IP "\fBKEEP STATE\fP" 1.9i
+A discussion of how .KEEP_STATE works.
+.IP "\fBMULTI PROCESSING\fP" 1.9i
+Discussion of \fBdmake's\fP parallel make facilities for architectures that
+support them.
+.IP "\fBCONDITIONALS\fP" 1.9i
+Conditional expressions which control the processing of the makefile.
+.IP "\fBEXAMPLES\fP" 1.9i
+Some hopefully useful examples.
+.IP "\fBCOMPATIBILITY\fP" 1.9i
+How \fBdmake\fP compares with previous versions of make.
+.IP "\fBLIMITS\fP" 1.9i
+Limitations of \fBdmake\fP.
+.IP \fBPORTABILITY\fP 1.9i
+Comments on writing portable makefiles.
+.IP \fBFILES\fP 1.9i
+Files used by \fBdmake\fP.
+.IP "\fBSEE ALSO\fP" 1.9i
+Other related programs, and man pages.
+.IP "\fBAUTHOR\fP" 1.9i
+The guy responsible for this thing.
+.IP \fBBUGS\fP 1.9i
+Hope not.
+.SH STARTUP
+When
+.B dmake
+begins execution it first processes the command line and then processes
+an initial startup-makefile.
+This is followed by an attempt to locate and process a user supplied makefile.
+The startup file defines the default values of all required control macros
+and the set of default rules for making targets and inferences.
+When searching for the startup makefile,
+.B dmake
+searches the following locations, in the order specified,
+until a startup file is located:
+.LP
+.RS
+.IP 1.
+The location given as the value of the macro
+MAKESTARTUP defined on the command line.
+.IP 2.
+The location given as the value of the environment variable MAKESTARTUP
+defined in the current environment.
+.IP 3.
+The location given as the value of the macro
+MAKESTARTUP defined internally within \fBdmake\fP.
+.RE
+.LP
+The above search is disabled by specifying the \-r option on the command line.
+An error is issued if a startup makefile cannot be found and the \-r
+option was not specified.
+A user may substitute a custom startup file by defining
+the MAKESTARTUP environment variable or by redefining the
+MAKESTARTUP macro on the command line.
+To determine where
+.B dmake
+looks for the default startup file, check your environment or issue the command
+\fI"dmake \-V"\fP.
+.PP
+A similar search is performed to locate a default user makefile when no
+\fB\-f\fP command line option is specified.
+By default, the prerequisite list of the special target .MAKEFILES
+specifies the names of possible makefiles and the search order that
+\fBdmake\fP should use to determine if one exists.
+A typical definition for this target is:
+.RS
+.sp
+\&.MAKEFILES : makefile.mk Makefile makefile
+.sp
+.RE
+\fBdmake\fP will first look for makefile.mk and then the others.
+If a prerequisite
+cannot be found \fBdmake\fP will try to make it before going on to the next
+prerequisite. For example, makefile.mk can be checked out of an RCS file
+if the proper rules for doing so are defined in the startup file.
+.PP
+If the first line of the user makefile is of the form:
+.RS
+.sp
+\#! command command_args
+.sp
+.RE
+then \fBdmake\fP will expand and run the command prior to reading any
+additional input. If the return code of the command is zero then \fBdmake\fP
+will continue on to process the remainder of the user makefile, if the return
+code is non-zero then dmake will exit.
+.PP
+\fBdmake\fP builds the internal dependency graph as it parses a user specified
+makefile. The graph is rooted at the special target \fB.ROOT\fP. .ROOT is the
+top level target that dmake builds when it starts to build targets. All user
+specified targets (those from the command line or taken as defaults from
+the makefile) are made prerequisites of the special target \fB.TARGETS\fP.
+\fBdmake\fP by default creates the relationship that .ROOT depends on .TARGETS
+and as a result everything is made. This approach allows the user to customize, within
+their makefile, the order and which, target, is built first. For example the
+default makefiles come with settings for .ROOT that specify:
+.sp
+.RS
+\&.ROOT .PHONY .NOSTATE .SEQUENTIAL : .INIT .TARGETS .DONE
+.RE
+.sp
+with .INIT and .DONE defined as:
+.sp
+.RS
+\&.INIT .DONE .PHONY:;
+.RE
+.sp
+which nicely emulates the behaviour of Sun's make extensions. The building of
+\&.ROOT's prerequisites is always forced to be sequential. However, this
+definition is trivially chaned by supplying the definition:
+.sp
+.RS
+\&.ROOT : .TARGETS
+.RE
+.sp
+which skips the preamble and postamble phases of building .TARGETS.
+.SH SYNTAX
+This section is a summary of the syntax of makefile statements.
+The description is given in a style similar to BNF, where { } enclose
+items that may appear zero or more times, and [ ] enclose items that
+are optional. Alternative productions for a left hand side are indicated
+by '\(->', and newlines are significant. All symbols in \fBbold\fP type
+are text or names representing text supplied by the user.
+.sp 2
+.RS
+.Ip "Makefile" "\(-> { Statement }"
+.Ip "Statement" "\(-> Macro-Definition"
+\(-> Conditional-Macro-Definition
+\(-> Conditional
+\(-> Rule-Definition
+\(-> Attribute-Definition
+.Ip "Macro-Definition" "\(-> \fBMACRO = LINE\fP"
+\(-> \fBMACRO [\fB!\fR]*= LINE\fP
+\(-> \fBMACRO [\fB!\fR]:= LINE\fP
+\(-> \fBMACRO [\fB!\fR]*:= LINE\fP
+\(-> \fBMACRO [\fB!\fR]+= LINE\fP
+\(-> \fBMACRO [\fB!\fR]+:= LINE\fP
+.Ip "Conditional-Macro-Definition \(-> " "\fBTARGET\fP ?= Macro-Definition"
+.Ip "Conditional \(-> " "\fB\&.IF\fR expression"
+ Makefile
+[ \fB.ELIF\fR expression
+ Makefile ]
+[ \fB.ELSE\fR
+ Makefile ]
+\fB\&.END\fR
+.Ip "expression" "\(-> \fBLINE\fR"
+\(-> \fBSTRING == LINE\fR
+\(-> \fBSTRING != LINE\fR
+.Ip "Rule-Definition \(-> " "target-definition"
+ [ recipe ]
+.PP
+target-definition \(-> targets [attrs] op { \fBPREREQUISITE\fP } [\fB;\fR rcp-line]
+.Ip "targets" "\(-> target { targets }"
+\(-> \fB"\fRtarget\fB"\fR { targets }
+.Ip "target" "\(-> special-target"
+\(-> \fBTARGET\fR
+.Ip "attrs" "\(-> attribute { attrs }"
+\(-> \fB"\fRattribute\fB"\fR { attrs }
+.Ip "op" "\(-> \fB:\fR { modifier }"
+.Ip "modifier" "\(-> \fB:\fR"
+\(-> \fB^\fR
+\(-> \fB!\fR
+\(-> \fB\-\fR
+\(-> \fB|\fR
+.Ip "recipe" "\(-> { \fBTAB\fR rcp-line }"
+\(-> [\fB@\fR][\fB%\fR][\fB\-\fR] \fB[
+.Is "recipe \(-> "
+.Ii " "
+ \fR{ \fBLINE\fR }
+.Ii " "
+\fB]\fR
+.Ip "rcp-line" "\(-> [\fB@\fR][\fB%\fR][\fB\-\fR][\fB+\fR] \fBLINE\fR"
+.Ip Attribute-Definition "\(-> attrs \fB:\fR targets"
+.Ip attribute "\(-> \fB.EPILOG\fR"
+\(-> \fB.ERRREMOVE\fR
+\(-> \fB.EXECUTE\fR
+\(-> \fB.GROUP\fR
+\(-> \fB.IGNORE\fR
+\(-> \fB.IGNOREGROUP\fR
+\(-> \fB.LIBRARY\fR
+\(-> \fB.MKSARGS\fR
+\(-> \fB.NOINFER\fR
+\(-> \fB.NOSTATE\fR
+\(-> \fB.PHONY\fR
+\(-> \fB.PRECIOUS\fR
+\(-> \fB.PROLOG\fR
+\(-> \fB.SETDIR=\fIpath\fP\fR
+\(-> \fB.SILENT\fR
+\(-> \fB.SEQUENTIAL\fR
+\(-> \fB.SWAP\fR
+\(-> \fB.USESHELL\fR
+\(-> \fB.SYMBOL\fR
+\(-> \fB.UPDATEALL\fR
+.Ip "special-target" "\(-> \fB.ERROR\fR"
+\(-> \fB.EXIT\fR
+\(-> \fB.EXPORT\fR
+\(-> \fB.GROUPEPILOG\fR
+\(-> \fB.GROUPPROLOG\fR
+\(-> \fB.IMPORT\fR
+\(-> \fB.INCLUDE\fR
+\(-> \fB.INCLUDEDIRS\fR
+\(-> \fB.MAKEFILES\fR
+\(-> \fB.REMOVE\fR
+\(-> \fB.SOURCE\fR
+\(-> \fB.SOURCE.\fIsuffix\fR
+\(-> .\fIsuffix1\fR.\fIsuffix2\fR
+.fi
+.RE
+.sp 1
+.PP
+Where, \fBTAB\fP represents a <tab> character, \fBSTRING\fP represents an
+arbitrary sequence of characters, and
+\fBLINE\fP represents a
+possibly empty sequence of characters terminated by a non-escaped
+(not immediately preceded by a backslash '\e') new-line character.
+\fBMACRO\fP, \fBPREREQUISITE\fP,
+and \fBTARGET\fP each represent a string of characters not
+including space or tab which respectively form the name of a macro,
+prerequisite or target.
+The name may itself be a macro expansion expression.
+A \fBLINE\fP can be continued over several physical lines by terminating it with
+a single backslash character. Comments are initiated by the
+pound \fB#\fR character and extend to the end of line.
+All comment text is discarded, a '#' may be placed into the makefile text
+by escaping it with '\e' (ie. \e# translates to # when it is parsed).
+An exception to this occurs when a # is seen inside
+a recipe line that begins with a <tab> or is inside a group recipe.
+If you specify the \fB\-c\fP command line switch then this behavior is
+disabled and
+.B dmake
+will treat all # characters as start of comment indicators unless they
+are escaped by \e.
+A set of continued lines may be commented out by placing a single # at the
+start of the first line.
+A continued line cannot span more than one makefile.
+.PP
+\fBwhite space\fP is defined to be any combination of
+<space>, <tab>, and the sequence \e<nl>
+when \e<nl> is used to terminate a LINE.
+When processing \fBmacro\fP definition lines,
+any amount of white space is allowed on either side of the macro operator
+and white space is stripped from both before and after the macro
+value string.
+The sequence \e<nl> is treated as white space during recipe expansion
+and is deleted from the final recipe string.
+You must escape the \e<nl> with another \e in order to get a \e at the end
+of a recipe line.
+The \e<nl> sequence is deleted from macro values when they are expanded.
+.PP
+When processing \fBtarget\fP definition lines,
+the recipe for a target must, in general, follow the first definition
+of the target (See the RULES AND TARGETS section for an exception), and
+the recipe may not span across multiple makefiles.
+Any targets and prerequisites found on a target definition line are taken
+to be white space separated tokens.
+The rule operator (\fIop\fP in SYNTAX section) is also considered
+to be a token but does not require
+white space to precede or follow it. Since the rule operator begins with a `:',
+traditional versions of make do not allow the `:' character to
+form a valid target name. \fBdmake\fP allows `:' to be present in
+target/prerequisite names as long as the entire target/prerequisite name is
+quoted. For example:
+.sp
+\ta:fred : test
+.sp
+would be parsed as TARGET = a, PREREQUISITES={fred, :, test}, which
+is not what was intended. To fix this you must write:
+.sp
+\t"a:fred" : test
+.sp
+Which will be parsed as expected. Quoted target and prerequisite
+specifications may also contain white space thereby allowing the use of
+complex function macro expressions..
+See the EXAMPLES section for how to apply \fB"\fP quoting
+to a list of targets.
+.SH ATTRIBUTES
+.B dmake
+defines several target attributes. Attributes may be
+assigned to a single target, a group of targets, or to all targets in the
+makefile. Attributes are used to modify
+\fBdmake\fP actions during target update.
+The recognized attributes are:
+.sp
+.IP \fB.EPILOG\fP 1.2i
+Insert shell epilog code when executing a group recipe associated with
+any target having this attribute set.
+.IP \fB.ERRREMOVE\fP 1.2i
+Always remove any target having this attribute if an error is encountered
+while making them. Setting this attribute overrides the .PRECIOUS attribute.
+.IP \fB.EXECUTE\fP 1.2i
+If the \-n flag was given then execute the recipe associated with any
+target having this attribute set.
+.IP \fB.FIRST\fP 1.2i
+Used in conjunction with .INCLUDE. Terminates the inclusion with the first
+successfully included prerequisite.
+.IP \fB.GROUP\fP 1.2i
+Force execution of a target's recipe as a group recipe.
+.IP \fB.IGNORE\fP 1.2i
+Ignore an error when trying to make any target with this attribute set.
+.IP \fB.IGNOREGROUP\fP 1.2i
+Disable the special meaning of '[' to initiate a group recipe.
+.IP \fB.LIBRARY\fP 1.2i
+Target is a library.
+.IP \fB.MKSARGS\fP 1.2i
+If running in an MSDOS environment then use MKS extended argument passing
+conventions to pass arguments to commands. Non-MSDOS
+environments ignore this attribute.
+.IP \fB.NOINFER\fP 1.2i
+Any target with this attribute set will not be subjected
+to transitive closure if it is inferred as a prerequisite
+of a target whose recipe and prerequisites are being inferred.
+(i.e. the inference algorithm will not use any prerequisite with this attribute
+set, as a target)
+If specified as '.NOINFER:' (ie. with no prerequisites or targets) then the
+effect is equivalent to specifying \fB\-T\fP on the command line.
+.IP \fB.NOSTATE\fP 1.2i
+Any target with this attribute set will not have command line flag
+information stored in the state file if .KEEP_STATE has been enabled.
+.IP \fB.PHONY\fP 1.2i
+Any target with this attribute set will have its recipe executed
+each time the target is made even if a file matching the target name can
+be located. Any targets that have a .PHONY attributed target as a
+prerequisite will be made each time the .PHONY attributed prerequisite is
+made.
+.IP \fB.PRECIOUS\fP 1.2i
+Do not remove associated target under any circumstances.
+Set by default for any targets whose corresponding files exist in the file
+system prior to the execution of \fBdmake\fP.
+.IP \fB.PROLOG\fP 1.2i
+Insert shell prolog code when executing a group recipe associated with
+any target having this attribute set.
+.IP \fB.SEQUENTIAL\fP 1.2i
+Force a sequential make of the associated target's prerequisites.
+.IP \fB.SETDIR\fP 1.2i
+Change current working directory to specified directory when making the
+associated target. You must
+specify the directory at the time the attribute is specified. To do this
+simply give \fI.SETDIR=path\fP as the attribute. \fIpath\fP is expanded and
+the result is used as the value of the directory to change to.
+If \fIpath\fP contains \fB$$@\fP then the name of the target to be built is
+used in computing the path to change directory to.
+If path is surrounded by single quotes then path is not expanded, and is used
+literally as the directory name.
+If the \fIpath\fP contains any `:' characters then the entire attribute string
+must be quoted using ".
+If a target having this attribute set also has the .IGNORE
+attribute set then if the change to the specified directory fails it will be
+ignored, and no error message will be issued.
+.IP \fB.SILENT\fP 1.2i
+Do not echo the recipe lines when making any target with this attribute set,
+and do not issue any warnings.
+.IP \fB.SWAP\fP 1.2i
+Under MSDOS
+when making a target with this attribute set swap the \fBdmake\fP executable
+to disk prior to executing the recipe line. Also see the '%' recipe line
+flag defined in the RECIPES section.
+.IP \fB.SYMBOL\fP 1.2i
+Target is a library member and is an entry point into a module in the
+library. This attribute is used only when searching a library for a target.
+Targets of the form lib((entry)) have this attribute set automatically.
+.IP \fB.USESHELL\fP 1.2i
+Force each recipe line of a target to be executed using a shell.
+Specifying this attribute is equivalent to specifying the '+' character at the
+start of each line of a non-group recipe.
+.IP \fB.UPDATEALL\fP 1.2i
+Indicates that all the targets listed in this rule are updated by the
+execution of the accompanying recipe.
+A common example is the production of the
+.I y.tab.c
+and
+.I y.tab.h
+files by
+.B yacc
+when it is run on a grammar. Specifying .UPDATEALL in such a rule
+prevents the running of yacc twice, once for the y.tab.c file and once
+for the y.tab.h file. .UPDATEALL targets that are specified in a single rule
+are treated as a single target and all timestamps are updated whenever any
+target in the set is made. As a side-effect, \fBdmake\fP internally sorts
+such targets in ascending alphabetical order and the value of $@ is always
+the first target in the sorted set.
+.LP
+All attributes are user setable and except for .UPDATEALL, .SETDIR and .MKSARGS
+may be used in one of two forms.
+The .MKSARGS attribute is restricted to use as a global attribute, and
+the use of the .UPDATEALL and .SETDIR attributes is restricted to rules
+of the second form only.
+.sp
+\tATTRIBUTE_LIST : \fItargets\fP
+.sp
+assigns the attributes specified by ATTRIBUTE_LIST to each target in
+.I targets
+or
+.sp
+\t\fItargets\fP ATTRIBUTE_LIST : ...
+.sp
+assigns the attributes specified by ATTRIBUTE_LIST to each target in
+.I targets.
+In the first form if
+.I targets
+is empty (ie. a NULL list), then the
+list of attributes will apply to all targets in the makefile
+(this is equivalent to the common Make construct of \fI".IGNORE :"\fP
+but has been modified to the notion of an attribute instead of
+a special target).
+Not all of the attributes have global meaning.
+In particular, .LIBRARY, .NOSTATE, .PHONY, .SETDIR, .SYMBOL and .UPDATEALL
+have no assigned global meaning.
+.PP
+Any attribute may be used with any target, even with the special targets.
+Some combinations are useless (e.g. .INCLUDE .PRECIOUS: ... ),
+while others are useful (e.g. .INCLUDE .IGNORE : "file.mk" will not complain
+if file.mk cannot be found using the include file search rules,
+see the section on SPECIAL TARGETS for a description of .INCLUDE).
+If a specified attribute will not be used with the special target a warning
+is issued and the attribute is ignored.
+.SH MACROS
+.B dmake
+supports six forms of macro assignment.
+.sp
+.IP "\fBMACRO = LINE\fP" 1.55i
+This is the most common and familiar form of macro assignment. It assigns
+LINE literally as the value of MACRO.
+Future expansions of MACRO recursively expand its value.
+.IP "\fBMACRO *= LINE\fP" 1.55i
+This form behaves exactly as the simple '=' form with the exception that if
+MACRO already has a value then the assignment is not performed.
+.IP "\fBMACRO := LINE\fP" 1.55i
+This form differs from the simple '=' form in that it expands LINE
+prior to assigning it as the value of MACRO.
+Future expansions of MACRO do not recursively expand its value.
+.IP "\fBMACRO *:= LINE\fP" 1.55i
+This form behaves exactly as the ':=' form with the exception that if
+MACRO already has a value then the assignment and expansion are not performed.
+.IP "\fBMACRO += LINE\fP" 1.55i
+This form of macro assignment allows macro values to grow. It takes the
+literal value of LINE and appends it to the previous value of MACRO separating
+the two by a single space.
+Future expansions of MACRO recursively expand its value.
+.IP "\fBMACRO +:= LINE\fP" 1.55i
+This form is similar to the '+=' form except that the value of LINE is expanded
+prior to being added to the value of MACRO.
+.PP
+Macro expressions specified on the command line allow the macro value
+to be redefined within the makefile only if the macro is defined using
+the '+=' and '+:=' operators. Other operators will define a macro that cannot
+be further modified.
+.PP
+Each of the preceeding macro assignment operators may be prefixed by \fB!\fP
+to indicate that the assignment should be forced and that no warnings should
+be issued. Thus, specifying \fB!\fP has the effect of silently forcing the
+specified macro assignment.
+.PP
+When \fBdmake\fP defines a non-environment macro it strips leading and
+trailing white space from the macro value.
+Macros imported from the environment via either the .IMPORT special
+target (see the SPECIAL TARGETS section), or the \fB\-e\fP, or \fB\-E\fP flags
+are an exception to this rule. Their values are
+always taken literally and white space is never stripped.
+In addition, named macros defined using the .IMPORT special target do
+not have their values expanded when they are used within a makefile.
+In contrast, environment macros that are imported
+due to the specification of the \fB\-e\fP or \fB\-E\fP flags
+are subject to expansion when used.
+.PP
+To specify a macro expansion
+enclose the name in () or {} and precede it with a dollar sign $.
+Thus $(TEST) represents an expansion of the macro variable named TEST.
+If TEST is
+defined then $(TEST) is replaced by its expanded value. If TEST is not
+defined then $(TEST) expands to the NULL string (this is equivalent to
+defining a macro as 'TEST=' ). A short form may be used for single character
+named macros. In this case the parentheses are optional, and $(I) is
+equivalent to $I.
+Macro expansion is recursive, hence, if the value string contains an expression
+representing a macro expansion, the expansion is performed. Circular macro
+expansions are detected and cause an error to be issued.
+.PP
+When defining a macro the given macro name is first expanded before being used
+to define the macro. Thus it is possible to define macros whose names
+depend on values of other macros. For example, suppose CWD is defined as
+.sp
+\tCWD = $(PWD:b)
+.sp
+then the value of $(CWD) is the name of the current directory.
+This can be used to define macros specific to this directory, for
+example:
+.sp
+\t_$(CWD).prt = list of files to print...
+.sp
+The actual name of the defined macro is a function of the current directory.
+A construct such as this is useful when processing a hierarchy of directories
+using .SETDIR attributed targets and a collection of small distributed
+makefile stubs.
+.PP
+Macro variables may be defined within the makefile, on the command
+line, or imported from the environment.
+.PP
+.B \fBdmake\fR
+supports several non-standard macro expansions:
+The first is of the form:
+.RS
+.IP \fI$(macro_name:modifier_list:modifier_list:...)\fR
+.RE
+.LP
+where
+.I modifier_list
+is chosen from the set { B or b, D or d, E or e, F or f, I or i, L or l, S or
+s, T or t, U or u, ^, +, 1 } and
+.RS
+.sp
+.Is "b "
+.Ii "b "
+\- file (not including suffix) portion of path names
+.Ii "d"
+\- directory portion of all path names
+.Ii "e"
+\- suffix portion of path names
+.Ii "f"
+\- file (including suffix) portion of path names
+.Ii "i"
+\- inferred names of targets
+.Ii "l"
+\- macro value in lower case
+.Ii "s"
+\- simple pattern substitution
+.Ii "t"
+\- tokenization.
+.Ii "u"
+\- macro value in upper case
+.Ii "^"
+\- prepend a prefix to each token
+.Ii "+"
+\- append a suffix to each token
+.Ii "1"
+\- return the first white space separated token from value
+.sp
+.RE
+.fi
+Thus if we have the example:
+.RS
+test = d1/d2/d3/a.out f.out d1/k.out
+.RE
+The following macro expansions produce the values on the right of '\(->' after
+expansion.
+.RS
+.sp
+.Is "$(test:s/out/in/:f) "
+.Ii "$(test:d)"
+\(-> d1/d2/d3/ d1/
+.Ii "$(test:b)"
+\(-> a f k
+.Ii "$(test:f)"
+\(-> a.out f.out k.out
+.Ii "${test:db}"
+\(-> d1/d2/d3/a f d1/k
+.Ii "${test:s/out/in/:f}"
+\(-> a.in f.in k.in
+.Ii $(test:f:t"+")
+\(-> a.out+f.out+k.out
+.Ii $(test:e)
+\(-> .out .out .out
+.Ii $(test:u)
+\(-> D1/D2/D3/A.OUT F.OUT D1/K.OUT
+.Ii $(test:1)
+\(-> d1/d2/d3/a.out
+.RE
+.fi
+.PP
+If a token ends in a string composed from the value of the macro DIRBRKSTR
+(ie. ends in a directory separator string, e.g. '/' in UNIX) and you use the
+\fB:d\fP modifier then the expansion returns the directory name less the
+final directory separator string. Thus successive pairs of :d modifiers
+each remove a level of directory in the token string.
+.PP
+The tokenization modifier takes all white space separated tokens from the
+macro value and separates them by the quoted separator string. The separator
+string may contain the following escape codes \ea => <bel>,
+\&\eb => <backspace>, \ef => <formfeed>, \en => <nl>, \er => <cr>,
+\&\et => <tab>, \ev => <vertical tab>, \e" => ", and \exxx => <xxx> where
+xxx is the octal representation of a character. Thus the
+expansion:
+.LP
+.RS
+.nf
+$(test:f:t"+\en")
+.RE
+produces:
+.RS
+a.out+
+f.out+
+k.out
+.fi
+.RE
+.PP
+The prefix operator \fB^\fP takes all white space separated tokens from the
+macro value and prepends \fIstring\fP to each.
+.LP
+.RS
+.nf
+$(test:f:^mydir/)
+.RE
+produces:
+.RS
+mydir/a.out mydir/f.out mydir/k.out
+.fi
+.RE
+.PP
+The suffix operator \fB+\fP takes all white space separated tokens from the
+macro value and appends \fIstring\fP to each.
+.LP
+.RS
+.nf
+$(test:b:+.c)
+.RE
+produces:
+.RS
+a.c f.c k.c
+.fi
+.RE
+.PP
+The next non-standard form of macro expansion allows for recursive macros.
+It is possible to specify a $(\fImacro_name\fR) or ${\fImacro_name\fR} expansion
+where \fImacro_name\fR contains more $( ... ) or ${ ... } macro expansions
+itself.
+.PP
+For example $(CC$(_HOST)$(_COMPILER)) will first expand CC$(_HOST)$(_COMPILER)
+to get a result and use that result as the name of the macro to expand.
+This is useful for writing a makefile for more than one target
+environment. As an example consider the following hypothetical case.
+Suppose that _HOST and _COMPILER are imported from the environment
+and are set to represent the host machine type and the host compiler
+respectively.
+.RS
+.sp
+.nf
+CFLAGS_VAX_CC = \-c \-O # _HOST == "_VAX", _COMPILER == "_CC"
+CFLAGS_PC_MSC = \-c \-ML # _HOST == "_PC", _COMPILER == "_MSC"
+.sp
+# redefine CFLAGS macro as:
+.sp
+CFLAGS := $(CFLAGS$(_HOST)$(_COMPILER))
+.fi
+.sp
+.RE
+This causes CFLAGS to take on a value that corresponds to the
+environment in which the make is being invoked.
+.PP
+The final non-standard macro expansion is of the form:
+.RS
+.sp
+string1{token_list}string2
+.RE
+.LP
+where string1, string2 and token_list are expanded. After expansion,
+string1 is prepended to each token found in token_list and
+string2 is appended to each resulting token from the previous prepend.
+string1 and string2 are not delimited by white space
+whereas the tokens in token_list are.
+A null token in the token list
+is specified using "".
+Thus using another example we have:
+.RS
+.sp
+.Is "test/{f1 f2}.o "
+.Ii "test/{f1 f2}.o"
+--> test/f1.o test/f2.o
+.Ii "test/ {f1 f2}.o"
+--> test/ f1.o f2.o
+.Ii "test/{f1 f2} .o"
+--> test/f1 test/f2 .o
+.Ii "test/{""f1"" """"}.o"
+--> test/f1.o test/.o
+.sp
+.Ii and
+.sp
+.Is "test/{d1 d2}/{f1 f2}.o --> "
+.Ii "test/{d1 d2}/{f1 f2}.o --> "
+test/d1/f1.o test/d1/f2.o
+test/d2/f1.o test/d2/f2.o
+.sp
+.RE
+.fi
+This last expansion is activated only when the first characters of
+\fItoken_list\fP
+appear immediately after the opening '{' with no intervening white space.
+The reason for this restriction is the following incompatibility with
+Bourne Shell recipes. The line
+.RS
+.sp
+{ echo hello;}
+.sp
+.RE
+is valid /bin/sh syntax; while
+.RS
+.sp
+{echo hello;}
+.sp
+.RE
+.fi
+is not. Hence the latter triggers the enhanced macro expansion while the former
+causes it to be suppressed.
+See the SPECIAL MACROS section for a description of the special macros that
+\fBdmake\fP defines and understands.
+.SH "RULES AND TARGETS"
+A makefile contains a series of entries that specify dependencies.
+Such entries are called \fItarget/prerequisite\fP or \fIrule\fP definitions.
+Each rule definition
+is optionally followed by a set of lines that provide a recipe for updating
+any targets defined by the rule.
+Whenever
+.B dmake
+attempts to bring a target up to date and an explicit recipe is provided with
+a rule defining the target, that recipe is used to update the
+target. A rule definition begins with a line having the following syntax:
+.sp
+.RS
+.nf
+\fI<targets>\fP [\fI<attributes>\fP] \fI<ruleop>\fP [\fI<prerequisites>\fP] [;\fI<recipe>\fP]
+.fi
+.RE
+.sp
+.I targets
+is a non-empty list of targets. If the target is a
+special target (see SPECIAL TARGETS section below) then it must appear alone
+on the rule line. For example:
+.sp
+.RS
+\&.IMPORT .ERROR : ...
+.RE
+.sp
+is not allowed since both .IMPORT and .ERROR are special targets.
+Special targets are not used in the construction of the dependency graph and
+will not be made.
+.PP
+.I attributes
+is a possibly empty list of attributes. Any attribute defined in the
+ATTRIBUTES section above may be specified. All attributes will be applied to
+the list of named targets in the rule definition. No other targets will
+be affected.
+.sp
+.IP NOTE: 0.75i
+As stated earlier,
+if both the target list and prerequisite list are empty but the attributes
+list is not, then the specified attributes affect all targets in the makefile.
+.sp
+.PP
+.I ruleop
+is a separator which is used to identify the targets from the prerequisites.
+Optionally it also provides a facility for modifying the way in which
+.B dmake
+handles the making of the associated targets.
+In its simplest form the operator is a single ':', and need not be separated
+by white space from its neighboring tokens. It may additionally be followed
+by any of the modifiers { !, ^, \-, :, | }, where:
+.sp
+.IP \fB!\fP
+says execute the recipe for the associated targets once for each out of date
+prerequisite. Ordinarily the recipe is executed
+once for all out of date prerequisites at the same time.
+.IP \fB^\fP
+says to insert the specified prerequisites, if any, before any
+other prerequisites already associated with the specified targets.
+In general, it is not useful to specify ^ with an empty
+list of prerequisites.
+.IP \fB\-\fP
+says to clear the previous list of prerequisites before adding
+the new prerequisites. Thus,
+.sp
+\t.SUFFIXES :
+.br
+\t.SUFFIXES : .a .b
+.sp
+can be replaced by
+.sp
+\t.SUFFIXES :\- .a .b
+.sp
+however the old form still works as expected. NOTE: .SUFFIXES is ignored by
+.B dmake
+it is used here simply as an example.
+.IP \fB:\fP
+When the rule operator is not modified by a second ':'
+only one set of rules may be specified for making a target.
+Multiple definitions may be used to add to the
+list of prerequisites that a target depends on.
+However, if a target is multiply defined
+only one definition may specify a recipe
+for making the target.
+.sp
+When a target's rule operator is modified by a second ':'
+(:: for example) then this definition may not be the only
+definition with a recipe for the target. There may be other :: target
+definition lines that specify a different set of prerequisites with a
+different recipe for updating the target.
+Any such target is made if any of the definitions
+find it to be out of date
+with respect to the related prerequisites
+and the corresponding recipe is used to update the
+target. By definition all '::' recipes that are found to be out of date for
+are executed.
+.sp
+In the following simple example, each rule has a `::' \fIruleop\fP. In such an
+operator we call the first `:' the operator, and the second `:' the modifier.
+.sp
+.nf
+a.o :: a.c b.h
+ first recipe for making a.o
+
+a.o :: a.y b.h
+ second recipe for making a.o
+.fi
+.sp
+If a.o is found to be out of date with respect to a.c then the first recipe
+is used to make a.o. If it is found out of date with respect to a.y then
+the second recipe is used. If a.o is out of date with respect to
+b.h then both recipes are invoked to make a.o.
+In the last case the order of invocation corresponds to the order in which the
+rule definitions appear in the makefile.
+.IP \fB|\fP
+Is defined only for PERCENT rule target definitions. When specified it
+indicates that the following construct should be parsed using the old
+semantinc meaning:
+.sp
+.nf
+%.o :| %.c %.r %.f ; some rule
+.sp
+is equivalent to:
+.sp
+%.o : %.c ; some rule
+%.o : %.r ; some rule
+%.o : %.f ; some rule
+.fi
+.PP
+Targets defined using a single `:' operator
+with a recipe may be redefined again with a new recipe by using a
+`:' operator with a `:' modifier.
+This is equivalent to a target having been
+initially defined with a rule using a `:' modifier.
+Once a target is defined using a `:'
+modifier it may not be defined again with a recipe using only the `:' operator
+with no `:' modifier. In both cases the use of a `:' modifier creates a new
+list of prerequisites and makes it the current prerequisite list for the target.
+The `:' operator with no recipe always modifies the current list
+of prerequisites.
+Thus assuming each of the following definitions has a recipe attached, then:
+.RS
+.sp
+.nf
+joe : fred ... (1)
+joe :: more ... (2)
+.sp
+and
+.sp
+joe :: fred ... (3)
+joe :: more ... (4)
+.sp
+.fi
+.RE
+are legal and mean: add the recipe associated with (2), or (4) to the set
+of recipes for joe, placing them after existing recipes for
+making joe.
+The constructs:
+.RS
+.sp
+.nf
+joe :: fred ... (5)
+joe : more ... (6)
+.sp
+and
+.sp
+joe : fred ... (7)
+joe : more ... (8)
+.sp
+.fi
+.RE
+are errors since we have two sets of perfectly good recipes for
+making the target.
+.PP
+.I prerequisites
+is a possibly empty list of targets that must be brought up to date before
+making the current target.
+.PP
+.I recipe
+is a short form and allows the user to specify short rule definitions
+on a single line.
+It is taken to be the first recipe line in a larger recipe
+if additional lines follow the rule definition.
+If the semi-colon is present but the recipe line is empty (ie. null string)
+then it is taken
+to be an empty rule. Any target so defined causes the
+.I "Don't know how to make ..."
+error message to be suppressed when
+.B dmake
+tries to make the target and fails.
+This silence is maintained for rules that are terminated
+by a semicolon and have no following recipe lines, for targets listed on the
+command line, for the first target found in the makefile, and for any target
+having no recipe but containing a list of prerequisites (see the COMPATIBILITY
+section for an exception to this rule if the AUGMAKE (\fB\-A\fP) flag
+was specified.
+.SH "RECIPES"
+The traditional format used by most versions of Make defines the recipe
+lines as arbitrary strings that may contain macro expansions. They
+follow a rule definition line and may be spaced
+apart by comment or blank lines.
+The list of recipe lines defining the recipe is terminated by a new target
+definition, a macro definition, or end-of-file.
+Each recipe line
+.B MUST
+begin with a \fB<TAB>\fP character which
+may optionally be followed with one or all
+of the characters
+.IR "'@%+\-'" "."
+The
+.I "'\-'"
+indicates that non-zero exit values (ie. errors)
+are to be ignored when this recipe line is executed, the
+.I "'\+'"
+indicates that the current recipe line is to be executed using the shell, the
+.I "'%'"
+indicates that
+.B dmake
+should swap itself out to secondary storage (MSDOS only) before running the
+recipe and the
+.I "'@'"
+indicates that the recipe line should NOT be echoed to the terminal prior to
+being executed. Each switch is off by default
+(ie. by default, errors are significant, commands are echoed, no swapping is
+done and a shell is
+used only if the recipe line contains a character found in the value of the
+SHELLMETAS macro).
+Global settings activated via command line options or special attribute or
+target names may also affect these settings.
+An example recipe:
+.sp
+.RS
+.nf
+target :
+\tfirst recipe line
+\tsecond recipe line, executed independent of first.
+\t@a recipe line that is not echoed
+\t\-and one that has errors ignored
+\t%and one that causes dmake to swap out
+\t\+and one that is executed using a shell.
+.fi
+.RE
+.PP
+The second and new format of the recipe block begins the block with the
+character '[' (the open group character) in the last non-white space
+position of a line, and terminates the
+block with the character ']' (the close group character)
+in the first non-white space position of a line.
+In this form each recipe line need not have a leading TAB. This is
+called a recipe group. Groups so defined are fed intact as a single
+unit to a shell for execution whenever the corresponding target needs to
+be updated. If the open group character '[' is preceded
+by one or all of \-, @ or %
+then they apply to the entire group in the same way that they
+apply to single recipe lines. You may also specify '+' but it is
+redundant as a shell is already being used to run the recipe.
+See the MAKING TARGETS section for a description of how
+.B dmake
+invokes recipes.
+Here is an example of a group recipe:
+.sp
+.RS
+.nf
+target :
+[
+ first recipe line
+ second recipe line
+ tall of these recipe lines are fed to a
+ single copy of a shell for execution.
+]
+.fi
+.RE
+.sp
+.SH "TEXT DIVERSIONS"
+.B dmake
+supports the notion of text diversions.
+If a recipe line contains the macro expression
+.RS
+.sp
+$(mktmp[,[\fIfile\fP][,\fItext\fP]] \fIdata\fP)
+.sp
+.RE
+then all text contained in the \fIdata\fP expression is expanded and
+is written to a temporary file. The return
+value of the macro is the name of the temporary file.
+.PP
+.I data
+can be any text and must be separated from the 'mktmp' portion of the
+macro name by white-space. The only restriction on the data text is that
+it must contain a balanced number of parentheses of the same kind as are
+used to initiate the $(mktmp ...) expression. For example:
+.RS
+.sp
+$(mktmp $(XXX))
+.sp
+.RE
+is legal and works as expected, but:
+.RS
+.sp
+$(mktmp text (to dump to file)
+.sp
+.RE
+is not legal. You can achieve what you wish by either defining a macro that
+expands to '(' or by using {} in the macro expression; like this:
+.RS
+.sp
+${mktmp text (to dump to file}
+.sp
+.RE
+Since the temporary file is opened when the
+macro containing the text diversion expression is expanded, diversions may
+be nested and any diversions that are created as part of ':=' macro
+expansions persist for the duration of the
+.B dmake
+run.
+The diversion text may contain
+the same escape codes as those described in the MACROS section.
+Thus if the \fIdata\fP text is to contain new lines they must be inserted
+using the \en escape sequence. For example the expression:
+.RS
+.sp
+.nf
+all:
+ cat $(mktmp this is a\en\e
+ test of the text diversion\en)
+.fi
+.sp
+.RE
+is replaced by:
+.RS
+.sp
+cat /tmp/mk12294AA
+.sp
+.RE
+where the temporary file contains two lines both of which are terminated
+by a new-line. If the \fIdata\fP text spans multiple lines in the makefile
+then each line must be continued via the use of a \e.
+A second more illustrative example generates a response file to an MSDOS
+link command:
+.RS
+.sp
+.nf
+OBJ = fred.obj mary.obj joe.obj
+all : $(OBJ)
+ link @$(mktmp $(^:t"+\en")\en)
+.fi
+.sp
+.RE
+The result of making `all' in the second example is the command:
+.RS
+.sp
+link @/tmp/mk02394AA
+.sp
+.RE
+where the temporary file contains:
+.RS
+.sp
+.nf
+fred.obj+
+mary.obj+
+joe.obj
+.fi
+.sp
+.RE
+The last line of the file is terminated by a new-line which is inserted
+due to the \en found at the end of the \fIdata\fP string.
+.PP
+If the optional \fIfile\fP specifier is present then its expanded value
+is the name of the temporary file to create. Whenever a $(mktmp ...) macro
+is expanded the macro $(TMPFILE) is set to a new temporary file name. Thus
+the construct:
+.RS
+.sp
+$(mktmp,$(TMPFILE) data)
+.sp
+.RE
+is completely equivalent to not specifying the $(TMPFILE) optional argument.
+Another example that would be useful for MSDOS users with a Turbo-C compiler
+.RS
+.sp
+$(mktmp,turboc.cfg $(CFLAGS))
+.sp
+.RE
+will place the contents of CFLAGS into a local \fIturboc.cfg\fP file.
+The second optional argument, \fItext\fP, if present alters the name
+of the value returned by the $(mktmp ...) macro.
+.PP
+Under MS-DOS text diversions may be a problem. Many DOS tools require
+that path names which contain directories use the \e character to delimit
+the directories. Some users however wish to use the '/' to delimit pathnames
+and use environments that allow them to do so.
+The macro USESHELL is set to "yes" if the
+current recipe is forced to use a shell via the .USESHELL or '+' directives,
+otherwise its value is "no".
+The
+.B dmake
+startup files define the macro DIVFILE whose value is either the
+value of TMPFILE or the value of TMPFILE edited to replace any '/' characters
+to the appropriate value based on the current shell and whether it will be
+used to execute the recipe.
+.PP
+Previous versions of
+.B dmake
+defined text diversions using <+, +> strings,
+where <+ started a text diversion and +> terminated one.
+.B dmake
+is backward compatible with this construct only
+if the <+ and +> appear literally
+on the same recipe line or in the same macro value string. In such instances
+the expression:
+.sp
+\t<+data+>
+.sp
+is mapped to:
+.sp
+\t$(mktmp data)
+.sp
+which is fully output compatible with the earlier construct. <+, +>
+constructs whose text spans multiple lines must be converted by hand to use
+$(mktmp ...).
+.PP
+If the environment variable TMPDIR is defined then the
+temporary file is placed into the directory specified by that variable.
+A makefile can modify the location of temporary files by
+defining a macro named TMPDIR and exporting it using the .EXPORT special
+target.
+.SH "SPECIAL TARGETS"
+This section describes the special targets that are recognized by \fBdmake\fP.
+Some are affected by attributes and others are not.
+.IP \fB.ERROR\fP 1.4i
+If defined then the recipe associated with this target is executed
+whenever an error condition is detected by \fBdmake\fP. All attributes that
+can be used with any other target may be used with this target. Any
+prerequisites of this target will be brought up to date during its processing.
+NOTE: errors will be ignored while making this target, in extreme cases this
+may cause some problems.
+.IP \fB.EXIT\fP 1.4i
+If this target is encountered while parsing a makefile then the parsing of the
+makefile is immediately terminated at that point.
+.IP \fB.EXPORT\fP 1.4i
+All prerequisites associated with this target are assumed to
+correspond to macro names and they and their values
+are exported to the environment as environment strings at the point in
+the makefile at which this target appears.
+Any attributes specified with this target are ignored.
+Only macros which have been assigned a value in the makefile prior to the
+export directive are exported, macros as yet undefined
+or macros whose value contains any of the characters "+=:*"
+are not exported.
+is suppre
+.IP \fB.IMPORT\fP 1.4i
+Prerequisite names specified for this target are searched for in the
+environment and defined as macros with their value taken from the environment.
+If the special name \fB.EVERYTHING\fP is used as a prerequisite name then
+all environment variables defined in the environment are imported.
+The functionality of the \fB\-E\fP flag can be forced by placing the construct
+\&\fI.IMPORT : .EVERYTHING\fP at the start of a makefile. Similarly, by
+placing the construct at the end, one can emulate the effect of the \fB\-e\fP
+command line flag.
+If a prerequisite name cannot be found in the environment
+an error message is issued.
+\&.IMPORT accepts the .IGNORE attribute. When given, it causes \fBdmake\fP
+to ignore the above error.
+See the MACROS section for a description of the processing of imported macro
+values.
+.IP \fB.INCLUDE\fP 1.4i
+Parse another makefile just as if it had been located at the point of the
+\&.INCLUDE in the current makefile.
+The list of prerequisites gives the list of
+makefiles to try to read. If the list contains multiple makefiles then they
+are read in order from left to right. The following search rules are used
+when trying to locate the file. If the filename is surrounded by " or just
+by itself then it is searched for in the current directory. If it is not
+found it is then searched for in each of the directories specified
+as prerequisites of the \&.INCLUDEDIRS special target.
+If the file name is surrounded by < and >, (ie.
+<my_spiffy_new_makefile>) then it is searched for only in the directories
+given by the .INCLUDEDIRS special target. In both cases if the file name is a
+fully qualified name starting at the root of the file system then it is only
+searched for once, and the .INCLUDEDIRS list is ignored.
+If .INCLUDE fails to find the file it invokes the inference engine to
+try to infer and hence make the file to be included. In this way the
+file can be checked out of an RCS repository for example.
+\&.INCLUDE accepts
+the .IGNORE, .SETDIR, and .NOINFER attributes.
+If the .IGNORE attribute is given and the file
+cannot be found then \fBdmake\fP continues processing,
+otherwise an error message is generated.
+If the .NOINFER attribute is given and the file
+cannot be found then \fBdmake\fP will not attempt to
+\fIinfer and make\fP the file.
+The .SETDIR attribute causes
+.B dmake
+to change directories to the specified directory prior to attempting the
+include operation. If all fails \fBdmake\fP attempts to \fImake\fP the file
+to be included. If making the file fails then \fBdmake\fP terminates unless
+the .INCLUDE directive also specified the .IGNORE attribute.
+If .FIRST is specified along with .INCLUDE then \fBdmake\fP attempts to
+include each named prerequisite and will terminate the inclusion with the
+first prerequisite that results in a successful inclusion.
+.IP \fB.INCLUDEDIRS\fP 1.4i
+The list of prerequisites specified for this target defines the set of
+directories to search when trying to include a makefile.
+.IP \fB.KEEP_STATE\fP 1.4i
+This special target is a synonym for the macro definition
+.sp
+\&\t.KEEP_STATE := _state.mk
+.sp
+It's effect is to turn on STATE keeping and to define \fI_state.mk\fP
+as the state file.
+.IP \fB.MAKEFILES\fP 1.4i
+The list of prerequisites is the set of files to try to read as the default
+makefile. By default this target is defined as:
+.sp
+\t\&.MAKEFILES : makefile.mk Makefile makefile
+.sp
+.IP \fB.SOURCE\fP 1.4i
+The prerequisite list of this target defines a set of directories to check
+when trying to locate a target file name. See the section on BINDING of
+targets for more information.
+.IP \fB.SOURCE.suff\fP 1.4i
+The same as .SOURCE, except that the .SOURCE.suff list is searched first when
+trying to locate a file matching the a target whose name ends in the suffix
+\&.suff.
+.IP \fB.REMOVE\fP 1.4i
+The recipe of this target is used whenever \fBdmake\fP needs to remove
+intermediate targets that were made but do not need to be kept around.
+Such targets result from the application of transitive closure on the
+dependency graph.
+.PP
+In addition to the special targets above,
+several other forms of targets are recognized and are considered special,
+their exact form and use is defined in the sections that follow.
+.SH "SPECIAL MACROS"
+.B dmake
+defines a number of special macros. They are divided into three classes:
+control macros, run-time macros, and function macros.
+The control macros are used by
+.B dmake
+to configure its actions, and are the preferred method of doing so.
+In the case when a control macro has the same function as a special
+target or attribute they share the same name as the special target or
+attribute.
+The run-time macros are defined when
+.B dmake
+makes targets and may be used by the user inside recipes.
+The function macros provide higher level functions dealing with macro
+expansion and diversion file processing.
+.SH "CONTROL MACROS"
+To use the control macros simply assign them a value just like any other
+macro. The control macros are divided into three groups:
+string valued macros, character valued macros, and boolean valued macros.
+.PP
+The following are all of the string valued macros.
+This list is divided into two groups. The first group gives the string
+valued macros that are defined internally and cannot be directly set by the
+user.
+.IP \fBINCDEPTH\fP 1.6i
+This macro's value is a string of digits representing
+the current depth of makefile inclusion.
+In the first makefile level this value is zero.
+.IP \fBMFLAGS\fP 1.6i
+Is the list of flags
+that were given on the command line including a leading switch character.
+The \-f flag is not included in this list.
+.IP \fBMAKECMD\fP 1.6i
+Is the name with which \fBdmake\fP was invoked.
+.IP \fBMAKEDIR\fP 1.6i
+Is the full path to the initial directory in which
+.B dmake
+was invoked.
+.IP \fBMAKEFILE\fP 1.6i
+Contains the string "\-f \fImakefile\fP" where, \fImakefile\fP is the name
+of initial user makefile that was first read.
+.IP \fBMAKEFLAGS\fP 1.6i
+Is the same as $(MFLAGS) but has no leading switch
+character. (ie. MFLAGS = \-$(MAKEFLAGS))
+.IP \fBMAKEMACROS\fP 1.6i
+Contains the complete list of macro expressions that were specified on the
+command line.
+.IP \fBMAKETARGETS\fP 1.6i
+Contains the name(s) of the target(s), if any, that were
+specified on the command line.
+.IP \fBMAKEVERSION\fP 1.6i
+Contains a string indicating the current \fBdmake\fP version number.
+.IP \fBMAXPROCESSLIMIT\fP 1.6i
+Is a numeric string representing the maximum number of processes that
+\fBdmake\fP can use when making targets using parallel mode.
+.IP \fBNULL\fP 1.6i
+Is permanently defined to be the NULL string.
+This is useful when comparing a conditional expression to an NULL value.
+.IP \fBPWD\fP 1.6i
+Is the full path to the
+current directory in which make is executing.
+.IP \fBTMPFILE\fP 1.6i
+Is set to the name of the most recent temporary file opened by \fBdmake\fP.
+Temporary files are used for text diversions and for group recipe processing.
+.IP \fBTMD\fP 1.6i
+Stands for "To Make Dir", and
+is the path from the present directory (value of $(PWD)) to the directory
+that \fBdmake\fP was started up in (value of $(MAKEDIR)).
+This macro is modified when .SETDIR attributes are processed.
+.IP \fBUSESHELL\fP 1.6i
+The value of this macro is set to "yes" if the current recipe is forced to
+use a shell for its execution via the .USESHELL or '+' directives, its value
+is "no" otherwise.
+.sp
+.PP
+The second group of string valued macros control
+.B dmake
+behavior and may be set by the user.
+.IP \fB.DIRCACHE\fP 1.6i
+If set to "yes" enables the directory cache (this is the default). If set to
+"no" disables the directory cache (equivalent to -d command-line flag).
+.IP \fB.DIRCACHERESPCASE\fP 1.6i
+If set to "yes" causes the directory cache, if enabled, to respect
+file case, if set to "no" facilities of the native OS are used to
+match file case.
+.IP \fB.NAMEMAX\fP 1.6i
+Defines the maximum length of a filename component. The value of the variable
+is initialized at startup to the value of the compiled macro NAME_MAX. On
+some systems the value of NAME_MAX is too short by default. Setting a new
+value for .NAMEMAX will override the compiled value.
+.IP \fB.NOTABS\fP 1.6i
+When set to "yes" enables the use of spaces as well as <tabs> to begin
+recipe lines.
+By default a non\-group recipe is terminated by a line without any leading
+white\-space or by a line not beggining with a <tab> character.
+Enabling this mode modifies the first condition of
+the above termination rule to terminate a
+non\-group recipe with a line that contains only white\-space.
+This mode does not effect the parsing of group recipes bracketed by [].
+.IP \fBAUGMAKE\fP 1.6i
+If set to "yes" value will enable the transformation of special
+meta targets to support special AUGMAKE inferences (See the COMPATIBILITY
+section).
+.IP \fBDIRBRKSTR\fP 1.6i
+Contains the string of chars used to terminate
+the name of a directory in a pathname.
+Under UNIX its value is "/", under MSDOS its value is "/\e:".
+.IP \fBDIRSEPSTR\fP 1.6i
+Contains the string that is used to separate directory components when
+path names are constructed. It is defined with a default value at startup.
+.IP \fBDIVFILE\fP 1.6i
+Is defined in the startup file and gives the name that should be returned for
+the diversion file name when used in
+$(mktmp ...) expansions, see the TEXT DIVERSION section for details.
+.IP \fBDYNAMICNESTINGLEVEL\fP 1.6i
+Specifies the maximum number of recursive dynamic macro expansions. Its
+initial value is 100.
+.IP \fB.KEEP_STATE\fP 1.6i
+Assigning this macro a value tells
+.B dmake
+the name of the state file to use and turns on the keeping of state
+information for any targets that are brought up to date by the make.
+.IP \fBGROUPFLAGS\fP 1.6i
+This macro gives the set of flags to pass to the shell when
+invoking it to execute a group recipe. The value of the macro is the
+list of flags with a leading switch indicator. (ie. `\-' under UNIX)
+.IP \fBGROUPSHELL\fP 1.6i
+This macro defines the full
+path to the executable image to be used as the shell when
+processing group recipes. This macro must be defined if group recipes are
+used. It is assigned a default value in the startup makefile. Under UNIX
+this value is /bin/sh.
+.IP \fBGROUPSUFFIX\fP 1.6i
+If defined, this macro gives the string to use as a suffix
+when creating group recipe files to be handed to the command interpreter.
+For example, if it is defined as .sh, then all
+temporary files created by \fBdmake\fP will end in the suffix .sh.
+Under MSDOS if you are using command.com as your GROUPSHELL, then this suffix
+must be set to .bat in order for group recipes to function correctly.
+The setting of GROUPSUFFIX and GROUPSHELL is done automatically for
+command.com in the startup.mk files.
+.IP \fBMAKE\fP 1.6i
+Is defined in the startup file by default.
+Initially this macro is defined to have the value "$(MAKECMD) $(MFLAGS)".
+The string $(MAKE) is recognized when using the \-n switch.
+.IP \fBMAKESTARTUP\fP 1.6i
+This macro defines the full path to the initial startup
+makefile. Use the \fB\-V\fP command line option to discover its initial
+value.
+.IP \fBMAXLINELENGTH\fP 1.6i
+This macro defines the maximum size of a single line of
+makefile input text. The size is specified as a number, the default value
+is defined internally and is shown via the \fB\-V\fP option.
+A buffer of this size plus 2 is allocated for reading makefile text. The
+buffer is freed before any targets are made, thereby allowing files containing
+long input lines to be processed without consuming memory during the actual
+make.
+This macro can only be used to extend the line length beyond it's default
+minimum value.
+.IP \fBMAXPROCESS\fP 1.6i
+Specify the maximum number of child processes to use when making targets.
+The default value of this macro is "1" and its value cannot exceed the value
+of the macro MAXPROCESSLIMIT. Setting the value of MAXPROCESS on the command
+line or in the makefile is equivalent to supplying a corresponding value to
+the -P flag on the command line.
+.IP \fBPREP\fP 1.6i
+This macro defines the number of iterations to be expanded
+automatically when processing % rule definitions of the form:
+.sp
+% : %.suff
+.sp
+See the sections on PERCENT(%) RULES for details on how PREP is used.
+.IP \fBSHELL\fP 1.6i
+This macro defines the full path to the executable
+image to be used as the shell when
+processing single line recipes. This macro must be defined if recipes
+requiring the shell for execution are to be used.
+It is assigned a default value in the startup makefile.
+Under UNIX this value is /bin/sh.
+.IP \fBSHELLFLAGS\fP 1.6i
+This macro gives the set of flags to pass to the shell when
+invoking it to execute a single line recipe. The value of the macro is the
+list of flags with a leading switch indicator. (ie. `\-' under UNIX)
+.IP \fBSHELLMETAS\fP 1.6i
+Each time
+.B dmake
+executes a single recipe line (not a group recipe) the line is
+searched for any occurrence of a character defined in the value of SHELLMETAS.
+If such a character is found the recipe line is defined to require a shell
+to ensure its correct execution. In such instances
+a shell is used to invoke the recipe line.
+If no match is found the recipe line is executed without the use of a shell.
+.sp
+.PP
+There is only one character valued macro defined by \fBdmake\fP:
+\fBSWITCHAR\fP contains the switch character used
+to introduce options on command lines. For UNIX its value is `\-', and for
+MSDOS its value may be `/' or `\-'.
+The macro is internally defined and is not user setable.
+The MSDOS version of \fBdmake\fP attempts to first extract SWITCHAR from an
+environment variable of the same name. If that fails it then attempts to
+use the undocumented getswitchar system call, and returns the result of
+that. Under MSDOS version 4.0 you must set the value of the environment
+macro SWITCHAR to '/' to obtain predictable behavior.
+.PP
+All boolean macros currently understood by
+.B dmake
+correspond directly to the previously defined attributes.
+These macros provide
+a second way to apply global attributes, and represent the
+preferred method of doing so. They are used by assigning them a
+value. If the value is not a NULL string then the boolean condition
+is set to on.
+If the value is a NULL string then the condition is set to off.
+There are five conditions defined and they correspond directly to the
+attributes of the same name. Their meanings are defined in the ATTRIBUTES
+section above.
+The macros are:
+\&\fB.EPILOG\fP,
+\&\fB.IGNORE\fP,
+\&\fB.MKSARGS\fP,
+\&\fB.NOINFER\fP,
+\&\fB.PRECIOUS\fP,
+\&\fB.PROLOG\fP,
+\&\fB.SEQUENTIAL\fP,
+\&\fB.SILENT\fP,
+\&\fB.SWAP\fP, and
+\&\fB.USESHELL\fP.
+Assigning any of these a non NULL value will globally set
+the corresponding attribute to on.
+.SH "RUNTIME MACROS"
+These macros are defined
+when \fBdmake\fP is making targets, and may take on different values for each
+target. \fB$@\fP is defined to be the full target name, \fB$?\fP is the
+list of all out of date prerequisites, \fB$&\fP is the list of all
+prerequisites, \fB$>\fP is the name of the library if the current target is a
+library member, and
+\fB$<\fP is the list of prerequisites specified in the current rule.
+If the current target had a recipe inferred then \fB$<\fP is the name of the
+inferred prerequisite even if the target had a list of prerequisites supplied
+using an explicit rule that did not provide a recipe. In such situations
+\fB$&\fP gives the full list of prerequisites.
+.PP
+\fB$*\fP is defined as
+\fB$(@:db)\fP when making targets with explicit recipes and is defined as the
+value of % when making targets whose recipe is the result of an inference.
+In the first case \fB$*\fP is the target name with no suffix,
+and in the second case, is the value of the matched % pattern from
+the associated %-rule.
+\fB$^\fP expands to the set of out of date prerequisites taken from the
+current value of \fB$<\fP.
+In addition to these,
+\fB$$\fP expands to $, \fB{{\fP expands to {, \fB}}\fP expands to }, and the
+strings \fB<+\fP and \fB+>\fP are recognized
+as respectively starting and terminating a text diversion when they appear
+literally together in the same input line.
+.PP
+The difference between $? and $^ can best be illustrated by an example,
+consider:
+.RS
+.sp
+.nf
+fred.out : joe amy hello
+\trules for making fred
+
+fred.out : my.c your.h his.h her.h # more prerequisites
+.fi
+.sp
+.RE
+Assume joe, amy, and my.c are newer then fred.out. When
+.B dmake
+executes the recipe for making fred.out the values of the following macros
+will be:
+.RS
+.sp
+.nf
+.Is "$@ "
+.Ii "$@"
+--> fred.out
+.Ii "$*"
+--> fred
+.Ii "$?"
+--> joe amy my.c # note output of $? vs $^
+.Ii "$^"
+--> joe amy
+.Ii "$<"
+--> joe amy hello
+.Ii "$&"
+--> joe amy hello my.c your.h his.h her.h
+.fi
+.sp
+.RE
+.SH "FUNCTION MACROS"
+.B dmake
+supports a full set of functional macros. One of these, the $(mktmp ...)
+macro, is discussed in detail in the TEXT DIVERSION section and is not
+covered here.
+.RS
+.sp
+.IP "$(\fBand\fP \fBmacroterm ...\fP)"
+expands each \fBmacroterm\fP in turn until there are no more or one of
+them returns an empty string. If all expand to non-empty strings the
+macro returs the string "t" otherwise it returns an empty string.
+.sp
+.IP "$(\fBassign\fP \fBexpression\fP)"
+Causes \fIexpression\fP to be parsed as a macro assignment expression and results
+in the specified assignment being made. An error is issued if the assignment
+is not syntatically correct. \fIexpression\fP may contain white space. This is
+in effect a dynamic macro assignment facility and may appear anywhere any
+other macro may appear. The result of the expanding a dynamic macro
+assignment expression is the name of the macro that was assigned and $(NULL)
+if the \fIexpression\fP is not a valid macro assignment expression.
+Some examples are:
+.RS
+.sp
+.nf
+$(assign foo := fred)
+$(assign $(ind_macro_name) +:= $(morejunk))
+.fi
+.RE
+.IP "$(\fBecho\fP \fBlist\fP)"
+Echo's the value of \fIlist\fP. \fIlist\fP is not expanded.
+.IP "$(\fBeq\fP,\fItext_a\fP,\fItext_b\fP \fBtrue\fP \fBfalse\fP)"
+expands
+.I text_a
+and
+.I text_b
+and compares their results. If equal it returns the result of the expansion
+of the
+.B true
+term, otherwise it returns the expansion of the
+.B false
+term.
+.IP "$(\fB!eq\fP,\fItext_a\fP,\fItext_b\fP \fBtrue\fP \fBfalse\fP)"
+Behaves identically to the previous macro except that the
+.B true
+string is chosen if the expansions of the two strings are not equal
+.IP "$(\fBforeach\fP,\fIvar\fP,\fIlist\fP \fBdata\fP)"
+Implements iterative macro expansion over \fIdata\fP using \fBvar\fP as the
+iterator taking on values from \fIlist\fP. \fIvar\fP and \fIlist\fP are
+expanded and the result is the concatenation of expanding \fIdata\fP with
+\fIvar\fP being set to each whitespace separated token from \fIlist\fP.
+For example:
+.RS
+.RS
+.sp
+.nf
+list = a b c
+all :; echo [$(foreach,i,$(list) [$i])]
+.fi
+.sp
+.RE
+will output
+.RS
+.sp
+.nf
+[[a] [b] [c]]
+.fi
+.sp
+.RE
+The iterator variable is defined as a local variable to this foreach
+instance. The following expression illustrates this:
+.RS
+.sp
+.nf
+$(foreach,i,$(foreach,i,$(sort c a b) root/$i) [$i/f.h])
+.fi
+.sp
+.RE
+when evaluated the result is:
+.RS
+.sp
+.nf
+[root/a/f.h] [root/b/f.h] [root/c/f.h]
+.fi
+.sp
+.RE
+The specification of list must be a valid macro expression, such as:
+.RS
+.sp
+.nf
+$($(assign list=a b c))
+$(sort d a b c)
+$(echo a b c)
+.fi
+.sp
+.RE
+and cannot just be the list itself. That is, the following foreach
+expression:
+.RS
+.sp
+.nf
+$(foreach,i,a b c [$i])
+.fi
+.sp
+.RE
+yields:
+.RS
+.sp
+.nf
+"b c [a]"
+.fi
+.sp
+.RE
+when evaluated.
+.RE
+.IP "$(\fBnil\fP \fBexpression\fP)"
+Always returns the value of $(NULL) regardless of what \fIexpression\fP is.
+This function macro can be used to discard results of expanding
+macro expressions.
+.IP "$(\fBnot\fP \fBmacroterm\fP)"
+expands \fBmacroterm\fP and returs the string "t" if the result of the
+expansion is the empty string; otherwise, it returns the empty string.
+.IP "$(\fBnull\fP,\fItext\fP \fBtrue\fP \fBfalse\fP)"
+expands the value of
+.I text.
+If it is NULL then the macro returns the value of the expansion of \fBtrue\fP
+and the expansion of \fBfalse\fP otherwise. The terms \fBtrue\fP, and
+\fBfalse\fP must be strings containing no white\-space.
+.IP "$(\fB!null\fP,\fItext\fP \fBtrue\fP \fBfalse\fP)"
+Behaves identically to the previous macro except that the
+.B true
+string is chosen if the expansion of
+.I text
+is not NULL.
+.IP "$(\fBor\fP \fBmacroterm ...\fP)"
+expands each \fBmacroterm\fP in turn and returs the empty string if
+each term expands to the empty string; otherwise, it returs the string
+"t".
+.IP "$(\fBshell\fP \fBcommand\fP)"
+Runs \fIcommand\fP as if it were part of a recipe and returns,
+separated by a single space, all the non-white
+space terms written to stdout by the command.
+For example:
+.RS
+.RS
+.sp
+$(shell ls *.c)
+.sp
+.RE
+will return \fI"a.c b.c c.c d.c"\fP if the files exist in the current
+directory. The recipe modification flags \fB[+@%\-]\fP are honored if they
+appear as the first characters in the command. For example:
+.RS
+.sp
+$(shell +ls *.c)
+.sp
+.RE
+will run the command using the current shell.
+.RE
+.IP "$(\fBshell,expand\fP \fBcommand\fP)"
+Is an extension to the \fB$(shell...\fP function macro that expands the result
+of running \fBcommand\fP.
+.IP "$(\fBsort\fP \fBlist\fP)"
+Will take all white\-space separated tokens in \fIlist\fP and will
+return their sorted equivalent list.
+.IP "$(\fBstrip\fP \fBdata\fP)"
+Will replace all strings of white\-space in data by a single space.
+.IP "$(\fBsubst\fP,\fIpat\fP,\fIreplacement\fP \fBdata\fP)"
+Will search for \fIpat\fP in
+.B data
+and will replace any occurrence of
+.I pat
+with the
+.I replacement
+string. The expansion
+.RS
+.sp
+$(subst,.o,.c $(OBJECTS))
+.sp
+.RE
+is equivalent to:
+.RS
+.sp
+$(OBJECTS:s/.o/.c/)
+.sp
+.RE
+.IP "$(\fBuniq\fP \fBlist\fP)"
+Will take all white\-space separated tokens in \fIlist\fP and will
+return their sorted equivalent list containing no duplicates.
+.RE
+.SH "CONDITIONAL MACROS"
+.B dmake
+supports conditional macros. These allow the definition of target specific
+macro values. You can now say the following:
+.RS
+.sp
+\fBtarget\fP ?= \fIMacroName MacroOp Value\fP
+.sp
+.RE
+This creates a definition for \fIMacroName\fP whose value is \fIValue\fP
+only when \fBtarget\fP is being made. You may use a conditional macro
+assignment anywhere that a regular macro assignment may appear, including
+as the value of a $(assign ...) macro.
+.LP
+The new definition is associated with the most recent cell definition
+for \fBtarget\fP. If no prior definition exists then one is created. The
+implications of this are immediately evident in the following example:
+.sp
+.RS
+.nf
+foo := hello
+.sp
+all : cond;@echo "all done, foo=[$(foo)] bar=[$(bar)]"
+.sp
+cond ?= bar := global decl
+.sp
+cond .SETDIR=unix::;@echo $(foo) $(bar)
+cond ?= foo := hi
+.sp
+cond .SETDIR=msdos::;@echo $(foo) $(bar)
+ cond ?= foo := hihi
+.fi
+.RE
+.sp
+The first conditional assignment creates a binding for 'bar' that is
+activated when 'cond' is made. The bindings following the :: definitions are
+activated when their respective recipe rules are used. Thus the
+first binding serves to provide a global value for 'bar' while any of the
+cond :: rules are processed, and the local bindings for 'foo' come into
+effect when their associated :: rule is processed.
+.LP
+Conditionals for targets of .UPDATEALL are all activated before the
+target group is made. Assignments are processed in order. Note that
+the value of a conditional macro assignment is NOT AVAILABLE until the
+associated target is made, thus the construct
+.sp
+.RS
+.nf
+mytarget ?= bar := hello
+mytarget ?= foo := $(bar)
+.fi
+.RE
+.sp
+results in $(foo) expanding to "", if you want the result to be "hello"
+you must use:
+.sp
+.RS
+.nf
+mytarget ?= bar := hello
+mytarget ?= foo = $(bar)
+.fi
+.RE
+.sp
+Once a target is made any associated conditional macros are deactivated
+and their values are no longer available. Activation occurrs after all
+inference, and .SETDIR directives have been processed and after $@ is
+assigned, but before prerequisites are processed; thereby making the values of
+conditional macro definitions available during construction of prerequisites.
+.LP
+If a %-meta rule target has associated conditional macro assignments,
+and the rule is chosen by the inference algorithm then the conditional
+macro assignments are inferred together with the associated recipe.
+.SH "DYNAMIC PREREQUISITES"
+.B dmake
+looks for prerequisites whose names contain macro expansions during target
+processing. Any such prerequisites are expanded and the result of the
+expansion is used as the prerequisite name. As an example the line:
+.sp
+\tfred : $$@.c
+.sp
+causes the $$@ to be expanded when \fBdmake\fP is making fred, and it resolves
+to the target \fIfred\fP.
+This enables dynamic prerequisites to be generated. The value
+of @ may be modified by any of the valid macro modifiers. So you can say for
+example:
+.sp
+\tfred.out : $$(@:b).c
+.sp
+where the $$(@:b) expands to \fIfred\fP.
+Note the use of $$ instead of $ to indicate the dynamic expansion, this
+is due to the fact that the rule line is expanded when it is initially parsed,
+and $$ then returns $ which later triggers the dynamic prerequisite expansion.
+If you really want a $ to be part of a prerequisite name you must use $$$$.
+Dynamic macro expansion is performed in all user defined rules,
+and the special targets .SOURCE*, and .INCLUDEDIRS.
+.PP
+If dynamic macro expansion results in multiple white space separated tokens
+then these are inserted into the prerequisite list inplace of the dynamic
+prerequisite. If the new list contains additional dynamic prerequisites they
+will be expanded when they are processed. The level of recursion in this
+expansion is controlled by the value of the variable \fBDYNAMICNESTINGLEVEL\fP
+and is set to 100 by default.
+.SH "BINDING TARGETS"
+This operation takes a target name and binds it to an existing file, if
+possible.
+.B dmake
+makes a distinction between the internal target name of a target and its
+associated external file name.
+Thus it is possible for a target's internal name and its external
+file name to differ.
+To perform the binding, the following set of rules is used.
+Assume that we are
+trying to bind a target whose name is of the form \fIX.suff\fP,
+where \fI.suff\fP is the suffix and \fIX\fP is the stem portion
+(ie. that part which contains the directory and the basename).
+.B dmake
+takes this target name and performs a series of search operations that try to
+find a suitably named file in the external file system.
+The search operation is user controlled
+via the settings of the various .SOURCE targets.
+.RS
+.IP 1.
+If target has the .SYMBOL attribute set then look for it in the library.
+If found, replace the target name with the library member name and continue
+with step 2. If the name is not found then return.
+.IP 2.
+Extract the suffix portion (that following the `.') of the target name.
+If the suffix is not null, look up the special target .SOURCE.<suff>
+(<suff> is the suffix).
+If the special target exists then search each directory given in
+the .SOURCE.<suff> prerequisite list for the target.
+If the target's suffix was null (ie. \fI.suff\fP was empty) then
+perform the above search but use the special target .SOURCE.NULL instead.
+If at any point a match is found then terminate the search.
+If a directory in the prerequisite list is the special name `.NULL ' perform
+a search for the full target name without prepending any directory portion
+(ie. prepend the NULL directory).
+.IP 3.
+The search in step 2. failed. Repeat the same search but this time
+use the special target .SOURCE.
+(a default target of '.SOURCE : .NULL' is defined by \fBdmake\fP at startup,
+and is user redefinable)
+.IP 4.
+The search in step 3. failed.
+If the target has the library member attribute (.LIBMEMBER)
+set then try to find the target in the library which was passed along
+with the .LIBMEMBER attribute (see the MAKING LIBRARIES section).
+The bound file name assigned to a target which is successfully
+located in a library is the same name that would be assigned had the search
+failed (see 5.).
+.IP 5.
+The search failed. Either the target was not found in any of the search
+directories or no applicable .SOURCE special targets exist.
+If applicable .SOURCE special targets exist, but the target was not found,
+then \fBdmake\fP assigns the first name searched as the bound file name.
+If no applicable .SOURCE special targets exist,
+then the full original target name becomes the bound file name.
+.RE
+.PP
+There is potential here for a lot of search operations. The trick is to
+define .SOURCE.x special targets with short search lists and leave .SOURCE
+as short as possible.
+The search algorithm has the following useful side effect.
+When a target having the .LIBMEMBER (library member) attribute is searched for,
+it is first searched for as an ordinary file.
+When a number of library members require updating it is desirable to compile
+all of them first and to update the library at the end in a single operation.
+If one of the members does not compile and \fBdmake\fP stops, then
+the user may fix the error and make again. \fBdmake\fP will not remake any
+of the targets whose object files have already been generated as long as
+none of their prerequisite files have been modified as a result of the fix.
+.PP
+When \fBdmake\fP constructs target pathnames './' substrings are removed and
+substrings of the form 'foo/..' are eliminated. This may result in somewhat
+unexpected values of the macro expansion \fB$@\fP, but is infact the corect
+result.
+.PP
+When defining .SOURCE and .SOURCE.x targets the construct
+.RS
+.sp
+.SOURCE :
+.br
+.SOURCE : fred gery
+.sp
+.RE
+is equivalent to
+.RS
+.sp
+.SOURCE :\- fred gery
+.RE
+.PP
+\fBdmake\fP correctly handles the UNIX Make variable VPATH. By definition VPATH
+contains a list of ':' separated directories to search when looking for a
+target. \fBdmake\fP maps VPATH to the following special rule:
+.RS
+.sp
+.SOURCE :^ $(VPATH:s/:/ /)
+.sp
+.RE
+Which takes the value of VPATH and sets .SOURCE to the same set of directories
+as specified in VPATH.
+.SH "PERCENT(%) RULES AND MAKING INFERENCES"
+When \fBdmake\fP makes a target, the target's set of prerequisites (if any)
+must exist and the target must have a recipe which \fBdmake\fP
+can use to make it.
+If the makefile does not specify an explicit recipe for the target then
+.B dmake
+uses special rules to try to infer a recipe which it can use
+to make the target. Previous versions of Make perform this task by using
+rules that are defined by targets of the form .<suffix>.<suffix> and by
+using the .SUFFIXES list of suffixes. The exact workings of this mechanism
+were sometimes difficult to understand and often limiting in their usefulness.
+Instead, \fBdmake\fP supports the concept of \fI%-meta\fP rules.
+The syntax and semantics of these rules differ from standard rule lines as
+follows:
+.sp
+.nf
+.RS
+\fI<%-target>\fP [\fI<attributes>\fP] \fI<ruleop>\fP [\fI<%-prerequisites>\fP] [;\fI<recipe>\fP]
+.RE
+.fi
+.sp
+where \fI%-target\fP is a target containing exactly a single `%' sign,
+.I attributes
+is a list (possibly empty) of attributes,
+.I ruleop
+is the standard set of rule operators,
+.I "%-prerequisites"
+\&, if present, is a list of prerequisites containing zero or more `%' signs,
+and
+.I recipe,
+if present, is the first line of the recipe.
+.PP
+The
+.I %-target
+defines a pattern against which a target whose recipe is
+being inferred gets matched. The pattern match goes as follows: all chars are
+matched exactly from left to right up to but not including the % sign in the
+pattern, % then matches the longest string from the actual target name
+not ending in
+the suffix given after the % sign in the pattern.
+Consider the following examples:
+.RS
+.sp
+.nf
+.Is "dir/%.c "
+.Ii "%.c"
+matches fred.c but not joe.c.Z
+.Ii "dir/%.c"
+matches dir/fred.c but not dd/fred.c
+.Ii "fred/%"
+matches fred/joe.c but not f/joe.c
+.Ii "%"
+matches anything
+.fi
+.sp
+.RE
+In each case the part of the target name that matched the % sign is retained
+and is substituted for any % signs in the prerequisite list of the %-meta rule
+when the rule is selected during inference and
+.B dmake
+constructs the new dependency.
+As an example the following %-meta rules describe the following:
+.RS
+.sp
+%.c : %.y ; recipe...
+.sp
+.RE
+describes how to make any file ending in .c if a corresponding file ending
+in .y can be found.
+.RS
+.sp
+foo%.o : fee%.k ; recipe...
+.sp
+.RE
+is used to describe how to make fooxxxx.o from feexxxx.k.
+.RS
+.sp
+%.a :; recipe...
+.sp
+.RE
+describes how to make a file whose suffix is .a without inferring any
+prerequisites.
+.RS
+.sp
+%.c : %.y yaccsrc/%.y ; recipe...
+.sp
+.RE
+is a short form for the construct:
+.RS
+.sp
+%.c : %.y ; recipe...
+.br
+%.c : yaccsrc/%.y ; recipe...
+.sp
+.RE
+ie. It is possible to specify the same recipe for two %-rules by giving
+more than one prerequisite in the prerequisite list.
+A more interesting example is:
+.RS
+.sp
+% : RCS/%,v ; co $<
+.sp
+.RE
+which describes how to take any target and check it out of
+the RCS directory if the corresponding file exists in the RCS directory.
+The equivalent SCCS rule would be:
+.RS
+.sp
+% : s.% ; get $<
+.sp
+.RE
+.PP
+The previous RCS example defines an infinite rule, because it says how to make
+.I anything
+from RCS/%,v, and
+.I anything
+also includes RCS/fred.c,v.
+To limit the size of the graph that results from such rules
+.B dmake
+uses the macro variable PREP (stands for % repetition). By default the value
+of this variable is 0, which says that no repetitions of a %-rule are to be
+generated. If it is set to something greater than 0, then that many
+repetitions of any infinite %-rule are allowed. If in the above
+example PREP was set to 1, then \fBdmake\fP would generate the dependency
+graph:
+.RS
+.sp
+% --> RCS/%,v --> RCS/RCS/%,v,v
+.sp
+.RE
+Where each link is assigned the same recipe as the first link.
+PREP should be used only in special cases, since it may result in
+a large increase in the number of possible prerequisites tested.
+.B dmake
+further assumes that any target that has no suffix can be made from
+a prerequisite that has at least one suffix.
+.PP
+.B dmake
+supports dynamic prerequisite generation for prerequisites of %-meta rules.
+This is best illustrated by an example. The RCS rule shown above can infer
+how to check out a file from a corresponding RCS file only if the target
+is a simple file name with no directory information. That is, the above rule
+can infer how to find \fIRCS/fred.c,v\fP from the target \fIfred.c\fP,
+but cannot infer how to find \fIsrcdir/RCS/fred.c,v\fP from \fIsrcdir/fred.c\fP
+because the above rule will cause \fBdmake\fP to look for RCS/srcdir/fred.c,v;
+which does not exist (assume that srcdir has its own RCS directory as is the
+common case).
+.PP
+A more versatile formulation of the above RCS check out rule is the following:
+.RS
+.sp
+% : $$(@:d)RCS/$$(@:f),v : co $@
+.sp
+.RE
+This rule uses the dynamic macro $@ to specify the prerequisite to try to
+infer. During inference of this rule the macro $@ is set to the value of
+the target of the %-meta rule and the appropriate prerequisite is generated by
+extracting the directory portion of the target name (if any), appending the
+string \fIRCS/\fP to it, and appending the target file name with a trailing
+\fI,v\fP attached to the previous result.
+.PP
+.B dmake
+can also infer indirect prerequisites.
+An inferred target can have a list of prerequisites added that will not
+show up in the value of $< but will show up in the value of $? and $&.
+Indirect prerequisites are specified in an inference rule by quoting the
+prerequisite with single quotes. For example, if you had the explicit
+dependency:
+.RS
+.sp
+.nf
+fred.o : fred.c ; rule to make fred.o
+fred.o : local.h
+.fi
+.sp
+.RE
+then this can be inferred for fred.o from the following inference rule:
+.RS
+.sp
+%.o : %.c 'local.h' ; makes a .o from a .c
+.sp
+.RE
+You may infer indirect prerequisites that are a function of the value of '%'
+in the current rule. The meta-rule:
+.RS
+.sp
+%.o : %.c '$(INC)/%.h' ; rule to make a .o from a .c
+.sp
+.RE
+infers an indirect prerequisite found in the INC directory whose name is the
+same as the expansion of $(INC), and the prerequisite name depends on the
+base name of the current target.
+The set of indirect prerequisites is attached to the meta rule in which they
+are specified and are inferred only if the rule is used to infer a recipe
+for a target. They do not play an active role in driving the inference
+algorithm.
+The construct:
+.RS
+.sp
+%.o : %.c %.f 'local.h'; recipe
+.sp
+.RE
+is equivalent to:
+.RS
+.sp
+.nf
+%.o : %.c 'local.h' : recipe
+.fi
+.sp
+.RE
+while:
+.RS
+.sp
+%.o :| %.c %.f 'local.h'; recipe
+.sp
+.RE
+is equivalent to:
+.RS
+.sp
+.nf
+%.o : %.c 'local.h' : recipe
+%.o : %.f 'local.h' : recipe
+.fi
+.sp
+.RE
+.PP
+If any of the attributes .SETDIR, .EPILOG, .PROLOG, .SILENT,
+\&.USESHELL, .SWAP, .PRECIOUS, .LIBRARY, .NOSTATE and .IGNORE
+are given for a %-rule then when that rule is bound to a target
+as the result of an inference, the target's set of attributes is augmented by
+the attributes from the above set that are specified in the bound %-rule.
+Other attributes specified for %-meta rules are not inherited by the target.
+The .SETDIR attribute is treated in a special way.
+If the target already had a .SETDIR attribute set then
+.B dmake
+changes to that directory prior to performing the inference.
+During inference any .SETDIR attributes for the inferred prerequisite
+are honored.
+The directories must exist for a %-meta rule to be selected as a possible
+inference path. If the directories do not exist no error message is issued,
+instead the corresponding path in the inference graph is rejected.
+.PP
+.B dmake
+also supports the old format special target .<suffix>.<suffix>
+by identifying any rules
+of this form and mapping them to the appropriate %-rule. So for example if
+an old makefile contains the construct:
+.RS
+.sp
+\&.c.o :; cc \-c $< \-o $@
+.sp
+.RE
+.B dmake
+maps this into the following %-rule:
+.RS
+.sp
+%.o : %.c; cc \-c $< \-o $@
+.sp
+.RE
+Furthermore,
+.B dmake
+understands several SYSV AUGMAKE special targets and maps them into
+corresponding %-meta rules. These transformation must be enabled by providing
+the \-A flag on the command line or by setting the value of AUGMAKE to
+non\-NULL.
+The construct
+.RS
+.sp
+\&.suff :; recipe
+.sp
+.RE
+gets mapped into:
+.RS
+.sp
+% : %.suff; recipe
+.sp
+.RE
+and the construct
+.RS
+.sp
+\&.c~.o :; recipe
+.sp
+.RE
+gets mapped into:
+.RS
+.sp
+%.o : s.%.c ; recipe
+.sp
+.RE
+In general, a special target of the form .<str>~ is replaced by the %-rule
+construct s.%.<str>, thereby providing support for the syntax used by SYSV
+AUGMAKE for providing SCCS support.
+When enabled, these mappings allow processing of existing SYSV
+makefiles without modifications.
+.PP
+.B dmake
+bases all of its inferences on the inference graph constructed from the
+%-rules defined in the makefile.
+It knows exactly which targets can be made from which prerequisites by
+making queries on the inference graph. For this reason .SUFFIXES is not
+needed and is completely ignored.
+.PP
+For a %-meta rule to be inferred as the
+rule whose recipe will be used to make a target, the target's name must match
+the %-target pattern, and any inferred %-prerequisite must already exist or
+have an explicit recipe so that the prerequisite can be made.
+Without \fItransitive closure\fP on the inference graph the above rule
+describes precisely when an inference match terminates the search.
+If transitive closure is enabled (the usual case), and a prerequisite does
+not exist or cannot be made, then
+.B dmake
+invokes the inference algorithm recursively on the prerequisite to see if
+there is some way the prerequisite can be manufactured. For, if the
+prerequisite can be made then the current target can also be made using the
+current %-meta rule.
+This means that there is no longer a need to give a rule
+for making a .o from a .y if you have already given a rule for making a .o
+from a .c and a .c from a .y. In such cases
+.B dmake
+can infer how to make the
+\&.o from the .y via the intermediary .c and will remove the .c when the .o is
+made. Transitive closure can be disabled by giving the \-T switch on the
+command line.
+.PP
+A word of caution.
+.B dmake
+bases its transitive closure on the %-meta rule targets.
+When it performs transitive closure it infers how to make a target from a
+prerequisite by performing a pattern match as if the potential prerequisite
+were a new target.
+The set of rules:
+.RS
+.nf
+.sp
+%.o : %.c :; rule for making .o from .c
+%.c : %.y :; rule for making .c from .y
+% : RCS/%,v :; check out of RCS file
+.fi
+.sp
+.RE
+will, by performing transitive closure, allow \fBdmake\fP to infer how to make
+a .o from a .y using a .c as an intermediate temporary file. Additionally
+it will be able to infer how to make a .y from an RCS file, as long as that
+RCS file is in the RCS directory and has a name which ends in .y,v.
+The transitivity computation is performed dynamically for each target that
+does not have a recipe. This has potential to be costly if the %-meta
+rules are not carefully specified. The .NOINFER attribute is used to mark
+a %-meta node as being a final target during inference. Any node with this
+attribute set will not be used for subsequent inferences. As an example
+the node RCS/%,v is marked as a final node since we know that if the RCS file
+does not exist there likely is no other way to make it. Thus the standard
+startup makefile contains an entry similar to:
+.RS
+.nf
+\&.NOINFER : RCS/%,v
+.fi
+.RE
+Thereby indicating that the RCS file is the end of the inference chain.
+Whenever the inference algorithm determines that a target can be made from
+more than one prerequisite and the inference chains for the two methods
+are the same length the algorithm reports an ambiguity and prints the
+ambiguous inference chains.
+.PP
+.B dmake
+tries to
+remove intermediate files resulting from transitive closure if the file
+is not marked as being PRECIOUS, or the \fB\-u\fP flag was not given on the
+command line, and if the inferred intermediate did not previously exist.
+Intermediate targets that existed prior to being made are never removed.
+This is in keeping with the philosophy that
+.B dmake
+should never remove things from the file system that it did not add.
+If the special target .REMOVE is defined and has a recipe then
+.B dmake
+constructs a list of the intermediate files to be removed and makes them
+prerequisites of .REMOVE. It then makes .REMOVE thereby removing the
+prerequisites if the recipe of .REMOVE says to. Typically .REMOVE is defined
+in the startup file as:
+.RS
+.sp
+\&.REMOVE :; $(RM) $<
+.RE
+.SH "MAKING TARGETS"
+In order to update a target \fBdmake\fP must execute a recipe.
+When a recipe needs to be executed it is first expanded so that any macros
+in the recipe text are expanded, and it is then either executed directly or
+passed to a shell.
+.B dmake
+supports two types of recipes. The regular recipes and group recipes.
+.PP
+When a regular recipe is invoked \fBdmake\fP executes each line of the recipe
+separately using a new copy of a shell if a shell is required.
+Thus effects of commands do not generally persist across recipe lines
+(e.g. cd requests in a recipe line do not carry over to the next recipe line).
+This is true even in environments such as \fBMSDOS\fP, where dmake internally
+sets the current working director to match the directory it was in before
+the command was executed.
+.PP
+The decision on whether a shell is required to execute a command is based on
+the value of the macro SHELLMETAS or on the specification of '+' or .USESHELL
+for the current recipe or target respectively.
+If any character in the value of
+SHELLMETAS is found in the expanded recipe text-line or the use of a shell
+is requested explicitly via '+' or .USESHELL then the command is
+executed using a shell, otherwise the command is executed directly.
+The shell that is used for execution is given by the value of the macro SHELL.
+The flags that are passed to the shell are given by the value of SHELLFLAGS.
+Thus \fBdmake\fP constructs the command line:
+.sp
+\t$(SHELL) $(SHELLFLAGS) $(expanded_recipe_command)
+.sp
+Normally
+.B dmake
+writes the command line that it is about to invoke to standard output.
+If the .SILENT attribute is set for the target or for
+the recipe line (via @), then the recipe line is not echoed.
+.PP
+Group recipe processing is similar to that of regular recipes, except that
+a shell is always invoked. The shell that is invoked is given by the value of
+the macro GROUPSHELL, and its flags are taken from the value of the macro
+GROUPFLAGS. If a target has the .PROLOG attribute set then
+.B dmake
+prepends to the shell script the recipe associated with the special target
+\&.GROUPPROLOG, and if the attribute .EPILOG is set as well, then the recipe
+associated with the special target .GROUPEPILOG is appended to the script
+file.
+This facility can be used to always prepend a common header and common trailer
+to group recipes.
+Group recipes are echoed to standard output just like standard recipes, but
+are enclosed by lines beginning with [ and ].
+.PP
+The recipe flags [+,\-,%,@] are recognized at the start of a recipe line
+even if they appear in a macro. For example:
+.RS
+.sp
+.nf
+SH = +
+all:
+\t$(SH)echo hi
+.fi
+.sp
+.RE
+is completely equivalent to writing
+.RS
+.sp
+.nf
+SH = +
+all:
+\t+echo hi
+.fi
+.sp
+.RE
+.PP
+The last step performed by
+.B dmake
+prior to running a recipe is to set the macro CMNDNAME to the name of the
+command to execute (determined by finding the first white\-space ending token
+in the command line). It then sets the macro CMNDARGS to be the remainder
+of the line.
+.B dmake
+then expands the macro COMMAND which by default is set to
+.RS
+.sp
+COMMAND = $(CMNDNAME) $(CMNDARGS)
+.sp
+.RE
+The result of this final expansion is the command that will be executed.
+The reason for this expansion is to allow for a different interface to
+the argument passing facilities (esp. under DOS) than that provided by
+.B dmake\fR.\fP
+You can for example define COMMAND to be
+.RS
+.sp
+COMMAND = $(CMNDNAME) @$(mktmp $(CMNDARGS))
+.sp
+.RE
+which dumps the arguments into a temporary file and runs the command
+.RS
+.sp
+$(CMNDNAME) @/tmp/ASAD23043
+.sp
+.RE
+which has a much shorter argument list. It is now up to the command to
+use the supplied argument as the source for all other arguments.
+As an optimization, if COMMAND is not defined
+.B dmake
+does not perform the above expansion. On systems, such as UNIX, that
+handle long command lines this provides a slight saving in processing the
+makefiles.
+.SH "MAKING LIBRARIES"
+Libraries are easy to maintain using \fBdmake\fP. A library is a file
+containing a collection of object files.
+Thus to make a library you simply specify it as a target with the .LIBRARY
+attribute set and specify its list of prerequisites. The prerequisites should
+be the object members that are to go into the library. When
+.B dmake
+makes the library target it uses the .LIBRARY attribute to pass to the
+prerequisites the .LIBMEMBER attribute and the name of the library. This
+enables the file binding mechanism to look for the member in the library if an
+appropriate object file cannot be found.
+.B dmake
+now supports \fBElf\fP libraries on systems that support \fBElf\fP and
+hence supports, on those systems, long member file names.
+A small example best illustrates this.
+.RS
+.nf
+.sp
+mylib.a .LIBRARY : mem1.o mem2.o mem3.o
+\trules for making library...
+\t# remember to remove .o's when lib is made
+.sp
+# equivalent to: '%.o : %.c ; ...'
+\&.c.o :; rules for making .o from .c say
+.sp
+.fi
+.RE
+.B dmake
+will use the .c.o rule for making the library members if appropriate .c files
+can be found using the search rules. NOTE: this is not specific in any way
+to C programs, they are simply used as an example.
+.PP
+.B dmake
+tries to handle the old library construct format in a sensible way.
+The construct
+.I lib(member.o)
+is separated and the \fIlib\fP portion is declared
+as a library target.
+The new target is defined
+with the .LIBRARY attribute set and the \fImember.o\fP portion of the
+construct is
+declared as a prerequisite of the lib target.
+If the construct \fIlib(member.o)\fP
+appears as a prerequisite of a target in the
+makefile, that target has the new name of the lib assigned as its
+prerequisite. Thus the following example:
+.RS
+.sp
+.nf
+a.out : ml.a(a.o) ml.a(b.o); $(CC) \-o $@ $<
+
+\&.c.o :; $(CC) \-c $(CFLAGS) \-o $@ $<
+%.a:
+.RS
+ar rv $@ $?
+ranlib $@
+rm \-rf $?
+.RE
+.sp
+.fi
+.RE
+constructs the following dependency
+graph.
+.RS
+.sp
+.nf
+a.out : ml.a; $(CC) \-o $@ $<
+ml.a .LIBRARY : a.o b.o
+
+%.o : %.c ; $(CC) -c $(CFLAGS) \-o $@ $<
+%.a :
+.RS
+ar rv $@ $?
+ranlib $@
+rm -rf $?
+.RE
+.sp
+.fi
+.RE
+and making a.out then works as expected.
+.PP
+The same thing happens for any target of the form \fIlib((entry))\fP.
+These targets have an
+additional feature in that the \fIentry\fP target has the .SYMBOL attribute
+set automatically.
+.PP
+NOTE: If the notion of entry points is supported by the archive and by
+\fBdmake\fP (currently not the case) then
+.B dmake
+will search the archive for the entry point and return not only the
+modification time of the member which defines the entry but also the name of
+the member file. This name will then replace \fIentry\fP and will be used for
+making the member file. Once bound to an archive member the .SYMBOL
+attribute is removed from the target.
+This feature is presently disabled as there is little standardization
+among archive formats, and we have yet to find a makefile utilizing this
+feature (possibly due to the fact that it is unimplemented in most versions
+of UNIX Make).
+.PP
+Finally, when
+.B dmake
+looks for a library member it must first locate the library file.
+It does so by first looking for the library relative to the current directory
+and if it is not found it then looks relative to the current value of
+$(TMD). This allows commonly used libraries to be kept near the root of
+a source tree and to be easily found by
+.B dmake\fR.\fP
+.SH "KEEP STATE"
+.B dmake
+supports the keeping of state information for targets that it makes whenever
+the macro .KEEP_STATE is assigned a value. The value of the macro should be
+the name of a state file that will contain the state information. If state
+keeping is enabled then each target that does not poses the .NOSTATE
+attribute will have a record written into the state file indicating the
+target's name, the current directory, the command used to update the target,
+and which, if any, :: rule is being used. When you make this target again
+if any of this information does not match the previous settings and the
+target is not out dated it will still be re\-made. The assumption is that one
+of the conditions above has changed and that we wish to remake the target.
+For example,
+state keeping is used in the maintenance of
+.B dmake
+to test compile different versions of the source using different compilers.
+Changing the compiler causes the compilation flags to be modified and hence
+all sources to be recompiled.
+.PP
+The state file is an ascii file and is portable, however it is
+not in human readable form as the entries represent hash keys of the above
+information.
+.PP
+The Sun Microsystem's Make construct
+.RS
+.sp
+\&.KEEP_STATE :
+.sp
+.RE
+is recognized and is mapped to \fB.KEEP_STATE:=_state.mk\fP.
+The
+.B dmake
+version of state keeping does not include scanning C source files for
+dependencies like Sun Make. This is specific to C programs and it was
+felt that it does not belong in make.
+.B dmake
+instead provides the tool, \fBcdepend\fP, to scan C source files and to produce
+depedency information. Users are free to modify cdepend to produce other
+dependency files. (NOTE:
+.B cdepend
+does not come with the distribution at this time, but will be available in
+a patch in the near future)
+.SH "MULTI PROCESSING"
+If the architecture supports it then \fBdmake\fP is capable of making a target's
+prerequisites in parallel. \fBdmake\fP will make as much in parallel as it
+can and use a number of child processes up to the maximum specified by
+MAXPROCESS or by the value supplied to the \-P command line flag.
+A parallel make is enabled by setting the value of MAXPROCESS (either directly
+or via \-P option) to a value which is > 1.
+\fBdmake\fP guarantees that all dependencies as specified in the makefile are
+honored. A target will not be made until all of its prerequisites have been
+made. Note that when you specify \fB-P 4\fP then four child processes are
+run concurrently but \fBdmake\fP actually displays the fifth command it will
+run immediately upon a child process becomming free. This is an artifact of
+the method used to traverse the dependency graph and cannot be removed.
+If a parallel make is being performed then the following restrictions on
+parallelism are enforced.
+.RS
+.IP 1.
+Individual recipe lines in a non-group recipe are performed sequentially in
+the order in which they are specified within the makefile and in parallel with
+the recipes of other targets.
+.IP 2.
+If a target contains multiple recipe definitions (cf. :: rules) then these are
+performed sequentially in the order in which the :: rules are specified within
+the makefile and in parallel with the recipes of other targets.
+.IP 3.
+If a target rule contains the `!' modifier, then the recipe is performed
+sequentially for the list of outdated prerequisites and in parallel with the recipes of other targets.
+.IP 4.
+If a target has the .SEQUENTIAL attribute set then all of its prerequisites
+are made sequentially relative to one another (as if MAXPROCESS=1), but in
+parallel with other targets in the makefile.
+.RE
+.PP
+Note: If you specify a parallel make then
+the order of target update and the order in which the associated recipes are
+invoked will not correspond to that displayed by the \-n flag.
+.SH "CONDITIONALS"
+.B dmake
+supports a makefile construct called a \fIconditional\fR. It allows
+the user
+to conditionally select portions of makefile text for input processing
+and to discard other portions. This becomes useful for
+writing makefiles that are intended to function for more than one target
+host and environment. The conditional expression is specified as follows:
+.sp
+.RS
+.nf
+\&.IF \fIexpression\fR
+ ... if text ...
+\&.ELIF \fIexpression\fR
+ ... if text ...
+\&.ELSE
+ ... else text ...
+\&.END
+.RE
+.fi
+.sp
+The .ELSE and .ELIF portions are optional, and the conditionals may be
+nested (ie. the text may contain another conditional).
+\&.IF, .ELSE, and .END
+may appear anywhere in the makefile, but a single conditional expression
+may not span multiple makefiles.
+.PP
+\fIexpression\fR can be one of the following three forms:
+.sp
+\t<text> | <text> == <text> | <text> != <text>
+.sp
+where \fItext\fR is either text or a macro expression. In any case,
+before the comparison is made, the expression is expanded. The text
+portions are then selected and compared. White space at the start and
+end of the text portion is discarded before the comparison. This means
+that a macro that evaluates to nothing but white space is considered a
+NULL value for the purpose of the comparison.
+In the first case the expression evaluates TRUE if the text is not NULL
+otherwise it evaluates FALSE. The remaining two cases both evaluate the
+expression on the basis of a string comparison.
+If a macro expression needs to be equated to a NULL string then compare it to
+the value of the macro $(NULL).
+You can use the $(shell ...) macro to construct more complex test expressions.
+.SH "EXAMPLES"
+.RS
+.nf
+.sp
+# A simple example showing how to use make
+#
+prgm : a.o b.o
+ cc a.o b.o \-o prgm
+a.o : a.c g.h
+ cc a.c \-o $@
+b.o : b.c g.h
+ cc b.c \-o $@
+.fi
+.RE
+.sp
+In the previous
+example prgm is remade only if a.o and/or b.o is out of date with
+respect to prgm.
+These dependencies can be stated more concisely
+by using the inference rules defined in the standard startup file.
+The default rule for making .o's from .c's looks something like this:
+.sp
+\&\t%.o : %.c; cc \-c $(CFLAGS) \-o $@ $<
+.sp
+Since there exists a rule (defined in the startup file)
+for making .o's from .c's
+\fBdmake\fR will use that rule
+for manufacturing a .o from a .c and we can specify our dependencies
+more concisely.
+.sp
+.RS
+.nf
+prgm : a.o b.o
+ cc \-o prgm $<
+a.o b.o : g.h
+.fi
+.RE
+.sp
+A more general way to say the above using the new macro expansions
+would be:
+.sp
+.RS
+.nf
+SRC = a b
+OBJ = {$(SRC)}.o
+.sp
+prgm : $(OBJ)
+ cc \-o $@ $<
+.sp
+$(OBJ) : g.h
+.fi
+.RE
+.sp
+If we want to keep the objects in a separate directory, called
+objdir, then we would write
+something like this.
+.sp
+.RS
+.nf
+SRC = a b
+OBJ = {$(SRC)}.o
+.sp
+prgm : $(OBJ)
+ cc $< \-o $@
+.sp
+$(OBJ) : g.h
+\&%.o : %.c
+ $(CC) \-c $(CFLAGS) \-o $(@:f) $<
+ mv $(@:f) objdir
+
+\&.SOURCE.o : objdir # tell dmake to look here for .o's
+.fi
+.RE
+.sp
+An example of building library members would go something like this:
+(NOTE: The same rules as above will be used to produce .o's from .c's)
+.sp
+.RS
+.nf
+SRC\t= a b
+LIB\t= lib
+LIBm\t= { $(SRC) }.o
+.sp
+prgm: $(LIB)
+ cc \-o $@ $(LIB)
+.sp
+$(LIB) .LIBRARY : $(LIBm)
+ ar rv $@ $<
+ rm $<
+.fi
+.RE
+.sp
+Finally, suppose that each of the source files in the previous example had
+the `:' character in their target name. Then we would write the above example
+as:
+.sp
+.RS
+.nf
+SRC\t= f:a f:b
+LIB\t= lib
+LIBm\t= "{ $(SRC) }.o" # put quotes around each token
+.sp
+prgm: $(LIB)
+ cc \-o $@ $(LIB)
+.sp
+$(LIB) .LIBRARY : $(LIBm)
+ ar rv $@ $<
+ rm $<
+.fi
+.RE
+.SH "COMPATIBILITY"
+There are two notable differences between
+.B \fBdmake\fR
+and the standard version of BSD UNIX 4.2/4.3 Make.
+.RS
+.IP 1. .3i
+BSD UNIX 4.2/4.3 Make supports wild card filename expansion for
+prerequisite names. Thus if a directory contains a.h, b.h and c.h, then a
+line like
+.sp
+\ttarget: *.h
+.sp
+will cause UNIX make to expand the *.h into "a.h b.h c.h". \fBdmake\fR
+does not support this type of filename expansion.
+.IP 2. .3i
+Unlike UNIX make, touching a library member causes \fBdmake\fR
+to search the library for the member name and to update the library time stamp.
+This is only implemented in the UNIX version.
+MSDOS and other versions may not have librarians that keep file time stamps,
+as a result \fBdmake\fR touches the library file itself, and prints a warning.
+.RE
+.PP
+\fBdmake\fP is not compatible with GNU Make. In particular it does not
+understand GNU Make's macro expansions that query the file system.
+.PP
+.B dmake
+is fully compatible with SYSV AUGMAKE, and supports the following AUGMAKE
+features:
+.RS
+.IP 1. .3i
+GNU Make style \fBinclude\fP, and \fBif/else/endif\fP directives are allowed
+in non-group recipes.
+Thus, the word \fBinclude\fP appearing at
+the start of a line that is not part of a gruop recipe will be mapped
+to the ".INCLUDE" directive that \fBdamke\fP uses.
+Similarly, the words \fBifeq\fP,\fBifneq\fP,\fBelif\fP,\fBelse\fP,
+and \fBendif\fP are mapped to their corresponding \fBdmake\fP equivalents.
+.IP 2. .3i
+The macro modifier expression $(macro:str=sub) is understood and is equivalent
+to the expression $(macro:s/str/sub), with the restriction that str must match
+the following regular expression:
+.sp
+\tstr[ |\et][ |\et]*
+.sp
+(ie. str only matches at the end of a token where str is a suffix and is
+terminated by a space, a tab, or end of line)
+Normally \fIsub\fP is expanded before the substitution is made, if you specify
+\-A on the command line then sub is not expanded.
+.IP 3.
+The macro % is defined to be $@ (ie. $% expands to the same value as $@).
+.IP 4.
+The AUGMAKE notion of libraries is handled correctly.
+.IP 5.
+When defining special targets for the inference rules and the AUGMAKE special
+target handling is enabled then the special target
+\&.X is equivalent to the %-rule "% : %.X".
+.IP 6.
+Directories are always made if you specify \fB\-A\fP. This is consistent
+with other UNIX versions of Make.
+.IP 7.
+Makefiles that utilize virtual targets to force making of other targets work
+as expected if AUGMAKE special target handling is enabled. For example:
+.sp
+.nf
+\tFRC:
+\tmyprog.o : myprog.c $(FRC) ; ...
+.fi
+.sp
+Works as expected if you issue the command
+.sp
+\t'\fBdmake\fP \-A FRC=FRC'
+.sp
+but fails with a 'don't know how to make FRC'
+error message if you do not specify AUGMAKE special target handling via
+the \-A flag (or by setting AUGMAKE:=yes internally).
+.IP 8.
+The \fBMSDOS\fP version of \fBdmake\fP now supports a single buitin runtime
+command \fBnoop\fP, which returns success if requested and does nothing.
+.RE
+.SH "LIMITS"
+In some environments the length of an argument string is restricted.
+(e.g. MSDOS command line arguments cannot be longer than 128 bytes if you are
+using the standard command.com command interpreter as your shell,
+.B dmake
+text diversions may help in these situations.)
+.SH "PORTABILITY"
+To write makefiles that can be moved from one environment to another requires
+some forethought. In particular you must define as macros all those things
+that may be different in the new environment.
+.B dmake
+has two facilities that help to support writing portable makefiles, recursive
+macros and conditional expressions. The recursive macros, allow one to define
+environment configurations that allow different environments for similar types
+of operating systems. For example the same make script can be used for SYSV and
+BSD but with different macro definitions.
+.PP
+To write a makefile that is portable between UNIX and MSDOS requires both
+features since in almost all cases you will need to define new recipes for
+making targets. The recipes will probably be quite different since the
+capabilities of the tools on each machine are different. Different
+macros will be needed to help handle the smaller differences in the two
+environments.
+.SH FILES
+Makefile, makefile, startup.mk (use dmake \-V to tell you where the startup
+file is)
+.SH "SEE ALSO"
+sh(1), csh(1), touch(1), f77(1), pc(1), cc(1)
+.br
+S.I. Feldman \fIMake - A Program for Maintaining Computer Programs\fP
+.SH "AUTHOR"
+Dennis Vadura, dvadura@wticorp.com
+.br
+Many thanks to Carl Seger for his helpful suggestions,
+and to Trevor John Thompson for his many excellent ideas and
+informative bug reports. Many thanks also go to those on the
+NET that have helped in making \fBdmake\fP one of the best Make tools
+available.
+.SH BUGS
+Some system commands return non-zero status inappropriately.
+Use
+.B \-i
+(`\-' within the makefile) to overcome the difficulty.
+.PP
+Some systems do not have easily accessible
+time stamps for library members (MSDOS, AMIGA, etc)
+for these \fBdmake\fR uses the time stamp of the library instead and prints
+a warning the first time it does so. This is almost always ok, except when
+multiple makefiles update a single library file. In these instances it is
+possible to miss an update if one is not careful.
+.PP
+This man page is way too long.
+.SH WARNINGS
+Rules supported by make(1) may not work if transitive closure is turned off
+(-T, .NOINFER).
+.PP
+PWD from csh/ksh will cause problems if a cd operation is performed and
+-e or -E option is used.
+.PP
+Using internal macros such as COMMAND, may wreak havoc if you don't understand
+their functionality.
diff --git a/dmake/man/readme b/dmake/man/readme
new file mode 100644
index 000000000000..f9fc689e6076
--- /dev/null
+++ b/dmake/man/readme
@@ -0,0 +1,26 @@
+This directory contains the DMAKE manual page. The typeset version of the
+manual is compressed and uuencoded as this is the only reasonable method of
+shipping the control-character filled manpage around.
+
+To unpack the typeset manual page please issue the following sequence of
+commands:
+
+ uudecode dmake.uue
+ uncompress dmake.Z
+ mv dmake dmake.p
+
+NOTE: You only need to do this if you cannot typeset the manual page
+ yourself.
+
+The other two files found here are:
+
+ dmake.tf - troff source for the manual page, you must use
+ GNU groff to typeset it.
+ dmake.nc - a typeset version of the manual page containing
+ no control characters.
+
+Alternately visit the dmake WWW site, at
+
+ http://www.wticorp.com/dmake/dmake.html
+
+Dennis
diff --git a/dmake/msdos/arlib.c b/dmake/msdos/arlib.c
new file mode 100644
index 000000000000..ecd556b7d621
--- /dev/null
+++ b/dmake/msdos/arlib.c
@@ -0,0 +1,56 @@
+/* RCS $Id: arlib.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Library access code.
+--
+-- DESCRIPTION
+-- This implementation uses the library timestamp inplace of the
+-- library member timestamp.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+PUBLIC time_t
+seek_arch(name, lib)
+char* name;
+char* lib;
+{
+ static int warned = FALSE;
+
+ if (!warned && !(Glob_attr&A_SILENT))
+ warned = TRUE,
+ Warning("Can't extract library member timestamp;\n\
+ using library timestamp instead.");
+ return (Do_stat(lib, NULL, NULL, TRUE));
+}
+
+PUBLIC int
+touch_arch(name, lib)
+char* name;
+char* lib;
+{
+ static int warned = FALSE;
+
+ if (!warned && !(Glob_attr&A_SILENT))
+ warned = TRUE,
+ Warning("Can't update library member timestamp;\n\
+ touching library instead.");
+ return (Do_touch(lib, NULL, NULL));
+}
+
diff --git a/dmake/msdos/borland/bcc30/config.h b/dmake/msdos/borland/bcc30/config.h
new file mode 100644
index 000000000000..8e02779edd75
--- /dev/null
+++ b/dmake/msdos/borland/bcc30/config.h
@@ -0,0 +1,48 @@
+/* RCS $Id: config.h,v 1.1.1.1 2000-09-22 15:33:28 hr Exp $
+--
+-- SYNOPSIS
+-- Configurarion include file.
+--
+-- DESCRIPTION
+-- There is one of these for each specific machine configuration.
+-- It can be used to further tweek the machine specific sources
+-- so that they compile.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* define this for configurations that don't have the coreleft function
+ * so that the code compiles. To my knowledge coreleft exists only on
+ * Turbo C, but it is needed here since the function is used in many debug
+ * macros. */
+/*#define coreleft() 0L*/
+extern unsigned int coreleft();
+
+#define SIGQUIT SIGTERM /* turbo C doesn't understand SIGQUIT */
+
+/* Turbo-C understands const declarations. */
+#define CONST const
+
+#ifndef MSDOS
+# define MSDOS 1
+#endif
+
+/* a small problem with pointer to voids on some unix machines needs this */
+#define PVOID void *
+
+/* Have to pull this in for the standard lib defines */
+#include <io.h>
diff --git a/dmake/msdos/borland/bcc30/config.mk b/dmake/msdos/borland/bcc30/config.mk
new file mode 100644
index 000000000000..0b1d122a868c
--- /dev/null
+++ b/dmake/msdos/borland/bcc30/config.mk
@@ -0,0 +1,8 @@
+
+# Definition of macros for library, and C startup code.
+osedir = $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)
+
+LDLIBS = e:/cc/borland/bcc30/lib/c$(MODEL)
+CSTARTUP = e:/cc/borland/bcc30/lib/c0$(MODEL).obj
+
+CFLAGS += -I$(osedir) -w-pia
diff --git a/dmake/msdos/borland/bcc30/lib.rsp b/dmake/msdos/borland/bcc30/lib.rsp
new file mode 100644
index 000000000000..41e591347bae
--- /dev/null
+++ b/dmake/msdos/borland/bcc30/lib.rsp
@@ -0,0 +1 @@
+d:\cc\borland\bcc30\lib\cl
diff --git a/dmake/msdos/borland/bcc30/libswp.rsp b/dmake/msdos/borland/bcc30/libswp.rsp
new file mode 100644
index 000000000000..64f053bf1fb1
--- /dev/null
+++ b/dmake/msdos/borland/bcc30/libswp.rsp
@@ -0,0 +1 @@
+e:\cc\borland\bcc30\lib\cl
diff --git a/dmake/msdos/borland/bcc30/mkswp.bat b/dmake/msdos/borland/bcc30/mkswp.bat
new file mode 100755
index 000000000000..9266d8dfc0cd
--- /dev/null
+++ b/dmake/msdos/borland/bcc30/mkswp.bat
@@ -0,0 +1,107 @@
+md objects
+tasm -t -mx -dmlarge msdos\exec.asm,,,;
+mv exec.obj objects
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia infer.c
+copy infer.obj objects
+del infer.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia make.c
+copy make.obj objects
+del make.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia stat.c
+copy stat.obj objects
+del stat.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia expand.c
+copy expand.obj objects
+del expand.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia dmstring.c
+copy dmstring.obj objects
+del dmstring.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia hash.c
+copy hash.obj objects
+del hash.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia dag.c
+copy dag.obj objects
+del dag.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia dmake.c
+copy dmake.obj objects
+del dmake.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia path.c
+copy path.obj objects
+del path.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia imacs.c
+copy imacs.obj objects
+del imacs.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia sysintf.c
+copy sysintf.obj objects
+del sysintf.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia parse.c
+copy parse.obj objects
+del parse.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia getinp.c
+copy getinp.obj objects
+del getinp.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia quit.c
+copy quit.obj objects
+del quit.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia state.c
+copy state.obj objects
+del state.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia dmdump.c
+copy dmdump.obj objects
+del dmdump.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia macparse.c
+copy macparse.obj objects
+del macparse.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia rulparse.c
+copy rulparse.obj objects
+del rulparse.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia percent.c
+copy percent.obj objects
+del percent.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia function.c
+copy function.obj objects
+del function.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia msdos\ruletab.c
+copy ruletab.obj objects
+del ruletab.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia msdos\dirbrk.c
+copy dirbrk.obj objects
+del dirbrk.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia msdos\runargv.c
+copy runargv.obj objects
+del runargv.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia msdos\arlib.c
+copy arlib.obj objects
+del arlib.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia msdos\dchdir.c
+copy dchdir.obj objects
+del dchdir.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia msdos\switchar.c
+copy switchar.obj objects
+del switchar.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia msdos\rmprq.c
+copy rmprq.obj objects
+del rmprq.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia msdos\spawn.c
+copy spawn.obj objects
+del spawn.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia msdos\find.c
+copy find.obj objects
+del find.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia msdos\dirlib.c
+copy dirlib.obj objects
+del dirlib.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia msdos\dstrlwr.c
+copy dstrlwr.obj objects
+del dstrlwr.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia unix\dcache.c
+copy dcache.obj objects
+del dcache.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia msdos\borland\tempnam.c
+copy tempnam.obj objects
+del tempnam.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc30 -w-pia msdos\borland\utime.c
+copy utime.obj objects
+del utime.obj
+tlink @msdos\borland\bcc30\objswp.rsp,dmake.exe,NUL.MAP,@msdos\borland\bcc30\libswp.rsp
+copy msdos\borland\bcc30\template.mk startup\config.mk
diff --git a/dmake/msdos/borland/bcc30/obj.rsp b/dmake/msdos/borland/bcc30/obj.rsp
new file mode 100644
index 000000000000..3f396242ce36
--- /dev/null
+++ b/dmake/msdos/borland/bcc30/obj.rsp
@@ -0,0 +1,34 @@
+d:\cc\borland\bcc30\lib\c0l.obj+
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dirbrk.obj+
+objects\runargv.obj+
+objects\arlib.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\rmprq.obj+
+objects\tee.obj+
+objects\dirlib.obj+
+objects\find.obj+
+objects\dcache.obj+
+objects\tempnam.obj+
+objects\utime.obj
diff --git a/dmake/msdos/borland/bcc30/objswp.rsp b/dmake/msdos/borland/bcc30/objswp.rsp
new file mode 100644
index 000000000000..aa0bf5e5831a
--- /dev/null
+++ b/dmake/msdos/borland/bcc30/objswp.rsp
@@ -0,0 +1,36 @@
+e:\cc\borland\bcc30\lib\c0l.obj+
+objects\exec.obj+
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dirbrk.obj+
+objects\runargv.obj+
+objects\arlib.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\rmprq.obj+
+objects\spawn.obj+
+objects\find.obj+
+objects\dirlib.obj+
+objects\dstrlwr.obj+
+objects\dcache.obj+
+objects\tempnam.obj+
+objects\utime.obj
diff --git a/dmake/msdos/borland/bcc30/public.h b/dmake/msdos/borland/bcc30/public.h
new file mode 100644
index 000000000000..a091150efedc
--- /dev/null
+++ b/dmake/msdos/borland/bcc30/public.h
@@ -0,0 +1,169 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:28 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+int If_root_path ANSI((char *));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+void Clean_up_processes ANSI(());
+int Wait_for_child ANSI((int, int));
+time_t seek_arch ANSI((char*, char*));
+int touch_arch ANSI((char*, char*));
+int dchdir ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int spawnvpe ANSI((int, char *, char **, char **));
+void Hook_std_writes ANSI((char *));
+void dstrlwr ANSI((char *, char *));
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/msdos/borland/bcc30/template.mk b/dmake/msdos/borland/bcc30/template.mk
new file mode 100644
index 000000000000..df574e09c7aa
--- /dev/null
+++ b/dmake/msdos/borland/bcc30/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= msdos
+ OSRELEASE *:= borland
+ OSENVIRONMENT *:= bcc30
diff --git a/dmake/msdos/borland/bcc40/config.h b/dmake/msdos/borland/bcc40/config.h
new file mode 100644
index 000000000000..994a10eab1ba
--- /dev/null
+++ b/dmake/msdos/borland/bcc40/config.h
@@ -0,0 +1,51 @@
+/* RCS $Id: config.h,v 1.1.1.1 2000-09-22 15:33:28 hr Exp $
+--
+-- SYNOPSIS
+-- Configurarion include file.
+--
+-- DESCRIPTION
+-- There is one of these for each specific machine configuration.
+-- It can be used to further tweek the machine specific sources
+-- so that they compile.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* define this for configurations that don't have the coreleft function
+ * so that the code compiles. To my knowledge coreleft exists only on
+ * Turbo C, but it is needed here since the function is used in many debug
+ * macros. */
+/*#define coreleft() 0L*/
+extern unsigned int coreleft();
+
+#define SIGQUIT SIGTERM /* turbo C doesn't understand SIGQUIT */
+
+/* Turbo-C understands const declarations. */
+#define CONST const
+
+#ifndef MSDOS
+# define MSDOS 1
+#endif
+
+/* a small problem with pointer to voids on some unix machines needs this */
+#define PVOID void *
+
+/* Borland redefined the environment variable, sigh */
+#define environ _environ
+
+/* Have to pull this in for the standard lib defines */
+#include <io.h>
diff --git a/dmake/msdos/borland/bcc40/config.mk b/dmake/msdos/borland/bcc40/config.mk
new file mode 100644
index 000000000000..550b86950705
--- /dev/null
+++ b/dmake/msdos/borland/bcc40/config.mk
@@ -0,0 +1,7 @@
+# Definition of macros for library, and C startup code.
+osedir = $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)
+
+LDLIBS = e:/cc/borland/bcc40/lib/c$(MODEL)
+CSTARTUP = e:/cc/borland/bcc40/lib/c0$(MODEL).obj
+
+CFLAGS += -I$(osedir) -w-pro
diff --git a/dmake/msdos/borland/bcc40/lib.rsp b/dmake/msdos/borland/bcc40/lib.rsp
new file mode 100644
index 000000000000..828ccf4ab0b8
--- /dev/null
+++ b/dmake/msdos/borland/bcc40/lib.rsp
@@ -0,0 +1,2 @@
+e:\cc\borland\bcc40\lib\cw32+
+e:\cc\borland\bcc40\lib\import32
diff --git a/dmake/msdos/borland/bcc40/libswp.rsp b/dmake/msdos/borland/bcc40/libswp.rsp
new file mode 100644
index 000000000000..1557935cd40c
--- /dev/null
+++ b/dmake/msdos/borland/bcc40/libswp.rsp
@@ -0,0 +1 @@
+e:\cc\borland\bcc40\lib\cl
diff --git a/dmake/msdos/borland/bcc40/mkswp.bat b/dmake/msdos/borland/bcc40/mkswp.bat
new file mode 100755
index 000000000000..d8a1bf824de4
--- /dev/null
+++ b/dmake/msdos/borland/bcc40/mkswp.bat
@@ -0,0 +1,107 @@
+md objects
+tasm -t -mx -dmlarge msdos\exec.asm,,,;
+mv exec.obj objects
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro infer.c
+copy infer.obj objects
+del infer.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro make.c
+copy make.obj objects
+del make.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro stat.c
+copy stat.obj objects
+del stat.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro expand.c
+copy expand.obj objects
+del expand.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro dmstring.c
+copy dmstring.obj objects
+del dmstring.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro hash.c
+copy hash.obj objects
+del hash.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro dag.c
+copy dag.obj objects
+del dag.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro dmake.c
+copy dmake.obj objects
+del dmake.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro path.c
+copy path.obj objects
+del path.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro imacs.c
+copy imacs.obj objects
+del imacs.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro sysintf.c
+copy sysintf.obj objects
+del sysintf.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro parse.c
+copy parse.obj objects
+del parse.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro getinp.c
+copy getinp.obj objects
+del getinp.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro quit.c
+copy quit.obj objects
+del quit.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro state.c
+copy state.obj objects
+del state.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro dmdump.c
+copy dmdump.obj objects
+del dmdump.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro macparse.c
+copy macparse.obj objects
+del macparse.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro rulparse.c
+copy rulparse.obj objects
+del rulparse.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro percent.c
+copy percent.obj objects
+del percent.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro function.c
+copy function.obj objects
+del function.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro msdos\ruletab.c
+copy ruletab.obj objects
+del ruletab.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro msdos\dirbrk.c
+copy dirbrk.obj objects
+del dirbrk.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro msdos\runargv.c
+copy runargv.obj objects
+del runargv.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro msdos\arlib.c
+copy arlib.obj objects
+del arlib.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro msdos\dchdir.c
+copy dchdir.obj objects
+del dchdir.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro msdos\switchar.c
+copy switchar.obj objects
+del switchar.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro msdos\rmprq.c
+copy rmprq.obj objects
+del rmprq.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro msdos\spawn.c
+copy spawn.obj objects
+del spawn.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro msdos\find.c
+copy find.obj objects
+del find.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro msdos\dirlib.c
+copy dirlib.obj objects
+del dirlib.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro msdos\dstrlwr.c
+copy dstrlwr.obj objects
+del dstrlwr.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro unix\dcache.c
+copy dcache.obj objects
+del dcache.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro msdos\borland\tempnam.c
+copy tempnam.obj objects
+del tempnam.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc40 -w-pro msdos\borland\utime.c
+copy utime.obj objects
+del utime.obj
+tlink @msdos\borland\bcc40\objswp.rsp,dmake.exe,NUL.MAP,@msdos\borland\bcc40\libswp.rsp
+copy msdos\borland\bcc40\template.mk startup\config.mk
diff --git a/dmake/msdos/borland/bcc40/obj.rsp b/dmake/msdos/borland/bcc40/obj.rsp
new file mode 100644
index 000000000000..572259dca8ea
--- /dev/null
+++ b/dmake/msdos/borland/bcc40/obj.rsp
@@ -0,0 +1,34 @@
+e:\cc\borland\bcc40\lib\c0x32.obj+
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dirbrk.obj+
+objects\runargv.obj+
+objects\arlib.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\rmprq.obj+
+objects\find.obj+
+objects\tee.obj+
+objects\dirlib.obj+
+objects\dcache.obj+
+objects\tempnam.obj+
+objects\utime.obj
diff --git a/dmake/msdos/borland/bcc40/objswp.rsp b/dmake/msdos/borland/bcc40/objswp.rsp
new file mode 100644
index 000000000000..712d47f47504
--- /dev/null
+++ b/dmake/msdos/borland/bcc40/objswp.rsp
@@ -0,0 +1,36 @@
+e:\cc\borland\bcc40\lib\c0l.obj+
+objects\exec.obj+
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dirbrk.obj+
+objects\runargv.obj+
+objects\arlib.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\rmprq.obj+
+objects\spawn.obj+
+objects\find.obj+
+objects\dirlib.obj+
+objects\dstrlwr.obj+
+objects\dcache.obj+
+objects\tempnam.obj+
+objects\utime.obj
diff --git a/dmake/msdos/borland/bcc40/public.h b/dmake/msdos/borland/bcc40/public.h
new file mode 100644
index 000000000000..a091150efedc
--- /dev/null
+++ b/dmake/msdos/borland/bcc40/public.h
@@ -0,0 +1,169 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:28 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+int If_root_path ANSI((char *));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+void Clean_up_processes ANSI(());
+int Wait_for_child ANSI((int, int));
+time_t seek_arch ANSI((char*, char*));
+int touch_arch ANSI((char*, char*));
+int dchdir ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int spawnvpe ANSI((int, char *, char **, char **));
+void Hook_std_writes ANSI((char *));
+void dstrlwr ANSI((char *, char *));
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/msdos/borland/bcc40/template.mk b/dmake/msdos/borland/bcc40/template.mk
new file mode 100644
index 000000000000..30a27692f3ed
--- /dev/null
+++ b/dmake/msdos/borland/bcc40/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= msdos
+ OSRELEASE *:= borland
+ OSENVIRONMENT *:= bcc40
diff --git a/dmake/msdos/borland/bcc45/config.h b/dmake/msdos/borland/bcc45/config.h
new file mode 100644
index 000000000000..994a10eab1ba
--- /dev/null
+++ b/dmake/msdos/borland/bcc45/config.h
@@ -0,0 +1,51 @@
+/* RCS $Id: config.h,v 1.1.1.1 2000-09-22 15:33:28 hr Exp $
+--
+-- SYNOPSIS
+-- Configurarion include file.
+--
+-- DESCRIPTION
+-- There is one of these for each specific machine configuration.
+-- It can be used to further tweek the machine specific sources
+-- so that they compile.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* define this for configurations that don't have the coreleft function
+ * so that the code compiles. To my knowledge coreleft exists only on
+ * Turbo C, but it is needed here since the function is used in many debug
+ * macros. */
+/*#define coreleft() 0L*/
+extern unsigned int coreleft();
+
+#define SIGQUIT SIGTERM /* turbo C doesn't understand SIGQUIT */
+
+/* Turbo-C understands const declarations. */
+#define CONST const
+
+#ifndef MSDOS
+# define MSDOS 1
+#endif
+
+/* a small problem with pointer to voids on some unix machines needs this */
+#define PVOID void *
+
+/* Borland redefined the environment variable, sigh */
+#define environ _environ
+
+/* Have to pull this in for the standard lib defines */
+#include <io.h>
diff --git a/dmake/msdos/borland/bcc45/config.mk b/dmake/msdos/borland/bcc45/config.mk
new file mode 100644
index 000000000000..550b86950705
--- /dev/null
+++ b/dmake/msdos/borland/bcc45/config.mk
@@ -0,0 +1,7 @@
+# Definition of macros for library, and C startup code.
+osedir = $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)
+
+LDLIBS = e:/cc/borland/bcc40/lib/c$(MODEL)
+CSTARTUP = e:/cc/borland/bcc40/lib/c0$(MODEL).obj
+
+CFLAGS += -I$(osedir) -w-pro
diff --git a/dmake/msdos/borland/bcc45/lib.rsp b/dmake/msdos/borland/bcc45/lib.rsp
new file mode 100644
index 000000000000..db2b78d82438
--- /dev/null
+++ b/dmake/msdos/borland/bcc45/lib.rsp
@@ -0,0 +1,2 @@
+e:\cc\borland\bcc45\lib\cw32+
+e:\cc\borland\bcc45\lib\import32
diff --git a/dmake/msdos/borland/bcc45/libswp.rsp b/dmake/msdos/borland/bcc45/libswp.rsp
new file mode 100644
index 000000000000..1557935cd40c
--- /dev/null
+++ b/dmake/msdos/borland/bcc45/libswp.rsp
@@ -0,0 +1 @@
+e:\cc\borland\bcc40\lib\cl
diff --git a/dmake/msdos/borland/bcc45/mkswp.bat b/dmake/msdos/borland/bcc45/mkswp.bat
new file mode 100755
index 000000000000..c6bfede2f370
--- /dev/null
+++ b/dmake/msdos/borland/bcc45/mkswp.bat
@@ -0,0 +1,107 @@
+md objects
+tasm -t -mx -dmlarge msdos\exec.asm,,,;
+mv exec.obj objects
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro infer.c
+copy infer.obj objects
+del infer.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro make.c
+copy make.obj objects
+del make.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro stat.c
+copy stat.obj objects
+del stat.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro expand.c
+copy expand.obj objects
+del expand.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro dmstring.c
+copy dmstring.obj objects
+del dmstring.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro hash.c
+copy hash.obj objects
+del hash.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro dag.c
+copy dag.obj objects
+del dag.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro dmake.c
+copy dmake.obj objects
+del dmake.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro path.c
+copy path.obj objects
+del path.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro imacs.c
+copy imacs.obj objects
+del imacs.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro sysintf.c
+copy sysintf.obj objects
+del sysintf.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro parse.c
+copy parse.obj objects
+del parse.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro getinp.c
+copy getinp.obj objects
+del getinp.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro quit.c
+copy quit.obj objects
+del quit.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro state.c
+copy state.obj objects
+del state.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro dmdump.c
+copy dmdump.obj objects
+del dmdump.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro macparse.c
+copy macparse.obj objects
+del macparse.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro rulparse.c
+copy rulparse.obj objects
+del rulparse.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro percent.c
+copy percent.obj objects
+del percent.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro function.c
+copy function.obj objects
+del function.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro msdos\ruletab.c
+copy ruletab.obj objects
+del ruletab.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro msdos\dirbrk.c
+copy dirbrk.obj objects
+del dirbrk.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro msdos\runargv.c
+copy runargv.obj objects
+del runargv.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro msdos\arlib.c
+copy arlib.obj objects
+del arlib.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro msdos\dchdir.c
+copy dchdir.obj objects
+del dchdir.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro msdos\switchar.c
+copy switchar.obj objects
+del switchar.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro msdos\rmprq.c
+copy rmprq.obj objects
+del rmprq.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro msdos\spawn.c
+copy spawn.obj objects
+del spawn.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro msdos\find.c
+copy find.obj objects
+del find.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro msdos\dirlib.c
+copy dirlib.obj objects
+del dirlib.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro msdos\dstrlwr.c
+copy dstrlwr.obj objects
+del dstrlwr.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro unix\dcache.c
+copy dcache.obj objects
+del dcache.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro msdos\borland\tempnam.c
+copy tempnam.obj objects
+del tempnam.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc45 -w-pro msdos\borland\utime.c
+copy utime.obj objects
+del utime.obj
+tlink @msdos\borland\bcc45\objswp.rsp,dmake.exe,NUL.MAP,@msdos\borland\bcc45\libswp.rsp
+copy msdos\borland\bcc45\template.mk startup\config.mk
diff --git a/dmake/msdos/borland/bcc45/obj.rsp b/dmake/msdos/borland/bcc45/obj.rsp
new file mode 100644
index 000000000000..e1d4b1e23186
--- /dev/null
+++ b/dmake/msdos/borland/bcc45/obj.rsp
@@ -0,0 +1,34 @@
+e:\cc\borland\bcc45\lib\c0x32.obj+
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dirbrk.obj+
+objects\runargv.obj+
+objects\arlib.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\rmprq.obj+
+objects\find.obj+
+objects\tee.obj+
+objects\dirlib.obj+
+objects\dcache.obj+
+objects\tempnam.obj+
+objects\utime.obj
diff --git a/dmake/msdos/borland/bcc45/objswp.rsp b/dmake/msdos/borland/bcc45/objswp.rsp
new file mode 100644
index 000000000000..712d47f47504
--- /dev/null
+++ b/dmake/msdos/borland/bcc45/objswp.rsp
@@ -0,0 +1,36 @@
+e:\cc\borland\bcc40\lib\c0l.obj+
+objects\exec.obj+
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dirbrk.obj+
+objects\runargv.obj+
+objects\arlib.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\rmprq.obj+
+objects\spawn.obj+
+objects\find.obj+
+objects\dirlib.obj+
+objects\dstrlwr.obj+
+objects\dcache.obj+
+objects\tempnam.obj+
+objects\utime.obj
diff --git a/dmake/msdos/borland/bcc45/public.h b/dmake/msdos/borland/bcc45/public.h
new file mode 100644
index 000000000000..a091150efedc
--- /dev/null
+++ b/dmake/msdos/borland/bcc45/public.h
@@ -0,0 +1,169 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:28 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+int If_root_path ANSI((char *));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+void Clean_up_processes ANSI(());
+int Wait_for_child ANSI((int, int));
+time_t seek_arch ANSI((char*, char*));
+int touch_arch ANSI((char*, char*));
+int dchdir ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int spawnvpe ANSI((int, char *, char **, char **));
+void Hook_std_writes ANSI((char *));
+void dstrlwr ANSI((char *, char *));
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/msdos/borland/bcc45/template.mk b/dmake/msdos/borland/bcc45/template.mk
new file mode 100644
index 000000000000..83b5e009033d
--- /dev/null
+++ b/dmake/msdos/borland/bcc45/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= msdos
+ OSRELEASE *:= borland
+ OSENVIRONMENT *:= bcc45
diff --git a/dmake/msdos/borland/bcc50/config.h b/dmake/msdos/borland/bcc50/config.h
new file mode 100644
index 000000000000..994a10eab1ba
--- /dev/null
+++ b/dmake/msdos/borland/bcc50/config.h
@@ -0,0 +1,51 @@
+/* RCS $Id: config.h,v 1.1.1.1 2000-09-22 15:33:28 hr Exp $
+--
+-- SYNOPSIS
+-- Configurarion include file.
+--
+-- DESCRIPTION
+-- There is one of these for each specific machine configuration.
+-- It can be used to further tweek the machine specific sources
+-- so that they compile.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* define this for configurations that don't have the coreleft function
+ * so that the code compiles. To my knowledge coreleft exists only on
+ * Turbo C, but it is needed here since the function is used in many debug
+ * macros. */
+/*#define coreleft() 0L*/
+extern unsigned int coreleft();
+
+#define SIGQUIT SIGTERM /* turbo C doesn't understand SIGQUIT */
+
+/* Turbo-C understands const declarations. */
+#define CONST const
+
+#ifndef MSDOS
+# define MSDOS 1
+#endif
+
+/* a small problem with pointer to voids on some unix machines needs this */
+#define PVOID void *
+
+/* Borland redefined the environment variable, sigh */
+#define environ _environ
+
+/* Have to pull this in for the standard lib defines */
+#include <io.h>
diff --git a/dmake/msdos/borland/bcc50/config.mk b/dmake/msdos/borland/bcc50/config.mk
new file mode 100644
index 000000000000..550b86950705
--- /dev/null
+++ b/dmake/msdos/borland/bcc50/config.mk
@@ -0,0 +1,7 @@
+# Definition of macros for library, and C startup code.
+osedir = $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)
+
+LDLIBS = e:/cc/borland/bcc40/lib/c$(MODEL)
+CSTARTUP = e:/cc/borland/bcc40/lib/c0$(MODEL).obj
+
+CFLAGS += -I$(osedir) -w-pro
diff --git a/dmake/msdos/borland/bcc50/lib.rsp b/dmake/msdos/borland/bcc50/lib.rsp
new file mode 100644
index 000000000000..fd89d29f284c
--- /dev/null
+++ b/dmake/msdos/borland/bcc50/lib.rsp
@@ -0,0 +1,2 @@
+e:\cc\borland\bcc50\lib\cw32+
+e:\cc\borland\bcc50\lib\import32
diff --git a/dmake/msdos/borland/bcc50/libswp.rsp b/dmake/msdos/borland/bcc50/libswp.rsp
new file mode 100644
index 000000000000..1557935cd40c
--- /dev/null
+++ b/dmake/msdos/borland/bcc50/libswp.rsp
@@ -0,0 +1 @@
+e:\cc\borland\bcc40\lib\cl
diff --git a/dmake/msdos/borland/bcc50/mkswp.bat b/dmake/msdos/borland/bcc50/mkswp.bat
new file mode 100755
index 000000000000..14de52506f56
--- /dev/null
+++ b/dmake/msdos/borland/bcc50/mkswp.bat
@@ -0,0 +1,107 @@
+md objects
+tasm -t -mx -dmlarge msdos\exec.asm,,,;
+mv exec.obj objects
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro infer.c
+copy infer.obj objects
+del infer.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro make.c
+copy make.obj objects
+del make.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro stat.c
+copy stat.obj objects
+del stat.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro expand.c
+copy expand.obj objects
+del expand.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro dmstring.c
+copy dmstring.obj objects
+del dmstring.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro hash.c
+copy hash.obj objects
+del hash.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro dag.c
+copy dag.obj objects
+del dag.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro dmake.c
+copy dmake.obj objects
+del dmake.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro path.c
+copy path.obj objects
+del path.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro imacs.c
+copy imacs.obj objects
+del imacs.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro sysintf.c
+copy sysintf.obj objects
+del sysintf.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro parse.c
+copy parse.obj objects
+del parse.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro getinp.c
+copy getinp.obj objects
+del getinp.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro quit.c
+copy quit.obj objects
+del quit.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro state.c
+copy state.obj objects
+del state.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro dmdump.c
+copy dmdump.obj objects
+del dmdump.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro macparse.c
+copy macparse.obj objects
+del macparse.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro rulparse.c
+copy rulparse.obj objects
+del rulparse.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro percent.c
+copy percent.obj objects
+del percent.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro function.c
+copy function.obj objects
+del function.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro msdos\ruletab.c
+copy ruletab.obj objects
+del ruletab.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro msdos\dirbrk.c
+copy dirbrk.obj objects
+del dirbrk.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro msdos\runargv.c
+copy runargv.obj objects
+del runargv.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro msdos\arlib.c
+copy arlib.obj objects
+del arlib.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro msdos\dchdir.c
+copy dchdir.obj objects
+del dchdir.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro msdos\switchar.c
+copy switchar.obj objects
+del switchar.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro msdos\rmprq.c
+copy rmprq.obj objects
+del rmprq.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro msdos\spawn.c
+copy spawn.obj objects
+del spawn.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro msdos\find.c
+copy find.obj objects
+del find.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro msdos\dirlib.c
+copy dirlib.obj objects
+del dirlib.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro msdos\dstrlwr.c
+copy dstrlwr.obj objects
+del dstrlwr.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro unix\dcache.c
+copy dcache.obj objects
+del dcache.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro msdos\borland\tempnam.c
+copy tempnam.obj objects
+del tempnam.obj
+bcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\bcc50 -w-pro msdos\borland\utime.c
+copy utime.obj objects
+del utime.obj
+tlink @msdos\borland\bcc50\objswp.rsp,dmake.exe,NUL.MAP,@msdos\borland\bcc50\libswp.rsp
+copy msdos\borland\bcc50\template.mk startup\config.mk
diff --git a/dmake/msdos/borland/bcc50/obj.rsp b/dmake/msdos/borland/bcc50/obj.rsp
new file mode 100644
index 000000000000..08ea653f70f4
--- /dev/null
+++ b/dmake/msdos/borland/bcc50/obj.rsp
@@ -0,0 +1,34 @@
+e:\cc\borland\bcc50\lib\c0x32.obj+
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dirbrk.obj+
+objects\runargv.obj+
+objects\arlib.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\rmprq.obj+
+objects\find.obj+
+objects\tee.obj+
+objects\dirlib.obj+
+objects\dcache.obj+
+objects\tempnam.obj+
+objects\utime.obj
diff --git a/dmake/msdos/borland/bcc50/objswp.rsp b/dmake/msdos/borland/bcc50/objswp.rsp
new file mode 100644
index 000000000000..712d47f47504
--- /dev/null
+++ b/dmake/msdos/borland/bcc50/objswp.rsp
@@ -0,0 +1,36 @@
+e:\cc\borland\bcc40\lib\c0l.obj+
+objects\exec.obj+
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dirbrk.obj+
+objects\runargv.obj+
+objects\arlib.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\rmprq.obj+
+objects\spawn.obj+
+objects\find.obj+
+objects\dirlib.obj+
+objects\dstrlwr.obj+
+objects\dcache.obj+
+objects\tempnam.obj+
+objects\utime.obj
diff --git a/dmake/msdos/borland/bcc50/public.h b/dmake/msdos/borland/bcc50/public.h
new file mode 100644
index 000000000000..3130d161c24e
--- /dev/null
+++ b/dmake/msdos/borland/bcc50/public.h
@@ -0,0 +1,169 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:29 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+int If_root_path ANSI((char *));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+void Clean_up_processes ANSI(());
+int Wait_for_child ANSI((int, int));
+time_t seek_arch ANSI((char*, char*));
+int touch_arch ANSI((char*, char*));
+int dchdir ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int spawnvpe ANSI((int, char *, char **, char **));
+void Hook_std_writes ANSI((char *));
+void dstrlwr ANSI((char *, char *));
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/msdos/borland/bcc50/template.mk b/dmake/msdos/borland/bcc50/template.mk
new file mode 100644
index 000000000000..51b575677985
--- /dev/null
+++ b/dmake/msdos/borland/bcc50/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= msdos
+ OSRELEASE *:= borland
+ OSENVIRONMENT *:= bcc50
diff --git a/dmake/msdos/borland/config.mk b/dmake/msdos/borland/config.mk
new file mode 100644
index 000000000000..42361968671d
--- /dev/null
+++ b/dmake/msdos/borland/config.mk
@@ -0,0 +1,46 @@
+# This is the Turbo C++ 2.0 DOS configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+# The following sources are required for TURBO C++ 2.0
+OSR_SRC = tempnam.c utime.c
+.SETDIR=$(osrdir) : $(OSR_SRC)
+
+SRC += $(OSR_SRC)
+.SOURCE.h : $(osrdir)
+
+# Local configuration modifications for CFLAGS. Make sure your turboc.cfg
+# file contains a -D__STDC__=1 and -DM_I86=1, if not then uncomment the line
+# below!
+#CFLAGS += -DM_I86=1 -D__STDC__=1
+
+# You can get a smaller executable still, buy adding a -1 to the list of
+# flags below, but then you can't run this on an 8086/88 cpu.
+#CFLAGS += -1
+CFLAGS += -I$(osrdir) -d -O -N- -w-nod $(C_$(MODEL))
+ASFLAGS += -t -mx $(S_$(MODEL))
+
+# Debugging information for Turbo-C
+DB_CFLAGS += -v
+DB_LDFLAGS += /v
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
+
+C_s =
+C_m = -mm
+C_c = -mc
+C_l = -ml
+
+S_s = -dmsmall
+S_m = -dmmedium
+S_c = -dmcompact
+S_l = -dmlarge
diff --git a/dmake/msdos/borland/tcc20/config.h b/dmake/msdos/borland/tcc20/config.h
new file mode 100644
index 000000000000..fdf421e87910
--- /dev/null
+++ b/dmake/msdos/borland/tcc20/config.h
@@ -0,0 +1,48 @@
+/* RCS $Id: config.h,v 1.1.1.1 2000-09-22 15:33:29 hr Exp $
+--
+-- SYNOPSIS
+-- Configurarion include file.
+--
+-- DESCRIPTION
+-- There is one of these for each specific machine configuration.
+-- It can be used to further tweek the machine specific sources
+-- so that they compile.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* define this for configurations that don't have the coreleft function
+ * so that the code compiles. To my knowledge coreleft exists only on
+ * Turbo C, but it is needed here since the function is used in many debug
+ * macros. */
+/*#define coreleft() 0L*/
+extern unsigned int coreleft();
+
+#define SIGQUIT SIGTERM /* turbo C doesn't understand SIGQUIT */
+
+/* Turbo-C understands const declarations. */
+#define CONST const
+
+#ifndef MSDOS
+# define MSDOS 1
+#endif
+
+/* a small problem with pointer to voids on some unix machines needs this */
+#define PVOID void *
+
+/* Have to pull this in for the standard lib defines */
+#include <io.h>
diff --git a/dmake/msdos/borland/tcc20/config.mk b/dmake/msdos/borland/tcc20/config.mk
new file mode 100644
index 000000000000..e7c53757d2b6
--- /dev/null
+++ b/dmake/msdos/borland/tcc20/config.mk
@@ -0,0 +1,10 @@
+# Definition of macros for library, and C startup code.
+osedir = $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)
+
+LDLIBS = e:/cc/borland/tcc20/lib/c$(MODEL)
+CSTARTUP = e:/cc/borland/tcc20/lib/c0$(MODEL).obj
+
+CFLAGS += -I$(osedir) -f-
+
+# Case of identifiers is significant
+NDB_LDFLAGS += -c
diff --git a/dmake/msdos/borland/tcc20/libswp.rsp b/dmake/msdos/borland/tcc20/libswp.rsp
new file mode 100644
index 000000000000..68d583f00580
--- /dev/null
+++ b/dmake/msdos/borland/tcc20/libswp.rsp
@@ -0,0 +1 @@
+e:\cc\borland\tcc20\lib\cl
diff --git a/dmake/msdos/borland/tcc20/mkswp.bat b/dmake/msdos/borland/tcc20/mkswp.bat
new file mode 100755
index 000000000000..52f6748e8ef3
--- /dev/null
+++ b/dmake/msdos/borland/tcc20/mkswp.bat
@@ -0,0 +1,107 @@
+md objects
+tasm -t -mx -dmlarge msdos\exec.asm,,,;
+mv exec.obj objects
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- infer.c
+copy infer.obj objects
+del infer.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- make.c
+copy make.obj objects
+del make.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- stat.c
+copy stat.obj objects
+del stat.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- expand.c
+copy expand.obj objects
+del expand.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- dmstring.c
+copy dmstring.obj objects
+del dmstring.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- hash.c
+copy hash.obj objects
+del hash.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- dag.c
+copy dag.obj objects
+del dag.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- dmake.c
+copy dmake.obj objects
+del dmake.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- path.c
+copy path.obj objects
+del path.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- imacs.c
+copy imacs.obj objects
+del imacs.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- sysintf.c
+copy sysintf.obj objects
+del sysintf.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- parse.c
+copy parse.obj objects
+del parse.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- getinp.c
+copy getinp.obj objects
+del getinp.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- quit.c
+copy quit.obj objects
+del quit.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- state.c
+copy state.obj objects
+del state.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- dmdump.c
+copy dmdump.obj objects
+del dmdump.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- macparse.c
+copy macparse.obj objects
+del macparse.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- rulparse.c
+copy rulparse.obj objects
+del rulparse.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- percent.c
+copy percent.obj objects
+del percent.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- function.c
+copy function.obj objects
+del function.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- msdos\ruletab.c
+copy ruletab.obj objects
+del ruletab.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- msdos\dirbrk.c
+copy dirbrk.obj objects
+del dirbrk.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- msdos\runargv.c
+copy runargv.obj objects
+del runargv.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- msdos\arlib.c
+copy arlib.obj objects
+del arlib.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- msdos\dchdir.c
+copy dchdir.obj objects
+del dchdir.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- msdos\switchar.c
+copy switchar.obj objects
+del switchar.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- msdos\rmprq.c
+copy rmprq.obj objects
+del rmprq.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- msdos\spawn.c
+copy spawn.obj objects
+del spawn.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- msdos\find.c
+copy find.obj objects
+del find.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- msdos\dirlib.c
+copy dirlib.obj objects
+del dirlib.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- msdos\dstrlwr.c
+copy dstrlwr.obj objects
+del dstrlwr.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- unix\dcache.c
+copy dcache.obj objects
+del dcache.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- msdos\borland\tempnam.c
+copy tempnam.obj objects
+del tempnam.obj
+tcc -c -I. -Imsdos -Imsdos\borland -d -O -N- -w-nod -ml -Imsdos\borland\tcc20 -f- msdos\borland\utime.c
+copy utime.obj objects
+del utime.obj
+tlink /c @msdos\borland\tcc20\objswp.rsp,dmake.exe,NUL.MAP,@msdos\borland\tcc20\libswp.rsp
+copy msdos\borland\tcc20\template.mk startup\config.mk
diff --git a/dmake/msdos/borland/tcc20/objswp.rsp b/dmake/msdos/borland/tcc20/objswp.rsp
new file mode 100644
index 000000000000..c177fda3efbd
--- /dev/null
+++ b/dmake/msdos/borland/tcc20/objswp.rsp
@@ -0,0 +1,36 @@
+e:\cc\borland\tcc20\lib\c0l.obj+
+objects\exec.obj+
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dirbrk.obj+
+objects\runargv.obj+
+objects\arlib.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\rmprq.obj+
+objects\spawn.obj+
+objects\find.obj+
+objects\dirlib.obj+
+objects\dstrlwr.obj+
+objects\dcache.obj+
+objects\tempnam.obj+
+objects\utime.obj
diff --git a/dmake/msdos/borland/tcc20/public.h b/dmake/msdos/borland/tcc20/public.h
new file mode 100644
index 000000000000..3130d161c24e
--- /dev/null
+++ b/dmake/msdos/borland/tcc20/public.h
@@ -0,0 +1,169 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:29 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+int If_root_path ANSI((char *));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+void Clean_up_processes ANSI(());
+int Wait_for_child ANSI((int, int));
+time_t seek_arch ANSI((char*, char*));
+int touch_arch ANSI((char*, char*));
+int dchdir ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int spawnvpe ANSI((int, char *, char **, char **));
+void Hook_std_writes ANSI((char *));
+void dstrlwr ANSI((char *, char *));
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/msdos/borland/tcc20/template.mk b/dmake/msdos/borland/tcc20/template.mk
new file mode 100644
index 000000000000..3cac6b22a240
--- /dev/null
+++ b/dmake/msdos/borland/tcc20/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= msdos
+ OSRELEASE *:= borland
+ OSENVIRONMENT *:= tcc20
diff --git a/dmake/msdos/borland/tempnam.c b/dmake/msdos/borland/tempnam.c
new file mode 100644
index 000000000000..c4d599de5971
--- /dev/null
+++ b/dmake/msdos/borland/tempnam.c
@@ -0,0 +1,109 @@
+/* RCS $Id: tempnam.c,v 1.1.1.1 2000-09-22 15:33:28 hr Exp $
+--
+-- SYNOPSIS
+-- tempnam
+--
+-- DESCRIPTION
+-- temp file name generation routines.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+/*LINTLIBRARY*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dos.h>
+
+#if defined(max)
+# undef max
+#endif
+#define max(A,B) (((A)<(B))?(B):(A))
+
+extern char *mktemp();
+extern int access();
+int d_access();
+
+/* Turbo C stdio.h doesn't define P_tmpdir, so let's do it here */
+/* Under DOS leave the default tmpdir pointing here! */
+#ifndef P_tmpdir
+static char *P_tmpdir = "";
+#endif
+
+char *
+tempnam(dir, prefix)
+char *dir; /* use this directory please (if non-NULL) */
+char *prefix; /* use this (if non-NULL) as filename prefix */
+{
+ static int count = 0;
+ register char *p, *q, *tmpdir;
+ int tl=0, dl=0, pl;
+ char buf[30];
+
+ pl = strlen(P_tmpdir);
+
+ if( (tmpdir = getenv("TMPDIR")) != NULL ) tl = strlen(tmpdir);
+ else if( (tmpdir = getenv("TMP")) != NULL ) tl = strlen(tmpdir);
+ if( dir != NULL ) dl = strlen(dir);
+
+ if( (p = malloc((unsigned)(max(max(dl,tl),pl)+13))) == NULL )
+ return(NULL);
+
+ *p = '\0';
+
+ if( (tl == 0) || (d_access( strcpy(p, tmpdir), 0) != 0) )
+ if( (dl == 0) || (d_access( strcpy(p, dir), 0) != 0) )
+ if( d_access( strcpy(p, P_tmpdir), 0) != 0 )
+ if( !prefix )
+ prefix = "tp";
+
+ if(prefix)
+ {
+ *(p+strlen(p)+2) = '\0';
+ (void)strncat(p, prefix, 2);
+ }
+
+ sprintf( buf, "%08x", _psp );
+ buf[6]='\0';
+ (void)strcat(p, buf );
+ sprintf( buf, "%04d", count++ );
+ q=p+strlen(p)-6;
+ *q++ = buf[0]; *q++ = buf[1];
+ *q++ = buf[2]; *q = buf[3];
+
+ if( (q = strrchr(p,'.')) != NULL ) *q = '\0';
+
+ return(p);
+}
+
+
+
+d_access( name, flag )
+char *name;
+int flag;
+{
+ extern char *DirSepStr;
+ char *p;
+ int r;
+
+ if( name == NULL || !*name ) return(1); /* NULL dir means current dir */
+ r = access( name, flag );
+ p = name+strlen(name)-1;
+
+ if(*p != '/' && *p != '\\') strcat( p, DirSepStr );
+
+ return( r );
+}
diff --git a/dmake/msdos/borland/utime.c b/dmake/msdos/borland/utime.c
new file mode 100644
index 000000000000..2b87022fe3f1
--- /dev/null
+++ b/dmake/msdos/borland/utime.c
@@ -0,0 +1,66 @@
+/* RCS $Id: utime.c,v 1.1.1.1 2000-09-22 15:33:28 hr Exp $
+--
+-- SYNOPSIS
+-- utime
+--
+-- DESCRIPTION
+-- chage the last modified time on a file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <io.h>
+#include <time.h>
+
+int
+utime(name, timep)/*
+====================
+ Broken for turbo C it only sets the file time to the current time by
+ touching a character in the file */
+char* name;
+time_t timep[2];
+{
+ struct stat buf;
+ int fil;
+ char data;
+
+ if (stat(name, &buf) != 0)
+ return (-1);
+ if (buf.st_size != 0) {
+ if ((fil = open(name, O_RDWR, S_IWRITE)) < 0)
+ return (-1);
+ if (read(fil, &data, 1) < 1) {
+ close(fil);
+ return (-1);
+ }
+ lseek(fil, 0L, 0);
+ if (write(fil, &data, 1) < 1) {
+ close(fil);
+ return (-1);
+ }
+ close(fil);
+ return (0);
+ } else if ((fil = creat(name, S_IWRITE)) < 0) {
+ return (-1);
+ } else {
+ close(fil);
+ return (0);
+ }
+}
diff --git a/dmake/msdos/config.mk b/dmake/msdos/config.mk
new file mode 100644
index 000000000000..77a32bf419de
--- /dev/null
+++ b/dmake/msdos/config.mk
@@ -0,0 +1,71 @@
+# This is an OS specific configuration file
+# It assumes that OBJDIR, TARGET and DEBUG are previously defined.
+# It defines CFLAGS, LDARGS, CPPFLAGS, STARTUPFILE, LDOBJS
+# It augments SRC, OBJDIR, TARGET, CFLAGS, LDLIBS
+#
+
+# Memory model to compile for
+# set to s - small, m - medium, c - compact, l - large
+# Need large model now, dmake has grown up :-)
+MODEL = l
+
+STARTUPFILE = $(OS)/startup.mk
+
+CPPFLAGS = $(CFLAGS)
+LDOBJS = $(CSTARTUP) $(OBJDIR)/{$(<:f)}
+LDARGS = $(LDHEAD) $(LDFLAGS:s/ //) @$(LDTMPOBJ),$(TARGET),NUL.MAP$(LDTAIL)
+LDTAIL = $(_libs)
+_libs = $(!null,$(LDLIBS) ,@$(LDTMPLIB))
+LDTMPOBJ = $(mktmp,,$(DIVFILE) $(LDOBJS:s,/,\\,:t"+\n")\n)
+LDTMPLIB = $(mktmp,,$(DIVFILE) $(LDLIBS:s,/,\\,:t"+\n")\n)
+
+# Debug flags
+DB_CFLAGS = -DDBUG
+DB_LDFLAGS =
+DB_LDLIBS =
+
+# NO Debug flags
+NDB_CFLAGS =
+NDB_LDFLAGS =
+NDB_LDLIBS =
+
+# Local configuration modifications for CFLAGS.
+CFLAGS += -I$(OS)
+
+# Common MSDOS source files.
+# Define SWAP to anything but 'y' for the swap code to be excluded on making.
+# Swapping for DOS versions is enabled by default.
+# Note: swapping is handled specially for ZTC in msdos/zortech/config.mk.
+SWAP *= y
+
+.IF $(OSRELEASE) != zortech
+ .IF $(SWAP) == y
+ SWP_SRC += spawn.c
+ ASRC += exec.asm
+ .ELSE
+ SWP_SRC += tee.c
+ .END
+.ELSE
+ SWP_SRC += tee.c
+.END
+
+OS_SRC += ruletab.c dirbrk.c runargv.c arlib.c dchdir.c switchar.c rmprq.c\
+ $(SWP_SRC) find.c dirlib.c dstrlwr.c
+UNIXSRC := dcache.c
+SRC += $(OS_SRC) $(UNIXSRC)
+.SETDIR=$(OS) : $(ASRC) $(OS_SRC)
+.SETDIR=unix : $(UNIXSRC)
+
+# Provide our own %$O : %$S rule.
+%$O : %$S
+ +$(AS) $(ASFLAGS) $(<:s,\,${__.DIVSEP-sh-${USESHELL}},:s,/,${__.DIVSEP-sh-${USESHELL}},),,,;
+ mv $(@:f) $(OBJDIR)
+
+# Set source dirs so that we can find files named in this
+# config file.
+.SOURCE.h : $(OS)
+
+# See if we modify anything in the lower levels.
+.IF $(OSRELEASE) != $(NULL)
+ .INCLUDE : $(OS)$(DIRSEPSTR)$(OSRELEASE)$(DIRSEPSTR)config.mk
+.END
diff --git a/dmake/msdos/dchdir.c b/dmake/msdos/dchdir.c
new file mode 100644
index 000000000000..19006825b7f6
--- /dev/null
+++ b/dmake/msdos/dchdir.c
@@ -0,0 +1,47 @@
+/* RCS $Id: dchdir.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Change directory.
+--
+-- DESCRIPTION
+-- Under DOS change the current drive as well as the current directory.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <dos.h>
+#include "extern.h"
+
+PUBLIC int
+dchdir(path)
+char *path;
+{
+ int res;
+
+ res = chdir(path);
+
+ if (res != -1 && path[1] == ':') {
+ union REGS reg;
+
+ /* we must change the logged drive, since the chdir worked. */
+ reg.h.ah = 0x0E;
+ reg.h.dl = (*path & ~0x20) - 'A' + 1;
+ intdos(&reg, &reg);
+ }
+
+ return (res);
+}
diff --git a/dmake/msdos/dirbrk.c b/dmake/msdos/dirbrk.c
new file mode 100644
index 000000000000..d8aab76b6f96
--- /dev/null
+++ b/dmake/msdos/dirbrk.c
@@ -0,0 +1,42 @@
+/* RCS $Id: dirbrk.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Define the directory separator string.
+--
+-- DESCRIPTION
+-- Define this string for any character that may appear in a path name
+-- and can be used as a directory separator.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+/* dos uses /, \, and : */
+char* DirBrkStr = "/\\:";
+
+/*
+** Return TRUE if the name is the full specification of a path name to a file
+** starting at the root of the file system, otherwise return FALSE
+*/
+PUBLIC int
+If_root_path(name)
+char *name;
+{
+ return( (strchr(DirBrkStr, *name) != NIL(char)) ||
+ (isalpha(*name) && name[1] == ':') );
+}
diff --git a/dmake/msdos/dirent.h b/dmake/msdos/dirent.h
new file mode 100644
index 000000000000..24ad5681da59
--- /dev/null
+++ b/dmake/msdos/dirent.h
@@ -0,0 +1,32 @@
+/* DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89 */
+
+#ifndef _DIRLIB_h_
+#define _DIRLIB_h_
+
+#include <stdio.h>
+#include "stdmacs.h"
+#include "dosdta.h"
+
+#define MAXNAMLEN 15
+
+struct dirent {
+ long d_ino;
+ unsigned short d_reclen;
+ unsigned short d_namlen;
+ char d_name[MAXNAMLEN+1];
+};
+
+typedef struct {
+ DTA dd_dta; /* disk transfer area for this dir. */
+ short dd_stat; /* status return from last lookup */
+ char dd_name[1]; /* full name of file -- struct is extended */
+} DIR;
+
+extern DIR *opendir ANSI((char *));
+extern struct dirent *readdir ANSI((DIR *));
+extern long telldir ANSI((DIR *));
+extern void seekdir ANSI((DIR *, long));
+extern void closedir ANSI((DIR *));
+
+#define rewinddir(dirp) seekdir(dirp,0L)
+#endif
diff --git a/dmake/msdos/dirlib.c b/dmake/msdos/dirlib.c
new file mode 100644
index 000000000000..eaef928772af
--- /dev/null
+++ b/dmake/msdos/dirlib.c
@@ -0,0 +1,285 @@
+/*
+ DIRLIB for MS-DOS
+ -----------------
+
+Enclosed is an implementation of the `dirlib' package for MS-DOS.
+The implementation is targeted for MS-C, although any reasonably
+competent C compiler should manage. The package consists of:
+
+ dir.h the header file
+ dir.c the functions
+ testdir.c a q&d test program
+
+The package tries to view directory naming in a Un*x light; in particular,
+directories such as '/.' and '/..' (as well as `.' and `..' if your
+current directory is root) are understood. Indefinite paths like
+`/../.././../..' will correctly refer to the root (of the particular disk).
+Names such as `a:////./../' are okay too.
+
+I've tried to be as sensible about DTA's as possible, since you never
+know who will be using one; they are set before use, and reset afterwards.
+
+There is some cruft in the package, namely the way `seekdir' and
+`telldir' are done. The code was derived from a little experimentation,
+and may not work after a certain point (although I believe the 2.x version
+to be solid). Caveat utilitor.
+
+Documentation for the package is available in the public domain; the
+package's functionality was derived from this documentation.
+
+Bug reports and comments are welcome. Enjoy!
+
+ - Matt
+
+-------
+UUCP: {ucbvax,ihnp4,randvax,trwrb!trwspp,ism780}!ucla-cs!matt
+ARPA: matt@LOCUS.UCLA.EDU
+Ph: (213) 825-2756
+
+--------
+Modified for use in dmake by Dennis Vadura. Mostly just clean up and an
+effort to make correctly typed objects are passed to functions in find.c.
+Also deleted all dos version 2.0 specific code. It is not required any
+more.
+*/
+
+/*
+ * revision history:
+ *
+ * VER MM/DD/YY COMMENTS
+ * ---- -------- --------
+ * 0.99 02/24/86 Beta release to INTERNET
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <dos.h>
+
+#include "dirent.h"
+
+extern int find_err;
+
+
+static char *
+getdcwd(drive)
+int drive;
+{
+ union REGS r;
+ struct SREGS s;
+ static char xcwd[64];
+ char far *cwd = xcwd;
+
+ r.h.ah = 0x47;
+ r.h.dl = drive;
+ r.x.si = FP_OFF(cwd);
+ s.ds = FP_SEG(cwd);
+ intdosx(&r, &r, &s);
+ find_err = r.x.ax;
+ if (r.x.cflag)
+ return (char *) 0;
+ return xcwd;
+}
+
+
+
+/*
+ * opendir
+ */
+
+#define SUFFIX "\\*.*"
+#define SLASH "\\"
+#define streq(a,b) (strcmp(a,b)==0)
+
+DIR *
+opendir(name)
+char *name;
+{
+ register DIR *nd;
+ char *cwd;
+ char drive[3];
+ int atroot = 0;
+ int rooted = 0;
+
+ /*
+ * hack off drive designator if present
+ */
+
+ if (name[1] == ':') {
+ cwd = getdcwd(toupper(name[0]) - 'A' + 1);
+ drive[0] = name[0]; drive[1] = ':'; drive[2] = '\0';
+ name += 2;
+ }
+ else {
+ cwd = getdcwd(0);
+ drive[0] = '\0';
+ }
+
+ /* is the name 'rooted'? */
+ if ((*name == '/') || (*name == '\\')) ++rooted;
+
+ /* see if we are at the root directory for this device */
+ if (!*cwd) ++atroot;
+
+ /*
+ * MSDOS '/' doesn't have a '.' or '..'
+ * also, double '/' sequences don't make sense.
+ * many ported programs expect them to work, so we fix it up...
+ */
+
+ /* chop off leading . and .. if at root */
+ if (atroot && (*name == '.')) {
+ switch (*++name) {
+ case '\0':
+ case '/':
+ case '\\':
+ break;
+
+ case '.':
+ switch (*++name) {
+ case '\0':
+ case '/':
+ case '\\':
+ break;
+ default:
+ --name;
+ --name;
+ }
+ break;
+
+ default:
+ --name;
+ }
+ }
+
+ /* chop off leading /'s, /.'s and /..'s to make naming sensible */
+ while (*name && ((*name == '/') || (*name == '\\'))) {
+ if (*++name == '.') {
+ switch (*++name) {
+ case '\0':
+ case '/':
+ case '\\':
+ break;
+
+ case '.':
+ switch (*++name) {
+ case '\0':
+ case '/':
+ case '\\':
+ break;
+
+ default:
+ --name;
+ --name;
+ }
+ break;
+
+ default:
+ --name;
+ }
+ }
+ }
+
+
+ /*
+ * name should now look like: path/path/path
+ * we must now construct name based on whether or not it
+ * was 'rooted' (started with a /)
+ */
+
+ if (rooted) cwd = "";
+
+ /* construct DIR */
+ if (!(nd = (DIR *)malloc(
+ sizeof(DIR)+strlen(drive)+strlen(cwd)+strlen(SLASH)+
+ strlen(name)+strlen(SUFFIX))))
+ return (DIR *) 0;
+
+ /* create long name */
+ strcpy(nd->dd_name, drive);
+ if (*cwd) {
+ strcat(nd->dd_name, SLASH);
+ strcat(nd->dd_name, cwd);
+ }
+ if (*name) {
+ strcat(nd->dd_name, SLASH);
+ strcat(nd->dd_name, name);
+ }
+ strcat(nd->dd_name, SUFFIX);
+
+ /* search */
+ if (!findfirst(&nd->dd_name[0], &nd->dd_dta)) {
+ free((char *)nd);
+ errno = ENOENT;
+ return (DIR *) 0;
+ }
+ nd->dd_stat = 0;
+ return nd;
+}
+
+
+struct dirent *
+readdir(dirp)
+DIR *dirp;
+{
+ static struct dirent dir;
+
+ if (dirp->dd_stat)
+ return (struct dirent *) 0;
+
+ /* format structure */
+ dir.d_ino = 0; /* not valid for DOS */
+ dir.d_reclen = 0;
+ strcpy(dir.d_name, dirp->dd_dta.name);
+ dir.d_namlen = strlen(dir.d_name);
+ strlwr(dir.d_name); /* DOSism */
+
+ /* read ahead */
+ if (findnext(&dirp->dd_dta) != NULL)
+ dirp->dd_stat = 0;
+ else
+ dirp->dd_stat = find_err;
+
+ return &dir;
+}
+
+
+void
+closedir(dirp)
+DIR *dirp;
+{
+ free((char *)dirp);
+}
+
+
+void
+seekdir(dirp, pos)
+DIR *dirp;
+long pos;
+{
+ /*
+ * check against DOS limits
+ */
+
+ if ((pos < 0) || (pos > 4095)) {
+ dirp->dd_stat = 1;
+ return;
+ }
+
+ *(short *)&dirp->dd_dta.fcb[13] = pos + 1;
+
+ /* read ahead */
+ if (findnext(&dirp->dd_dta))
+ dirp->dd_stat = 0;
+ else
+ dirp->dd_stat = find_err;
+}
+
+
+long
+telldir(dirp)
+DIR *dirp;
+{
+ return (long) (*(short *)&dirp->dd_dta.fcb[13] - 2);
+}
diff --git a/dmake/msdos/dosdta.h b/dmake/msdos/dosdta.h
new file mode 100644
index 000000000000..c9642715d937
--- /dev/null
+++ b/dmake/msdos/dosdta.h
@@ -0,0 +1,16 @@
+#ifndef _DOSDTA_
+#define _DOSDTA_
+
+#include "stdmacs.h"
+typedef struct {
+ char fcb[21];
+ char attr;
+ short time;
+ short date;
+ long size;
+ char name[13];
+} DTA;
+
+extern DTA *findfirst ANSI((char *, DTA *));
+extern DTA *findnext ANSI((DTA *));
+#endif
diff --git a/dmake/msdos/dstrlwr.c b/dmake/msdos/dstrlwr.c
new file mode 100644
index 000000000000..64027eb36481
--- /dev/null
+++ b/dmake/msdos/dstrlwr.c
@@ -0,0 +1,49 @@
+/* RCS $Id: dstrlwr.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Rotines for computing case mappings in Win95/NT environments.
+--
+-- DESCRIPTION
+-- This code is an attempt at providing sane case mappings to help
+-- deal with the disparity in file name case between 8.3 and long
+-- file names under Win95/NT.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+#include "extern.h"
+
+PUBLIC void
+dstrlwr(entry, target)
+char *entry;
+char *target;
+{
+ char *p;
+
+ if (STOBOOL(DcacheRespCase))
+ return;
+
+ /* Look for the target being lower case, if so then lower the case
+ * of the directory entry. Note that we only check the first
+ * character of the target. This is a bit of a kludge but there is
+ * really no other way to know, particularly since this test will be
+ * performed for each member of the directory but against the same
+ * target. */
+ if (islower(*target))
+ strlwr(entry);
+
+ return;
+}
diff --git a/dmake/msdos/exec.asm b/dmake/msdos/exec.asm
new file mode 100644
index 000000000000..db745aece6b2
--- /dev/null
+++ b/dmake/msdos/exec.asm
@@ -0,0 +1,1234 @@
+;
+; DESCRIPTION
+; This code is a model independent version of DOS exec that will swap
+; the calling process out to secondary storage prior to running the
+; child. The prototype for calling the exec function is below.
+;
+; exec( int swap, char far *program, char far *cmdtail,
+; int environment_seg, char far *tmpfilename );
+;
+;
+; To assemble this file issue the command:
+;
+; tasm /mx /t /dmmodel exec.asm
+;
+; where 'model' is one of {small, compact, medium, large}, you may
+; also use MASM 5.1 to assemble this file, in this case simply replace
+; 'tasm' with 'masm' in the above command line.
+;
+; AUTHOR
+; Dennis Vadura, dvadura@watdragon.uwaterloo.ca
+; CS DEPT, University of Waterloo, Waterloo, Ont., Canada
+;
+; COPYRIGHT
+; Copyright (c) 1990 by Dennis Vadura. All rights reserved.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; (version 1), as published by the Free Software Foundation, and
+; found in the file 'LICENSE' included with this distribution.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warrant of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, write to the Free Software
+; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+;
+ifdef have286
+ .286 ; define have286 with -D for 80286 processor or better
+ mpusha Macro
+ pusha
+ Endm
+
+ mpopa Macro
+ popa
+ Endm
+
+else ; 8088/8086 compatible
+ mpusha Macro
+ push ax
+ push cx
+ push dx
+ push bx
+ push sp
+ push bp
+ push si
+ push di
+ Endm
+
+ mpopa Macro
+ pop di
+ pop si
+ pop bp
+ add sp,2
+ pop bx
+ pop dx
+ pop cx
+ pop ax
+ Endm
+endif
+
+ifdef msmall
+ .model small
+argbase equ 4
+endif
+ifdef mcompact
+ .model compact
+argbase equ 4
+endif
+ifdef mmedium
+ .model medium
+argbase equ 6
+endif
+ifdef mlarge
+ .model large
+argbase equ 6
+endif
+a_swap equ <bp+argbase+0>
+a_prog equ <bp+argbase+2>
+a_tail equ <bp+argbase+6>
+a_env equ <bp+argbase+10>
+a_tmp equ <bp+argbase+12>
+
+a_handle equ <bp+argbase>
+
+
+; Define all useful equ's
+swap_xms equ 0 ; we swapped it out to xms
+swap_ems equ 2 ; we swapped it out to ems
+swap_file equ 4 ; we swapped it out to a file
+seg_no_alloc equ 0 ; this is part of a segment
+seg_alloc equ 1 ; this is a full segment header
+seg_data equ 2 ; this is data for part of a segment
+
+
+; Define any global/external variables that we will be accessing from here.
+ .data
+ extrn _errno:word ; Set to dos ret code from exec
+ public _Interrupted ; Set to 1 if interrupted 0
+_Interrupted dw 0 ; otherwise
+
+ .code
+ assume cs:@code, ds:@code, ss:@code, es:@code
+
+ even
+execstack dw 64 dup (?) ; put the temporary exec stack right
+exec_sp label word ; at the start.
+
+old_ss dw ? ; save stack seg across exec
+old_sp dw ? ; save stack ptr across exec
+progsize dw ? ; original size of the program
+rootsize dw ? ; size of base root kept during swap
+resend dw ? ; paragraph where resident code ends
+envseg dw ? ; paragraph of environment segment
+psp dw ? ; our own psp
+swap dw ? ; swapping selection flag
+eretcode dw ? ; return code from exec
+interrupted dw ? ; interrupted flag for exec
+arenahead dw ? ; start of memory block list
+alstr dw ? ; allocation strategy save spot
+in_exec dw 0 ; flag, 1 ==> in exec
+
+cmdpath db 65 dup(?) ; file to exec
+cmdtail db 129 dup(?) ; its command tail
+fcb db 37 dup(0) ; dummy fcb
+tmpseg db 7 dup(?) ; block header buffer
+
+tmpname db 65 dup(0) ; name of temporary file resource
+
+ even
+tmphandle dw ? ; handle for temporary file
+real_21h dd 0 ; will be DOS's 21h vector if doing -C
+
+std_fil_handle dw ? ; file handle for -C file
+std_fil_number db ? ; system file number for -C file
+our_stdout db ? ; sys file number our stdout handle
+
+error_rhdr db "exec: Failure reading header block", 0DH, 0AH, '$'
+error_rseg db "exec: Failure reading segment data", 0DH, 0AH, '$'
+error_resize db "exec: Failure on resize", 0DH, 0AH, '$'
+error_free db "exec: Failure to free a block", 0DH, 0AH, '$'
+error_string db "exec: Program swap failure", 0DH, 0AH, '$'
+error_alloc db "exec: Memory blocks don't match", 0DH, 0AH, '$'
+
+ even
+write_header label word
+ whdr_xms_ptr dw word ptr whdr_xms
+ whdr_ems_ptr dw word ptr whdr_ems
+ whdr_file_ptr dw word ptr whdr_file
+
+write_seg label word
+ wseg_xms_ptr dw word ptr wseg_xms
+ wseg_ems_ptr dw word ptr wseg_ems
+ wseg_file_ptr dw word ptr wseg_file
+
+read_header label word
+ rhdr_xms_ptr dw word ptr rhdr_xms
+ rhdr_ems_ptr dw word ptr rhdr_ems
+ rhdr_file_ptr dw word ptr rhdr_file
+
+read_seg label word
+ rseg_xms_ptr dw word ptr rseg_xms
+ rseg_ems_ptr dw word ptr rseg_ems
+ rseg_file_ptr dw word ptr rseg_file
+
+free_resource label word
+ free_xms_ptr dw word ptr free_xms_resource
+ free_ems_ptr dw word ptr free_ems_resource
+ free_file_ptr dw word ptr free_file_resource
+
+reset_resource label word
+ reset_xms_ptr dw word ptr reset_xms_resource
+ reset_ems_ptr dw word ptr reset_ems_resource
+ reset_file_ptr dw word ptr reset_file_resource
+
+old_ctl_brk label dword
+ old_ctl_brk_off dw ?
+ old_ctl_brk_seg dw ?
+
+old_crit_err label dword
+ old_crit_err_off dw ?
+ old_crit_err_seg dw ?
+
+exec_block label word
+ ex_envseg dw ? ; env seg, use parent's if 0
+ ex_cmdtail dd ? ; command tail for exec
+ ex_fcb1 dd far ptr fcb ; fcb's aren't used by dmake
+ ex_fcb2 dd far ptr fcb
+ ex_ss dw ? ; saved ss for exec
+ ex_sp dw ? ; saved sp for exec
+ ex_error dw 0 ; error code for dos exec
+
+
+; Special 21h (DOS call) handler to tee stdout/stderr writes to the -C file.
+; Ignore 21h calls that aren't writes to 1 or 2; i.e., pass them to DOS handler.
+; If write call was from this process, it's pretty simple to duplicate it
+; to the -C file. If it's from another process, we try to write to its
+; inherited handle. Worst case is where the handle wasn't inherited: someone
+; closed it. In that instance we have to switch to dmake's PSP to do the
+; duplicate write.
+
+; Subprocesses do not get their stdout/stderr teed to the -C file if
+; their stdout/stderr no longer points to the file/device that dmake's
+; stdout points to. This is tested by looking at the process's job
+; file table, which is a table that maps process handles to DOS system file
+; table numbers. (The far pointer to the JFT is at the PSP offset 34h.)
+; The JFT is also queried to see if the -C file was inherited.
+
+; O_BINARY, O_TEXT problems are ignored here. These are fudged by the
+; C library before it calls DOS; since we're working below that level
+; we don't have to worry about it.
+
+simulate_21h Macro
+ pushf ;; direct call to DOS
+ call cs:[real_21h]
+ Endm
+
+ assume cs:@code, ds:nothing, es:nothing, ss:nothing
+our_21h_handler proc far
+ pushf
+ cmp ah,40h ; is this a write?
+ jne call_dos ; --no
+ cmp bx,1 ; write on handle 1 (stdout?)
+ je duplicate_it
+ cmp bx,2 ; stderr?
+ je duplicate_it
+
+call_dos:
+ popf
+ jmp [real_21h] ; far jump to real handler, which will do the sys call
+ ; and return to the original caller
+
+duplicate_it:
+ mpusha
+ push ds
+ push es
+ mov bp,sp
+
+ mov di,std_fil_handle ; handle of the -C file
+
+ If @CodeSize eq 0
+ ; Small/compact models allow for quick test of us versus subprocess.
+ ; False negative (it's us with a different CS) will be picked
+ ; up by code just below. (Might happen due to call from C library.)
+ ; False positives would be bad, but can't happen.
+ mov ax,[bp+24] ; caller's CS
+ cmp ax,@code ; same as us?
+ je call_from_dmake
+ Endif
+
+ mov ah,51h ; get PSP ("undocumented version" works in DOS 2.0+)
+ simulate_21h ; PSP segment returned in BX
+ cmp bx,psp ; our PSP?
+ je call_from_dmake ; --yes, no PSP changing needed
+
+ mov es,bx ; set ES to current (caller's) PSP
+ lds bx,es:[34h] ; set DS:BX pointing to caller's job file table
+
+ mov si,[bp+12] ; file handle caller passed in (known to be 1 or 2)
+ mov al,[bx+si] ; system file number corresponding to caller's handle
+ cmp al,our_stdout ; same as our stdout?
+ jne do_real_write ; no--subprocess must have redirected it
+
+ mov al,[bx+di] ; see if caller has dup of -C file still open
+ cmp al,std_fil_number
+ je use_dup ; yes--we can write using caller's PSP
+
+ ; Calling process (or some intermediate process) has closed
+ ; the -C descriptor. We'll use dmake's (our) -C descriptor, but
+ ; to do so we'll have to change the PSP. Disable BREAK handling
+ ; so that ^break doesn't kill the wrong process.
+
+ mov ax,3300h ; get BREAK flag
+ simulate_21h
+ mov si,dx ; save BREAK state in SI
+ sub dx,dx ; now turn break flag off
+ mov ax,3301h
+ simulate_21h ; don't want ^Break recoginized while PSP changed
+ mov bx,psp ; set dmake's PSP
+ mov ah,50h
+ simulate_21h
+
+ mov bx,di ; handle of -C file
+ ; CX still has caller's count
+ mov ds,[bp+2] ; restore caller's DS
+ mov dx,[bp+14] ; DS:DX again points to caller's buffer
+ mov ah,40h
+ simulate_21h ; write the copy
+
+ mov bx,es ; caller's PSP
+ mov ah,50h ; set PSP
+ simulate_21h ; restore caller's PSP
+ mov dx,si ; break state before we changed it
+ mov ax,3301h
+ simulate_21h ; restore break state
+
+ jmp short do_real_write
+
+use_dup:
+ mov ds,[bp+2] ; restore caller's DS
+ mov dx,[bp+14] ; DS:DX again points to caller's buffer
+
+call_from_dmake:
+ mov bx,di ; handle of -C file
+ mov ah,40h ; write
+ ; CX still has caller's count
+ simulate_21h ; write to the file
+
+do_real_write:
+ pop es
+ pop ds
+ mpopa
+ popf
+ jmp [real_21h] ; far jump to real handler, which will do the sys call
+ ; and return to the original caller
+our_21h_handler endp
+
+ assume cs:@code, ds:@code, ss:@code, es:@code
+
+;-----------------------------------------------------------------------------
+; First define the critical-error and control-brk handlers.
+; The critical error handler simply pops the machine state and returns an
+; access denied result code.
+crit_err_handler proc far
+ add sp, 6 ; ip/cs/flags ...
+ pop ax
+ pop bx
+ pop cx
+ pop dx
+ pop si
+ pop di
+ pop bp
+ pop ds
+ pop es
+ push bp ; fix up the return flags
+ mov bp, sp
+ xchg ax, [bp+6] ; get the flag byte.
+ or ax, 1 ; set the carry bit
+ xchg ax, [bp+6] ; put it back.
+ pop bp
+ mov ax, 5 ; access denied
+ iret
+crit_err_handler endp
+
+
+;-----------------------------------------------------------------------------
+; Here we set the interrupted flag, and terminate the currently running
+; process.
+ctl_brk_handler proc far
+ clc ; make sure carry is clear
+ inc cs:interrupted ; set the flag
+
+; Make certain it isn't us that is going to get terminated.
+; There is a small window where the in_exec flag is set but the child is
+; not running yet, I assume that DOS doesn't test for ctl_brk at that time
+; as it is bussily creating a new process.
+ cmp cs:in_exec,0
+ je just_return ; note this implies CF == 0
+ stc ; set CF to abort child
+just_return: iret
+ctl_brk_handler endp
+
+
+;-----------------------------------------------------------------------------
+; Something really nasty happened, so abort the exec call and exit.
+; This kills the calling process altogether, and is a very nasty way of
+; termination since files may still be open etc.
+abort_exec_rhdr label near
+ mov dx, offset error_rhdr
+ jmp print_it
+abort_exec_rseg label near
+ mov dx, offset error_rseg
+ jmp print_it
+abort_exec_resize label near
+ mov dx, offset error_resize
+ jmp print_it
+abort_exec_free label near
+ mov dx, offset error_free
+ jmp print_it
+abort_exec_alloc label near
+ mov dx, offset error_alloc
+ jmp print_it
+abort_exec proc near
+ mov dx, offset error_string
+print_it: push dx
+ mov bx, [swap]
+ call [free_resource+bx]
+ mov ax, cs
+ mov ds, ax
+ pop dx
+ mov ah, 9
+ int 21H
+kill_program: mov ax, 04cffH ; nuke it!
+ int 21H
+abort_exec endp
+
+
+;-----------------------------------------------------------------------------
+; lodsw/stosw loop to copy data. Called only for word copy operations.
+; ds:si - point at source
+; es:di - point at destination
+; cx - count of bytes to copy.
+copy_data proc near
+ shr cx, 1 ; convert to word count
+ jnc copy_words
+ movsb
+copy_words: rep movsw ; copy the words.
+ ret
+copy_data endp
+
+
+
+;=============================================================================
+; THE FOLLOWING SECTION DEALS WITH ALL ROUTINES REQUIRED TO READ XMS RECORDS.
+;=============================================================================
+rhdr_xms proc near
+ ret
+rhdr_xms endp
+
+rseg_xms proc near
+ ret
+rseg_xms endp
+
+reset_xms_resource proc near
+ ret
+reset_xms_resource endp
+
+free_xms_resource proc near
+ ret
+free_xms_resource endp
+;=============================================================================
+
+
+
+;=============================================================================
+; THE FOLLOWING SECTION DEALS WITH ALL ROUTINES REQUIRED TO READ EMS RECORDS.
+;=============================================================================
+rhdr_ems proc near
+ ret
+rhdr_ems endp
+
+rseg_ems proc near
+ ret
+rseg_ems endp
+
+reset_ems_resource proc near
+ ret
+reset_ems_resource endp
+
+free_ems_resource proc near
+ ret
+free_ems_resource endp
+;=============================================================================
+
+
+
+;=============================================================================
+; THE FOLLOWING SECTION DEALS WITH ALL ROUTINES REQUIRED TO READ FILE RECORDS.
+;=============================================================================
+; This routine reads a segment header from a file.
+; The header is a seven byte record formatted as follows:
+; segment address - of data
+; offset address - of data
+; length in paragraphs - of data
+; mode - 1 => segment header (allocate seg on read)
+; 0 => subsegment, don't allocate on read.
+; The information is placed into the tmpseg data area in the code segment.
+; The routine aborts if an error is detected.
+rhdr_file proc near
+ mov dx, offset tmpseg ; read the header record out
+ mov cx, 7
+ mov bx, [tmphandle]
+ mov ah, 03fH
+ int 21H
+ jnc rhdr_done ; make sure it worked
+ jmp abort_exec_rhdr
+
+rhdr_done: cmp ax, 7
+ je exit_rhdr_file
+ or ax, ax
+ je signal_eof
+ jmp abort_exec_rhdr
+
+signal_eof: stc
+exit_rhdr_file: ret
+rhdr_file endp
+
+
+;-----------------------------------------------------------------------------
+; Read a segment from the temporary file whose handle is in cs:tmphandle.
+; The routine aborts if an error is detected.
+rseg_file proc near
+ push ds
+ mov ds, word ptr cs:tmpseg; Now read the whole segment
+ mov dx, word ptr cs:tmpseg+2
+ mov cx, word ptr cs:tmpseg+4
+ mov bx, cs:tmphandle
+ mov ah, 03fH
+ int 21H
+ pop ds
+ jnc rseg_done
+ jmp abort_exec_rseg
+
+rseg_done: cmp ax, [word ptr tmpseg+4]
+ je exit_rseg_file
+ jmp abort_exec_rseg ; If we didn't get read full
+exit_rseg_file: ret ; segment then abort
+rseg_file endp
+
+
+;-----------------------------------------------------------------------------
+; Seek to the beginning of the file.
+reset_file_resource proc near
+ mov bx, [tmphandle]
+ xor cx, cx
+ mov dx, cx
+ mov ax, 04200H ; seek to begining of file
+ int 21H
+ ret
+reset_file_resource endp
+
+
+;-----------------------------------------------------------------------------
+; unlink the temporary file allocated for swapping.
+; We close the file first, and then delete it. We ignore errors here since
+; we can't do anything about them anyway.
+free_file_resource proc near
+ mov bx, [tmphandle] ; get the file handle
+ mov ah, 03eH ; close the file
+ int 21H
+ mov dx, offset tmpname ; Now delete the temp file
+ mov ah, 041H
+ int 21H
+ ret
+free_file_resource endp
+;=============================================================================
+
+
+
+;=============================================================================
+; CODE TO SWAP THE IMAGE IN FROM SECONDARY STORAGE
+;=============================================================================
+swap_in proc near
+ mov bx, [alstr] ; get previous alloc strategy
+ mov ax, 5801H ; and set it back
+ int 21H
+ mov bx, [swap] ; get type of resource
+ call [reset_resource+bx] ; reset the resource
+ mov es, [psp] ; resize the program back
+ mov bx, [progsize] ; to original size
+ mov ah, 04AH
+ int 21H
+ jnc read_seg_loop
+ jmp abort_exec
+
+read_seg_loop: mov bx, [swap] ; get type of resource
+ call [read_header+bx] ; get seg header
+ jc exit_swap_in ; all done
+ mov al, [tmpseg+6]
+ cmp al, seg_no_alloc ; see if dummy segment header
+ je read_seg_loop
+ cmp al, seg_alloc ; do we need to do an alloc?
+ jne read_data ; nope
+
+; Allocate back the memory for a segment that is not the [psp], note that this
+; must come back to the same segment we had previously since other segments
+; may have pointers stored in their variables that point to this segment using
+; segment:offset long pointers.
+ mov bx, [word ptr tmpseg+4] ; get count of paragraphs
+ mov ah, 048H ; dos_alloc
+ int 21H
+ jc alloc_error ; oops!
+ cmp ax, [word ptr tmpseg] ; did we get the same segment?
+ je read_seg_loop ; yup!
+alloc_error: jmp abort_exec_alloc
+
+read_data: mov bx, [swap]
+ call [read_seg+bx] ; this must succeed, if fail
+ jmp read_seg_loop ; we never come back here
+
+exit_swap_in: mov bx, [swap] ; all done, so free resource
+ call [free_resource+bx]
+ ret
+swap_in endp
+
+
+;=============================================================================
+; CODE TO SWAP THE IMAGE OUT TO SECONDARY STORAGE
+;=============================================================================
+; This routine is called to swap the non-resident portion of the program
+; out to the resource specified by the value of [cs:swap]. If the swap out
+; fails, then appropriate routines are called to free the resources allocated
+; up to that point.
+;
+; The steps used to swap the program out are as follows:
+; - calculate new size of program to remain resident and size to swap
+; out.
+; - write out non-resident portion of current segment
+; - walk DOS allocation chain and write out all other segments owned by
+; the current program that are contiguous with the _psp segment
+; - copy the environment down to low memory
+; - resize the current _psp segment to savesize
+; - free all segments belonging to program except current _psp segment
+swap_out proc near
+ mov ax, 05800H ; get memory alocation strategy
+ int 021H
+ mov [alstr], ax ; and save it for future restoration.
+ mov di, [psp] ; compute length of program to current
+ mov bx, cs ; value of cs, and find program size
+ sub bx, di ; by looking at length stored in
+ mov ax, di ; arena header found in front of psp
+ dec ax
+ mov es, ax
+ mov si, es:3 ; si is size of program in paragraphs
+ mov [progsize], si ; progsize now contains the size.
+
+; Now compute length of program segment to save.
+; Length is: cs - psp + (offset overlay_code_here+15 >> 4)
+ mov ax, offset overlay_code_here+15
+ shr ax, 1
+ shr ax, 1
+ shr ax, 1
+ shr ax, 1
+ add bx, ax ; bx is size of program to keep
+ sub si, bx ; si is # of paragraphs to save.
+ add di, bx ; di is paragraph to start at
+ mov rootsize, bx
+ mov resend, di ; cs:resend is saved start para
+ mov al, seg_no_alloc ; set no allocation for segment
+ call write_segment
+ jc abort_swap_out
+
+; We have now saved the portion of the program segment that will not remain
+; resident during the exec. We should now walk the DOS allocation chain and
+; write out all other segments owned by the current process.
+save_segments: mov ax, [psp]
+ dec ax
+ mov es, ax
+ mov bx, offset write_segment_data
+ call walk_arena_chain
+ jc abort_swap_out
+
+; Now we must walk the chain of allocated memory blocks again and free
+; all those that are owned by the current process, except the one that is
+; the current process' psp.
+free_segments: mov ax, [psp]
+ dec ax
+ mov es,ax
+ mov bx, offset free_dos_segment
+ call walk_arena_chain
+ jnc resize_program
+ jmp abort_exec_free ; can't fix it up now.
+
+; We now resize the program to the size specified by cs:rootsize. This will
+; free most of the memory taken up by the current program segment.
+resize_program: mov es, [psp] ; es is segment to resize.
+ mov bx, [rootsize] ; bx is size of segment.
+ mov ah, 04aH ; resize memory block
+ int 21H
+ jnc swap_out_ok
+ jmp abort_exec_resize ; disaster
+swap_out_ok: ret
+
+; The swap out failed for some reason, so free any allocated resources
+; and set the carry bit.
+abort_swap_out: mov bx, [swap]
+ call [free_resource+bx]
+ xor ax, ax
+ mov [swap], ax ; clear the swap flag
+ stc
+ ret
+swap_out endp
+
+
+;=============================================================================
+; CODE TO SET-UP FOR AND EXEC THE CHILD PROCESS
+;=============================================================================
+; Actually execute the program. If cs:swap is set, this code will invoke the
+; swap-out/swap-in code as required.
+do_exec proc near
+ cmp [swap], 0 ; does the user want to swap?
+ je no_swap_out ; nope
+ call init_swap ; figger out where to swap to
+ jc no_swap_out ; if carry set then don't swap
+ call swap_out
+
+no_swap_out: cmp [interrupted], 0 ; were we interrupted?
+ jne leave_exec ; yep, so clean up, don't exec
+
+; free passed in environment block if it is non zero.
+; This way the parent program does not need to free it.
+ mov ax, [envseg]
+ or ax, ax
+ je setup_block
+ push ax
+ mov es, ax
+ mov ah, 49H
+ int 21H
+ pop ax
+
+; set up the parameter block for the DOS exec call.
+; offset contents
+; 00 segment address of environment to be passed,
+; 0 => use parents env.
+; 02 pointer to command tail for new process.
+; 06 pointer to fcb1
+; 0a pointer to fcb2
+setup_block: mov ax, [envseg]
+ mov [ex_envseg], ax
+ mov cx, cs
+ mov [word ptr ex_cmdtail], offset cmdtail
+ mov [word ptr ex_cmdtail+2], cx
+
+; set up registers for exec call
+; ds:dx - pointer to pathname of program to execute
+; es:bx - pointer to above parameter block
+ mov dx, offset cmdpath
+ mov es, cx
+ mov bx, offset exec_block
+
+; Under DOS 2.x exec is notorious for clobbering registers and guarantees
+; to preserve only cs:ip.
+ push ds
+ mov [ex_sp], sp
+ mov [ex_ss], ss
+ mov [ex_error], 0 ; clear exec error code
+ inc [in_exec] ; set internal flag
+ mov ax, 04b00H
+ int 21H
+
+; returned from exec, so restore possibly clobbered registers.
+ mov ss, cs:ex_ss
+ mov sp, cs:ex_sp
+ pop ds
+
+; check to make certain the exec call worked.
+ jnc it_worked
+
+; exec call failed. Save return code from msdos.
+ mov [ex_error], ax
+ jmp leave_exec
+
+it_worked: mov ah, 04dH ; get the return code
+ int 21H
+ cmp ah,1 ; check if terminated by ^C
+ jnz nosigint
+ inc interrupted ; yes so set flag
+nosigint: xor ah, ah ; 8-bit return code, so clear ah
+ mov [eretcode], ax
+
+leave_exec: cmp [swap], 0 ; check swap, if non-zero swap back in
+ je no_swap_in
+ call swap_in
+
+; Clear the in_exec after the swap back in. This way we are guaranteed to
+; get parent in and the resources freed should a ^C be hit when we are reading
+; the image in.
+no_swap_in: mov [in_exec], 0
+ ret
+do_exec endp
+
+
+
+;==============================================================================
+; Everything past this point is overwriten with the environment and new
+; program after the currently executing program is swapped out.
+;==============================================================================
+overlay_code_here label word
+
+;-----------------------------------------------------------------------------
+; Figure out where we can swap to and initialize the resource we are going to
+; use. We try XMS, EMS, and a tempfile (if specified), in that order. We set
+; [cs:swap] to the correct value based on which of the resources exists.
+; If none can be used, then [cs:swap] is set to 0, and no swap takes place.
+; The exec code will still attempt to execute the child in this instance, but
+; may fail due to lack of resources. Each swap_out_* routine must provide
+; its own clean-up handler should it not be able to write all program
+; segments to the swap resource.
+init_swap proc near
+ mov [swap], 0
+;call init_xms
+;jnc init_done
+;call init_ems
+;jnc init_done
+ call init_file
+init_done: ret
+init_swap endp
+
+
+;-----------------------------------------------------------------------------
+; This routine is used to walk the DOS allocated memory block chain
+; starting at address supplied in the es register. For each block it
+; calls the routine specified by the bx register with the segment length
+; in si, and its address in di. It does not apply the routine to the
+; segment if the segment is the same as the current program's [cs:psp] value.
+memheader struc
+ magic db ? ; either 'Z' for end or 'M' for allocated
+ owner dw ? ; psp of owner block
+ len dw ? ; length in paragraphs of segment
+memheader ends
+
+walk_arena_chain proc near
+ mov si, word ptr es:3 ; get length
+ mov di, es
+ inc di
+ mov ax, word ptr es:1
+
+; Stop the search if the block is NOT owned by us. Ignore our own psp block
+; and our environment segment block.
+ cmp ax, cs:psp ; is it owned by us?
+ jne walk_done ; NOPE! -- all done
+ cmp di, cs:envseg ; skip our environment
+ je next_block
+ cmp di, cs:psp ; skip our psp
+ je next_block
+
+; Now save state and call the routine pointed at by [bx].
+ push di
+ push si
+ push bx
+ call bx
+ pop bx
+ pop si
+ pop di
+ jc exit_walk ; if error then stop
+ mov al, byte ptr es:0 ; check if at end
+ cmp al, 'Z'
+ je walk_done
+
+next_block: add di, si ; go on to next segment
+ mov es, di
+ jmp walk_arena_chain
+walk_done: clc
+exit_walk: ret
+walk_arena_chain endp
+
+
+;-----------------------------------------------------------------------------
+; This routine takes a dos segment found in the di register and free's it.
+free_dos_segment proc near
+ mov es, di ; free dos memory block
+ mov ah, 49H
+ int 21H
+ ret
+free_dos_segment endp
+
+
+;-----------------------------------------------------------------------------
+; Called to invoke write_segment with proper values in the al register. Only
+; ever called from walk_arena_chain, and so al should be set to seg_alloc.
+write_segment_data label near
+ mov al, seg_alloc ; and fall through into write_segment
+;-----------------------------------------------------------------------------
+; This routine writes a segment as a block of data segments if the number of
+; paragraphs to write exceeds 0x0fff (rarely the case).
+; It stuffs the info into tmpseg, and then calls wheader and wseg to get the
+; data out.
+;
+; di:dx segment:offset of segment; offset is ALWAYS zero.
+; si number of paragraphs to write.
+; al mode of header to write
+write_segment proc near
+ push di
+ push si
+ xor dx,dx
+ mov bx, [swap]
+ call [write_header+bx]
+ pop si
+ pop di
+ jc exit_wseg
+
+do_io_loop: cmp si, 0 ; are we done yet?
+ je exit_wseg ; yup so leave.
+ mov cx, si ; # of paragraphs to move
+ cmp cx, 0fffH ; see if we have lots to move?
+ jle do_io
+ mov cx, 0fffH ; reset to max I/O size
+
+do_io: push cx ; save # of paragraphs we are writing
+ shl cx, 1 ; shift cx by four to the left
+ shl cx, 1
+ shl cx, 1
+ shl cx, 1
+ push di ; save the start, and count left
+ push si
+ mov si, cx
+ xor dx,dx
+ mov al, seg_data
+ mov bx, [swap]
+ push bx
+ call [write_header+bx]
+ pop bx
+ call [write_seg+bx]
+ pop si
+ pop di
+ pop dx ; original paragraph count in dx
+ jc exit_wseg ; it failed so exit.
+ add di, dx ; adjust the pointers, and continue.
+ sub si, dx
+ jmp do_io_loop
+exit_wseg: ret
+write_segment endp
+
+
+;=============================================================================
+; THE FOLLOWING SECTION DEALS WITH ALL ROUTINES REQUIRED TO WRITE XMS RECORDS.
+;=============================================================================
+init_xms proc near
+ ret
+init_xms endp
+
+whdr_xms proc near
+ ret
+whdr_xms endp
+
+wseg_xms proc near
+ ret
+wseg_xms endp
+;=============================================================================
+
+
+;=============================================================================
+; THE FOLLOWING SECTION DEALS WITH ALL ROUTINES REQUIRED TO WRITE EMS RECORDS.
+;=============================================================================
+init_ems proc near
+ ret
+init_ems endp
+
+whdr_ems proc near
+ ret
+whdr_ems endp
+
+wseg_ems proc near
+ ret
+wseg_ems endp
+;=============================================================================
+
+
+;=============================================================================
+; THE FOLLOWING SECTION DEALS WITH ALL ROUTINES REQUIRED TO WRITE FILES.
+;=============================================================================
+;-----------------------------------------------------------------------------
+; Attempt to create a temporary file. If the tempfile name is NIL then return
+; with the cary flag set.
+init_file proc near
+ mov al, [tmpname]
+ or al, al
+ je err_init_file
+ mov dx, offset tmpname
+ xor cx, cx
+ mov ah, 03cH
+ int 21H
+ jc err_init_file ; if carry set then failure
+ mov [tmphandle], ax ; init swapping
+ mov [swap], swap_file
+ jmp exit_init_file
+err_init_file: stc
+exit_init_file: ret
+init_file endp
+
+
+;-----------------------------------------------------------------------------
+; This routine writes a segment header to a file.
+; The header is a seven byte record formatted as follows:
+; segment address - of data
+; offset address - of data
+; length in paragraphs - of data
+; mode - 1 => segment header (allocate seg on read)
+; 0 => subsegment, don't allocate on read.
+; Routine takes three arguments:
+; di:dx segment:offset of segment
+; si number of paragraphs to write.
+; al mode of header to write
+whdr_file proc near
+ mov [word ptr tmpseg], di ; save the segment/offset
+ mov [word ptr tmpseg+2], dx
+ mov [word ptr tmpseg+4], si ; save the segment length
+ mov [tmpseg+6], al
+ mov dx, offset tmpseg ; write the header record out
+ mov cx, 7
+ mov bx, [tmphandle]
+ mov ah, 040H
+ int 21H
+ jc exit_whdr_file ; make sure it worked
+ cmp ax, 7
+ je exit_whdr_file ; oh oh, disk is full!
+err_whdr_file: stc
+exit_whdr_file: ret
+whdr_file endp
+
+
+;-----------------------------------------------------------------------------
+; Write a segment to the temporary file whose handle is in cs:tmphandle
+; Parameters for the write are assumed to be stored in the tmpseg data area.
+; function returns carry set if failed, carry clear otherwise.
+wseg_file proc near
+ push ds
+ mov ds, word ptr cs:tmpseg ; Now write the whole segment
+ mov dx, word ptr cs:tmpseg+2
+ mov cx, word ptr cs:tmpseg+4
+ mov bx, cs:tmphandle
+ mov ah, 040H
+ int 21H
+ pop ds
+ jc exit_wseg_file ; make sure it worked
+ cmp ax, [word ptr tmpseg+4]
+ je exit_wseg_file
+err_wseg_file: stc ; it failed (usually disk full)
+exit_wseg_file: ret
+wseg_file endp
+;=============================================================================
+
+
+;=============================================================================
+; _exec: THIS IS THE MAIN ENTRY ROUTINE TO THIS MODULE
+;=============================================================================
+; This is the main entry routine into the swap code and corresponds to the
+; following C function call:
+;
+; exec( int swap, char far *program, char far *cmdtail, int environment_seg,
+; char far *tmpfilename );
+;
+; Exec performs the following:
+; 1. set up the local code segment copies of arguments to the exec call.
+; 2. switch to a local stack frame so that we don't clobber the user
+; stack.
+; 3. save old interrupt vectors for ctrl-brk.
+; 4. install our own handler for the ctrl-brk interrupt, our handler
+; terminates the current running process, and returns with non-zero
+; status code.
+; 5. get our psp
+; 6. setup arguments for exec call
+; 7. exec the program, save result code on return.
+; 8. restore previous ctrl-brk and crit-error handler.
+; 9. restore previous process stack, and segment registers.
+; 10. return from exec with child result code in AX
+; and global _Interrupted flag set to true if child execution was
+; interrupted.
+
+; NOTE: When first called the segments here assume the standard segment
+; settings.
+ assume cs:@code, ds:DGROUP,es:DGROUP,ss:DGROUP
+
+ public _exec
+_exec proc
+ push bp ; set up the stack frame
+ mov bp, sp
+ push si ; save registers we shouldn't step on.
+ push di
+ push ds
+
+; set up for copying of parameters passed in with long pointers.
+ push cs ; going to use lodsb/stosb, set up es
+ pop es ; as destination.
+ assume es:@code ; let the assembler know :-)
+ cld ; make sure direction is right
+
+; Copy all parameters into the bottom of the code segment. After doing so we
+; will immediately switch stacks, so that the user stack is preserved intact.
+ mov ax, ss:[a_swap] ; save swap
+ mov es:swap, ax
+ mov ax, ss:[a_env] ; save env seg to use
+ mov es:envseg, ax
+
+ mov di, offset cs:cmdpath ; copy the command
+ lds si, ss:[a_prog] ; 65 bytes worth
+ mov cx, 65
+ call copy_data
+
+ mov di, offset cs:cmdtail ; copy the command tail
+ lds si, ss:[a_tail] ; 129 bytes worth
+ mov cx, 129
+ call copy_data
+
+ mov di, offset cs:tmpname ; copy the temp file name
+ lds si, ss:[a_tmp] ; 65 bytes worth.
+ mov cx, 65
+ call copy_data
+
+; Now we save the current ss:sp stack pointer and swap stack to our temporary
+; stack located in the current code segment. At the same time we reset the
+; segment pointers to point into the code segment only.
+swap_stacks: mov ax, ss
+ mov es:old_ss, ax
+ mov es:old_sp, sp
+ mov ax, cs
+ mov ds, ax
+ mov ss, ax ; set ss first, ints are then
+ mov sp, offset cs:exec_sp ; disabled for this instr too
+ assume ds:@code, ss:@code ; let the assembler know :-)
+
+; Now we save the old control break and critical error handler addresses.
+; We replace them by our own routines found in the resident portion of the
+; swapping exec code.
+set_handlers: mov [interrupted], 0 ; clear interrupted flag
+ mov [eretcode], 0 ; clear the return code
+ mov ax, 03523H ; get int 23 handler address
+ int 21H
+ mov cs:old_ctl_brk_off, bx
+ mov cs:old_ctl_brk_seg, es
+ mov dx, offset ctl_brk_handler
+ mov ax, 02523H ; set int 23 handler address
+ int 21H
+
+ mov ax, 03524H ; get int 24 handler address
+ int 21H
+ mov cs:old_crit_err_off, bx
+ mov cs:old_crit_err_seg, es
+ mov dx, offset crit_err_handler
+ mov ax, 02524H ; set int 24 handler address
+ int 21H
+
+; Go and execute the child, we've set up all of its parameters. The do_exec
+; routine will attempt to perform a swap of the code if requested to do so by
+; a non-zero value in the variable cs:swap.
+ mov ah, 051H ; get the psp
+ int 21H
+ mov cs:psp, bx
+ call do_exec
+
+; We're back from the exec, so fix things up the way they were.
+; Restore the old control-break and critical-error handlers.
+ lds dx, cs:old_ctl_brk
+ mov ax, 02523H
+ int 21H
+ lds dx, cs:old_crit_err
+ mov ax, 02524H
+ int 21H
+
+; Restore previous program stack segment registers, and data segment.
+ mov ax, cs:old_ss
+ mov ss, ax ; mov into ss first, that way
+ mov sp, cs:old_sp ; no interrupts in this instr.
+ pop ds
+
+; Tell the assembler we have swaped segments again.
+ assume ds:DGROUP,es:DGROUP,ss:DGROUP
+
+; Set the global Interrupted flag so that parent can tell it was interrupted.
+ mov ax, seg DGROUP:_Interrupted
+ mov es, ax
+ mov ax, cs:interrupted
+ mov es:_Interrupted, ax
+
+; Set the global errno value to reflect the success/failure of the DOS
+; exec call.
+ mov ax, seg DGROUP:_errno
+ mov es, ax
+ mov ax, cs:ex_error
+ mov es:_errno, ax
+
+; Fetch the child's return code, pop rest of stuff off of the stack
+; and return to the caller.
+ mov ax, cs:eretcode
+ pop di
+ pop si
+ pop bp
+ ret
+_exec endp
+
+; void do_hook_std_writes(int handle);
+; This saves the 21h interrupt vector and changes it to point
+; into this code. Argument is the file handle of the -C file.
+
+ public _do_hook_std_writes
+_do_hook_std_writes proc
+ push bp
+ mov bp,sp
+ push di
+
+ mov di, ss:[a_handle] ; handle of -C file
+ mov std_fil_handle, di
+
+ mov ah, 51h ; request our PSP
+ int 21h
+ mov [psp], bx ; save it
+
+ mov es, bx
+ les bx, es:[34h] ; pointer to job file table
+ mov al, es:[bx+1] ; system file # of our stdout
+ mov [our_stdout], al
+ mov al, es:[bx+di] ; system file number of -C file
+ mov std_fil_number, al
+
+ mov ax,3521h ; request vector 21h
+ int 21h ; it's returned in ES:BX
+ mov word ptr [real_21h], bx
+ mov word ptr [real_21h+2], es
+
+ push ds
+ mov ax,cs
+ mov ds,ax
+ lea dx,our_21h_handler ; DS:DX is the new vector
+ mov ax,2521h ; set vector 21h
+ int 21h
+
+ pop ds
+ pop di
+ pop bp
+ ret
+_do_hook_std_writes endp
+
+; void do_unhook_std_writes(void);
+; This restores the 21h interrupt vector.
+; The saved vector is zero if it wasn't changed (no -C option).
+
+ public _do_unhook_std_writes
+_do_unhook_std_writes proc
+ push ds
+
+ lds dx, [real_21h] ; put saved vector into DS:DX
+ mov ax, ds
+ or ax, dx
+ jz unhook_return ; zero means we didn't hook 21h
+
+ mov ax,2521h ; set vector 21h
+ simulate_21h
+
+unhook_return: pop ds
+ ret
+_do_unhook_std_writes endp
+end
diff --git a/dmake/msdos/exec.h b/dmake/msdos/exec.h
new file mode 100644
index 000000000000..f603bc43d2cb
--- /dev/null
+++ b/dmake/msdos/exec.h
@@ -0,0 +1,43 @@
+/* RCS $Id: exec.h,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Internal version of exec for dmake.
+--
+-- DESCRIPTION
+-- External defines for the exec.c code.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+#ifndef _EXEC_h_
+#define _EXEC_h_
+
+#ifndef ANSI
+#if defined(__STDC__) || defined(__TURBOC__)
+#define ANSI(x) x
+#else
+#define ANSI(x) ()
+#endif
+#endif
+
+extern int exec ANSI((int, char far *, char far *, unsigned int, char far *));
+
+#ifndef MK_FP
+#define MK_FP(seg,ofs) \
+ ((void far *) (((unsigned long)(seg) << 16) | (unsigned)(ofs)))
+#endif
+
+#endif
diff --git a/dmake/msdos/exec.uue b/dmake/msdos/exec.uue
new file mode 100644
index 000000000000..90a1c3e661e8
--- /dev/null
+++ b/dmake/msdos/exec.uue
@@ -0,0 +1,63 @@
+begin 777 exec.obj
+M@! #DU31$]37&5X96,N87-M;(@@ '%1U<F)O($%S<V5M8FQE<B @5F5R
+M<VEO;B S+C";B!8 0.DJ<T$=#DU31$]37&5X96,N87-M.H@# $#I3)8" !H
+MB , 0*&4EA "45814-?5$585 1#3T1%:9@' $@:" (# ?&6# %7T1!5$$$
+M1$%40<*8!P!( @ $!0$-E@@ !D1'4D]54(N:! &_P);C D !E]E<G)N;P#@
+MD!, 0(,7TEN=&5R<G5P=&5D 69 < !%5]D;U]U;FAO;VM?<W1D7W=R
+M:71E<P,( &>0# 05?97AE8^$& '.0&@ 1-?9&]?:&]O:U]S=&1?=W)I
+M=&5SN < FH@$ $"B 9&@!@ !F ,&B#@ !7 $E $ 0 $ RJ(. &(
+M 4$ 0 ! 0""H@X <D! 0 ! $ ! (&@" !S $ BJ#' '4
+M 65X96,Z($9A:6QU<F4@<F5A9&EN9R!H96%D97(@8FQO8VL-"B1E>&5C.B!&
+M86EL=7)E(')E861I;F<@<V5G;65N="!D871A#0HD97AE8SH@1F%I;'5R92!O
+M;B!R97-I>F4-"B1E>&5C.B!&86EL=7)E('1O(&9R964@82!B;&]C:PT*)&5X
+M96,Z(%!R;V=R86T@<W=A<"!F86EL=7)E#0HD97AE8SH@365M;W)Y(&)L;V-K
+M<R!D;VXG="!M871C: T*)+>B#@ !EP(! $ 0 $ LJ H &8 G(&=0:7
+M!G,&=@:]!@,$!P0+! 0$" 0J! 8$"@1@! 4$"012! J<20#$ %0!Q )4 <0$
+M5 '$!E0!Q A4 <0*5 '$#%0!Q Y4 <005 '$$E0!Q!14 <065 '$&%0!Q!I4
+M <0<5 '$'E0!Q"!4 <0B5 $GH P <H"7 $ %P! #-G D S !4 <P$5 $5
+MH,T# =8" "<@/Q =0J#^P%T"X/[ G0&G2[_+LP!4%%24U155E<>!HOL+HL^
+MT &T49PN_Q[, 2X['HP =&R.PR;%'C0 BW8,B@ N.@;3 75CB@$N.@;2 71*
+MN SG"[_'LP!B_(KTK@!,YPN_Q[, 2Z+'HP M%"<+O\>S &+WXY> HM6#K1
+MG"[_'LP!C,.T4)PN_Q[, 8O6N $SG"[_'LP!ZQ".7@*+5@Z+W[1 G"[_'LP!
+M!Q]?7EV#Q );6EE8G2[_+LP!@\0&6%M96EY?71\'58OLAT8&#0$ AT8&7;@%
+M ,_X+O\&D@ N@SZ8 !T ?G/NM0!ZQR0NOD!ZQ:0NAX"ZQ"0NC@"ZPJ0NG4"
+MZP20NE@"4HL>C@#_E[ "C,B.V%JT"<TAN/],S2'1Z7,!I/.EP\/#P\/#P\/#
+MNH$!N0< BQ[* ;0_S2%S NNF/0< = <+P'0"ZYOYPQXNCAZ! 2Z+%H,!+HL.
+MA0$NBQ[* ;0_S2$?<P+K@3L&A0%T ^EX_\.+'LH!,\F+T;@ 0LTAPXL>R@&T
+M/LTANH@!M$'-(<.+'I8 N %8S2&+'HX _Y>V HX&C "+'H0 M$K-(7,#Z4__
+MBQZ. /^7I )R**"' 3P =.\\ 743BQZ% ;1(S2%R!CL&@0%TV^DA_XL>C@#_
+MEZH"Z\Z+'HX _Y>P L.X %C-(:.6 (L^C ",RRO?B\=(CL FBS8# (DVA "X
+MYP71Z-'HT>C1Z /8*_,#^XD>A@")/H@ L #H'0%R,:&, $B.P+LD!NC+ '(C
+MH8P 2([ NQT&Z+T <P/IJ_Z.!HP BQZ& +1*S2%S ^F4_L.+'HX _Y>P C/
+MHXX ^<.#/HX '0(Z(, <@/H<_^#/I( '5FH8H "\!T"%".P+1)S2%8H8H
+MH\0"C,G'!L8"VP")#L@"NIH CL&[Q (>B2;4 HP6T@+'!M8" #_!I@ N !+
+MS2$NCA;2 BZ+)M0"'W,&H]8"ZQ.0M$W-(8#\ 74$_P:2 #+DHY @SZ. !T
+M ^B?_L<&F ,/'!HX #HE@##)HLV P",QT<FH0$ +CL&C !U)BX[/HH
+M=!DN.SZ, '025U93_]-;7E]R#R:@ \6G0& _Z.Q^O'^,..Q[1)S2'#L %7
+M5C/2BQZ. /^7F )>7W(Z@_X =#6+SH'Y_P]^ [G_#U'1X='AT>'1X5=6B_$S
+MTK "BQZ. %/_EY@"6_^7G@)>7UIR!@/Z*_+KQL/#P\/#P\.@B $*P'07NH@!
+M,\FT/,TA<@RCR@''!HX ! #K I#YPXD^@0&)%H,!(YR1 <065 '$)U0!Q"]4
+M <0T5 '$1U0!Q%!4 <1;5 '$:%0!Q&U4 <1U5 '$A50!Q(]4 <2:5 '$K%0!
+MQ+Y4 <3A5 '$YE0!Q.Y4 <3T5 '$^E0!Q0!4 <4&5 '%#%0!Q1%4 <455 '%
+M-E0!Q3U4 <585 '%750!Q6)4 <5G5 '%=%0!Q7Y4 <6,5 '%DU0!Q9Q4 <6E
+M5 '%J50!Q:U4 <6Q5 '%OE0!Q<)4 <7'5 '%TU0!Q=U4 <865 '&/%0!QDI4
+M <7F5 '%ZE0!Q?!4 <7T5 '%_50!Q@%4 <835 '&*%0!QBQ4 <8V5 '&1%0!
+MQE94 <9:5 '&:%0!QFQ4 <9Q5 '&=U0!QH94 <:,5 '&FU0!QIY4 <:D5 '&
+MIE0!QJI4 <:M5 '&LE0!QK=4 <:[5 '&OU0!QL54 <;/5 '&U%0!QMI4 <;J
+M5 '&[U0!QO-4 <;]5 ''!%0!QQM4 <<B5 ''*50!QU94 <=:5 ''@U0!QXA4
+M <>-5 ''HE0!QZE4 <>T5 ''N%0!Q\-4 <?'5 $%H'\! 9\&B3:% :*' ;J!
+M ;D' (L>R@&T0,TA<@8]!P!T ?G#'BZ.'H$!+HL6@P$NBPZ% 2Z+'LH!M$#-
+M(1]R!SL&A0%T ?G#58OL5E<>#@?\BT8&)J.. (M&$":CB@"_F@#%=@BY00#H
+M]_R_VP#%=@RY@0#HZ_R_B '%=A*Y00#HW_R,T":C@ FB2:" (S(CMB.T+R
+M ,<&D@ ,<&D +@C-<TA+HD>O (NC :^ KJS [@C)<TAN"0US2$NB1[
+M BZ,!L("NI8#N"0ES2&T4<TA+HD>C #HU?TNQ1:\ K@C)<TA+L46P *X)"7-
+M(2ZA@ ".T"Z+)H( '[@ ([ +J&2 ":C "X ".P"ZAU@(FHP +J&0 %]>
+M7<M5B^Q7BWX&+HD^T &T4<TA+HD>C ".PR;$'C0 )HI' 2ZBTP$FB@$NHM(!
+MN"$US2$NB1[, 2Z,!LX!'HS(CMBZV *X(27-(1]?7<L>+L46S &,V O"= FX
+M(26<+O\>S $?RPJ<O0#$ E0!Q 54 <0(5 '$#U0!Q")4 <0G5 '$+%0!Q#%4
+M <0\5 '$4%0!Q%=4 <1:5 '$9E0!Q')4 <2!5 '$AE0!Q(]4 <235 '$F50!
+MQ*54 <2J5 '$K50!Q+Q4 <3!5 '$Q%0!Q-)4 <3:5 '$Y%0!Q.U4 <3T5 '(
+M^!0! L3^5 '% A0! LD%%@$!Q0M4 <4/%@$!Q1-4 <4C5 '%+%0!Q3M4 <5"
+E5 '%3%0!Q5%4 <595 '%:%0!Q7=4 ?6@!@ " %B* @ =%0!
+
+end
diff --git a/dmake/msdos/find.c b/dmake/msdos/find.c
new file mode 100644
index 000000000000..d35cc477ec9e
--- /dev/null
+++ b/dmake/msdos/find.c
@@ -0,0 +1,130 @@
+/*
+ Directory Access Library
+
+ FIND.C taken from DIRLIB.C by M. J. Weinstein
+ Released to public domain 1-Jan-89
+
+ The author may be contacted at:
+ matt@cs.ucla.edu -or- POB 84524, L.A., CA 90073
+
+ Modified by dvadura@watdragon.edu to work with dmake.
+ (nuked the DOS version 2 code, since dmake needs version
+ 3.0 or greater to function).
+ */
+
+
+/*
+ * revision history:
+ *
+ * VER MM/DD/YY COMMENTS
+ * ---- -------- --------
+ * 0.99 02/24/86 Beta release to INTERNET
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <alloc.h>
+#include <dos.h>
+#include "dosdta.h"
+
+#ifndef MK_FP
+#define MK_FP(seg,ofs) ((void far *) \
+ (((unsigned long)(seg) << 16) | (unsigned)(ofs)))
+#endif
+#ifndef FP_SEG
+#define FP_SEG(fp) ((unsigned)((unsigned long)(fp) >> 16))
+#endif
+#ifndef FP_OFF
+#define FP_OFF(fp) ((unsigned)(fp))
+#endif
+
+int find_err;
+
+/*
+ * get/set dta address
+ */
+
+static DTA far *
+_getsetdta(newdta)
+DTA far *newdta;
+{
+ DTA far *olddta;
+ union REGS r;
+ struct SREGS s;
+
+ /* get old dta */
+ r.h.ah = 0x2f;
+ intdos(&r, &r);
+ segread(&s);
+ olddta = (DTA far *) MK_FP(s.es, r.x.bx);
+
+ /* conditionally set new dta */
+ if (newdta) {
+ r.h.ah = 0x1a;
+ s.ds = FP_SEG(newdta);
+ r.x.dx = FP_OFF(newdta);
+ intdosx(&r, &r, &s);
+ }
+
+ return olddta;
+}
+
+/*
+ * dos findfirst
+ */
+
+DTA *
+findfirst(name, dta)
+char *name;
+DTA *dta;
+{
+ union REGS r;
+ struct SREGS s;
+ DTA far *dtasave;
+ char far *nmp = (char far *)name;
+
+ dtasave = _getsetdta((DTA far *)dta);
+
+ /* do directory lookup */
+ segread(&s);
+ r.h.ah = 0x4e;
+ r.x.cx = 0x10;
+ r.x.dx = FP_OFF(nmp);
+ s.ds = FP_SEG(nmp);
+ intdosx(&r, &r, &s);
+ /* restore dta */
+ _getsetdta(dtasave);
+ find_err = r.x.ax;
+ if (r.x.cflag)
+ return(NULL);
+
+ return dta;
+}
+
+/*
+ * dos findnext
+ */
+
+DTA *
+findnext(dta)
+DTA *dta;
+{
+ union REGS r;
+ DTA far *dtasave;
+
+ dtasave = _getsetdta((DTA far *)dta);
+
+ /* do directory lookup */
+ r.h.ah = 0x4f;
+ intdos(&r, &r);
+ /* restore old dta */
+ _getsetdta(dtasave);
+ find_err = r.x.ax;
+ if (r.x.cflag)
+ return(NULL);
+
+ return dta;
+}
diff --git a/dmake/msdos/microsft/config.h b/dmake/msdos/microsft/config.h
new file mode 100644
index 000000000000..ba62cfe2a353
--- /dev/null
+++ b/dmake/msdos/microsft/config.h
@@ -0,0 +1,77 @@
+/* RCS $Id: config.h,v 1.1.1.1 2000-09-22 15:33:29 hr Exp $
+--
+-- SYNOPSIS
+-- Configurarion include file.
+--
+-- DESCRIPTION
+-- There is one of these for each specific machine configuration.
+-- It can be used to further tweek the machine specific sources
+-- so that they compile.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#if defined (_MSC_VER)
+# if _MSC_VER < 500
+ Force a compile-time blowup.
+ Do not define "#define _MSC_VER" for MSC compilers earlier than 5.0.
+# endif
+#endif
+
+/* define this for configurations that don't have the coreleft function
+ * so that the code compiles. To my knowledge coreleft exists only on
+ * Turbo C, but it is needed here since the function is used in many debug
+ * macros. */
+#define coreleft() 0L
+
+/* MSC Version 4.0 doesn't understand SIGTERM, later versions do. */
+#ifndef SIGTERM
+# define SIGTERM SIGINT
+#endif
+
+/* Fixes unimplemented line buffering for MSC 5.x and 6.0.
+ * MSC _IOLBF is the same as _IOFBF
+ */
+#if defined(MSDOS) && defined (_MSC_VER)
+# undef _IOLBF
+# define _IOLBF _IONBF
+#endif
+
+/* in alloc.h: size_t is redefined
+ * defined in stdio.h which is included by alloc.h
+ */
+#if defined(MSDOS) && defined (_MSC_VER)
+# define _TYPES_
+#endif
+
+/* in sysintf.c: SIGQUIT is used, this is not defined in MSC */
+#ifndef SIGQUIT
+# define SIGQUIT SIGTERM
+#endif
+
+/* MSC doesn't seem to care about CONST */
+#define CONST
+
+#ifndef MSDOS
+# define MSDOS 1
+#endif
+
+/* a small problem with pointer to voids on some unix machines needs this */
+#define PVOID void *
+
+/* Have to pull this in for the standard lib defines */
+#include <io.h>
diff --git a/dmake/msdos/microsft/config.mk b/dmake/msdos/microsft/config.mk
new file mode 100644
index 000000000000..cd049cd471af
--- /dev/null
+++ b/dmake/msdos/microsft/config.mk
@@ -0,0 +1,59 @@
+# This is the MSC 4.0 and higher DOS configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+TMPDIR :=
+.EXPORT : TMPDIR
+
+# Definition of macros for library, and C startup code.
+
+# The following sources are required for MSC
+OSR_SRC = tempnam.c
+.SETDIR=$(osrdir) : $(OSR_SRC)
+
+SRC += $(OSR_SRC)
+.SOURCE.h : $(osrdir)
+
+SET_STACK = -stack:4096
+NDB_LDFLAGS += $(SET_STACK)
+
+ASFLAGS += -t -mx $(S_$(MODEL))
+
+# Microsoft C doesn't need tail but needs head
+LDTAIL = ;
+LDHEAD =
+
+# Debugging libraries
+DB_LDFLAGS += -co -li -map $(SET_STACK)
+DB_LDLIBS +=
+
+# NO Debug MSC flags:
+# Set the environment variable MSC_VER to be one of 5.1, 6.0, 8.0 (for VC++4.0)
+# to get these by default when you make dmake using 'dmake'.
+#
+# Setting MSC_VER to one of the above sets the variable _MSC_VER appropriately
+# and sets the flags appropriately.
+
+CFLAGS += -I$(osrdir) $(C_$(MODEL)) -nologo
+DB_CFLAGS += -Zi
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
+
+C_s =
+C_m = -AM
+C_c = -AC
+C_l = -AL
+
+S_s = -Dmsmall
+S_m = -Dmmedium
+S_c = -Dmcompact
+S_l = -Dmlarge
diff --git a/dmake/msdos/microsft/msc51/config.mk b/dmake/msdos/microsft/msc51/config.mk
new file mode 100644
index 000000000000..beaae0dfea97
--- /dev/null
+++ b/dmake/msdos/microsft/msc51/config.mk
@@ -0,0 +1,11 @@
+# Definition of macros for library, and C startup code.
+osedir = $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)
+
+.IMPORT .IGNORE : MSC_VER
+MSC_VER *= 5.1
+
+CFLAGS += -I$(osedir) -D_MSC_VER=$(MSC_VER:s,.,,)0
+
+NDB_CFLAGS += -Oscl -Gs
+NDB_LDFLAGS += -exe -packc -batch
+NDB_LDLIBS +=
diff --git a/dmake/msdos/microsft/msc51/lib.rsp b/dmake/msdos/microsft/msc51/lib.rsp
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/dmake/msdos/microsft/msc51/lib.rsp
@@ -0,0 +1 @@
+
diff --git a/dmake/msdos/microsft/msc51/libswp.rsp b/dmake/msdos/microsft/msc51/libswp.rsp
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/dmake/msdos/microsft/msc51/libswp.rsp
@@ -0,0 +1 @@
+
diff --git a/dmake/msdos/microsft/msc51/mk.bat b/dmake/msdos/microsft/msc51/mk.bat
new file mode 100755
index 000000000000..b111d6e62f01
--- /dev/null
+++ b/dmake/msdos/microsft/msc51/mk.bat
@@ -0,0 +1,102 @@
+md objects
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs infer.c
+copy infer.obj objects
+del infer.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs make.c
+copy make.obj objects
+del make.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs stat.c
+copy stat.obj objects
+del stat.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs expand.c
+copy expand.obj objects
+del expand.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs dmstring.c
+copy dmstring.obj objects
+del dmstring.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs hash.c
+copy hash.obj objects
+del hash.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs dag.c
+copy dag.obj objects
+del dag.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs dmake.c
+copy dmake.obj objects
+del dmake.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs path.c
+copy path.obj objects
+del path.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs imacs.c
+copy imacs.obj objects
+del imacs.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs sysintf.c
+copy sysintf.obj objects
+del sysintf.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs parse.c
+copy parse.obj objects
+del parse.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs getinp.c
+copy getinp.obj objects
+del getinp.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs quit.c
+copy quit.obj objects
+del quit.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs state.c
+copy state.obj objects
+del state.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs dmdump.c
+copy dmdump.obj objects
+del dmdump.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs macparse.c
+copy macparse.obj objects
+del macparse.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs rulparse.c
+copy rulparse.obj objects
+del rulparse.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs percent.c
+copy percent.obj objects
+del percent.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs function.c
+copy function.obj objects
+del function.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\ruletab.c
+copy ruletab.obj objects
+del ruletab.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\dirbrk.c
+copy dirbrk.obj objects
+del dirbrk.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\runargv.c
+copy runargv.obj objects
+del runargv.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\arlib.c
+copy arlib.obj objects
+del arlib.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\dchdir.c
+copy dchdir.obj objects
+del dchdir.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\switchar.c
+copy switchar.obj objects
+del switchar.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\rmprq.c
+copy rmprq.obj objects
+del rmprq.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\tee.c
+copy tee.obj objects
+del tee.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\find.c
+copy find.obj objects
+del find.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\dirlib.c
+copy dirlib.obj objects
+del dirlib.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\dstrlwr.c
+copy dstrlwr.obj objects
+del dstrlwr.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs unix\dcache.c
+copy dcache.obj objects
+del dcache.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\microsft\tempnam.c
+copy tempnam.obj objects
+del tempnam.obj
+link /stack:4096/exe/packc/batch @msdos\microsft\msc51\obj.rsp,dmake.exe,NUL.MAP;
+copy msdos\microsft\msc51\template.mk startup\config.mk
diff --git a/dmake/msdos/microsft/msc51/mkswp.bat b/dmake/msdos/microsft/msc51/mkswp.bat
new file mode 100755
index 000000000000..5ab14d3517e5
--- /dev/null
+++ b/dmake/msdos/microsft/msc51/mkswp.bat
@@ -0,0 +1,104 @@
+md objects
+masm -t -mx -Dmlarge msdos\exec.asm,,,;
+mv exec.obj objects
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs infer.c
+copy infer.obj objects
+del infer.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs make.c
+copy make.obj objects
+del make.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs stat.c
+copy stat.obj objects
+del stat.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs expand.c
+copy expand.obj objects
+del expand.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs dmstring.c
+copy dmstring.obj objects
+del dmstring.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs hash.c
+copy hash.obj objects
+del hash.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs dag.c
+copy dag.obj objects
+del dag.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs dmake.c
+copy dmake.obj objects
+del dmake.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs path.c
+copy path.obj objects
+del path.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs imacs.c
+copy imacs.obj objects
+del imacs.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs sysintf.c
+copy sysintf.obj objects
+del sysintf.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs parse.c
+copy parse.obj objects
+del parse.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs getinp.c
+copy getinp.obj objects
+del getinp.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs quit.c
+copy quit.obj objects
+del quit.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs state.c
+copy state.obj objects
+del state.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs dmdump.c
+copy dmdump.obj objects
+del dmdump.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs macparse.c
+copy macparse.obj objects
+del macparse.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs rulparse.c
+copy rulparse.obj objects
+del rulparse.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs percent.c
+copy percent.obj objects
+del percent.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs function.c
+copy function.obj objects
+del function.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\ruletab.c
+copy ruletab.obj objects
+del ruletab.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\dirbrk.c
+copy dirbrk.obj objects
+del dirbrk.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\runargv.c
+copy runargv.obj objects
+del runargv.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\arlib.c
+copy arlib.obj objects
+del arlib.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\dchdir.c
+copy dchdir.obj objects
+del dchdir.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\switchar.c
+copy switchar.obj objects
+del switchar.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\rmprq.c
+copy rmprq.obj objects
+del rmprq.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\spawn.c
+copy spawn.obj objects
+del spawn.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\find.c
+copy find.obj objects
+del find.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\dirlib.c
+copy dirlib.obj objects
+del dirlib.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\dstrlwr.c
+copy dstrlwr.obj objects
+del dstrlwr.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs unix\dcache.c
+copy dcache.obj objects
+del dcache.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc51 -D_MSC_VER=510 -Oscl -Gs msdos\microsft\tempnam.c
+copy tempnam.obj objects
+del tempnam.obj
+link /stack:4096/exe/packc/batch @msdos\microsft\msc51\objswp.rsp,dmake.exe,NUL.MAP;
+copy msdos\microsft\msc51\template.mk startup\config.mk
diff --git a/dmake/msdos/microsft/msc51/obj.rsp b/dmake/msdos/microsft/msc51/obj.rsp
new file mode 100644
index 000000000000..8f79a32754c9
--- /dev/null
+++ b/dmake/msdos/microsft/msc51/obj.rsp
@@ -0,0 +1,33 @@
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dirbrk.obj+
+objects\runargv.obj+
+objects\arlib.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\rmprq.obj+
+objects\tee.obj+
+objects\find.obj+
+objects\dirlib.obj+
+objects\dstrlwr.obj+
+objects\dcache.obj+
+objects\tempnam.obj
diff --git a/dmake/msdos/microsft/msc51/objswp.rsp b/dmake/msdos/microsft/msc51/objswp.rsp
new file mode 100644
index 000000000000..54524124d236
--- /dev/null
+++ b/dmake/msdos/microsft/msc51/objswp.rsp
@@ -0,0 +1,34 @@
+objects\exec.obj+
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dirbrk.obj+
+objects\runargv.obj+
+objects\arlib.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\rmprq.obj+
+objects\spawn.obj+
+objects\find.obj+
+objects\dirlib.obj+
+objects\dstrlwr.obj+
+objects\dcache.obj+
+objects\tempnam.obj
diff --git a/dmake/msdos/microsft/msc51/public.h b/dmake/msdos/microsft/msc51/public.h
new file mode 100644
index 000000000000..3130d161c24e
--- /dev/null
+++ b/dmake/msdos/microsft/msc51/public.h
@@ -0,0 +1,169 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:29 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+int If_root_path ANSI((char *));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+void Clean_up_processes ANSI(());
+int Wait_for_child ANSI((int, int));
+time_t seek_arch ANSI((char*, char*));
+int touch_arch ANSI((char*, char*));
+int dchdir ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int spawnvpe ANSI((int, char *, char **, char **));
+void Hook_std_writes ANSI((char *));
+void dstrlwr ANSI((char *, char *));
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/msdos/microsft/msc51/template.mk b/dmake/msdos/microsft/msc51/template.mk
new file mode 100644
index 000000000000..7174197d6284
--- /dev/null
+++ b/dmake/msdos/microsft/msc51/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= msdos
+ OSRELEASE *:= microsft
+ OSENVIRONMENT *:= msc51
diff --git a/dmake/msdos/microsft/msc60/config.mk b/dmake/msdos/microsft/msc60/config.mk
new file mode 100644
index 000000000000..5b206bec34bd
--- /dev/null
+++ b/dmake/msdos/microsft/msc60/config.mk
@@ -0,0 +1,11 @@
+# Definition of macros for library, and C startup code.
+osedir = $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)
+
+.IMPORT .IGNORE : MSC_VER
+MSC_VER *= 6.0
+
+CFLAGS += -I$(osedir) -D_MSC_VER=$(MSC_VER:s,.,,)0
+
+NDB_CFLAGS += -Osecgl -Gs
+NDB_LDFLAGS += -exe -packc -batch
+NDB_LDLIBS +=
diff --git a/dmake/msdos/microsft/msc60/lib.rsp b/dmake/msdos/microsft/msc60/lib.rsp
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/dmake/msdos/microsft/msc60/lib.rsp
@@ -0,0 +1 @@
+
diff --git a/dmake/msdos/microsft/msc60/libswp.rsp b/dmake/msdos/microsft/msc60/libswp.rsp
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/dmake/msdos/microsft/msc60/libswp.rsp
@@ -0,0 +1 @@
+
diff --git a/dmake/msdos/microsft/msc60/mk.bat b/dmake/msdos/microsft/msc60/mk.bat
new file mode 100755
index 000000000000..c260b6d54abd
--- /dev/null
+++ b/dmake/msdos/microsft/msc60/mk.bat
@@ -0,0 +1,102 @@
+md objects
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs infer.c
+copy infer.obj objects
+del infer.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs make.c
+copy make.obj objects
+del make.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs stat.c
+copy stat.obj objects
+del stat.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs expand.c
+copy expand.obj objects
+del expand.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs dmstring.c
+copy dmstring.obj objects
+del dmstring.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs hash.c
+copy hash.obj objects
+del hash.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs dag.c
+copy dag.obj objects
+del dag.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs dmake.c
+copy dmake.obj objects
+del dmake.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs path.c
+copy path.obj objects
+del path.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs imacs.c
+copy imacs.obj objects
+del imacs.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs sysintf.c
+copy sysintf.obj objects
+del sysintf.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs parse.c
+copy parse.obj objects
+del parse.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs getinp.c
+copy getinp.obj objects
+del getinp.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs quit.c
+copy quit.obj objects
+del quit.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs state.c
+copy state.obj objects
+del state.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs dmdump.c
+copy dmdump.obj objects
+del dmdump.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs macparse.c
+copy macparse.obj objects
+del macparse.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs rulparse.c
+copy rulparse.obj objects
+del rulparse.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs percent.c
+copy percent.obj objects
+del percent.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs function.c
+copy function.obj objects
+del function.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\ruletab.c
+copy ruletab.obj objects
+del ruletab.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\dirbrk.c
+copy dirbrk.obj objects
+del dirbrk.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\runargv.c
+copy runargv.obj objects
+del runargv.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\arlib.c
+copy arlib.obj objects
+del arlib.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\dchdir.c
+copy dchdir.obj objects
+del dchdir.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\switchar.c
+copy switchar.obj objects
+del switchar.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\rmprq.c
+copy rmprq.obj objects
+del rmprq.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\tee.c
+copy tee.obj objects
+del tee.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\find.c
+copy find.obj objects
+del find.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\dirlib.c
+copy dirlib.obj objects
+del dirlib.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\dstrlwr.c
+copy dstrlwr.obj objects
+del dstrlwr.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs unix\dcache.c
+copy dcache.obj objects
+del dcache.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\microsft\tempnam.c
+copy tempnam.obj objects
+del tempnam.obj
+link /stack:4096/exe/packc/batch @msdos\microsft\msc60\obj.rsp,dmake.exe,NUL.MAP;
+copy msdos\microsft\msc60\template.mk startup\config.mk
diff --git a/dmake/msdos/microsft/msc60/mkswp.bat b/dmake/msdos/microsft/msc60/mkswp.bat
new file mode 100755
index 000000000000..6b9ed76a5085
--- /dev/null
+++ b/dmake/msdos/microsft/msc60/mkswp.bat
@@ -0,0 +1,104 @@
+md objects
+masm -t -mx -Dmlarge msdos\exec.asm,,,;
+mv exec.obj objects
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs infer.c
+copy infer.obj objects
+del infer.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs make.c
+copy make.obj objects
+del make.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs stat.c
+copy stat.obj objects
+del stat.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs expand.c
+copy expand.obj objects
+del expand.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs dmstring.c
+copy dmstring.obj objects
+del dmstring.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs hash.c
+copy hash.obj objects
+del hash.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs dag.c
+copy dag.obj objects
+del dag.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs dmake.c
+copy dmake.obj objects
+del dmake.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs path.c
+copy path.obj objects
+del path.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs imacs.c
+copy imacs.obj objects
+del imacs.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs sysintf.c
+copy sysintf.obj objects
+del sysintf.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs parse.c
+copy parse.obj objects
+del parse.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs getinp.c
+copy getinp.obj objects
+del getinp.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs quit.c
+copy quit.obj objects
+del quit.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs state.c
+copy state.obj objects
+del state.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs dmdump.c
+copy dmdump.obj objects
+del dmdump.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs macparse.c
+copy macparse.obj objects
+del macparse.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs rulparse.c
+copy rulparse.obj objects
+del rulparse.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs percent.c
+copy percent.obj objects
+del percent.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs function.c
+copy function.obj objects
+del function.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\ruletab.c
+copy ruletab.obj objects
+del ruletab.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\dirbrk.c
+copy dirbrk.obj objects
+del dirbrk.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\runargv.c
+copy runargv.obj objects
+del runargv.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\arlib.c
+copy arlib.obj objects
+del arlib.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\dchdir.c
+copy dchdir.obj objects
+del dchdir.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\switchar.c
+copy switchar.obj objects
+del switchar.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\rmprq.c
+copy rmprq.obj objects
+del rmprq.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\spawn.c
+copy spawn.obj objects
+del spawn.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\find.c
+copy find.obj objects
+del find.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\dirlib.c
+copy dirlib.obj objects
+del dirlib.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\dstrlwr.c
+copy dstrlwr.obj objects
+del dstrlwr.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs unix\dcache.c
+copy dcache.obj objects
+del dcache.obj
+cl -c -I. -Imsdos -Imsdos\microsft -AL -nologo -Imsdos\microsft\msc60 -D_MSC_VER=600 -Osecgl -Gs msdos\microsft\tempnam.c
+copy tempnam.obj objects
+del tempnam.obj
+link /stack:4096/exe/packc/batch @msdos\microsft\msc60\objswp.rsp,dmake.exe,NUL.MAP;
+copy msdos\microsft\msc60\template.mk startup\config.mk
diff --git a/dmake/msdos/microsft/msc60/obj.rsp b/dmake/msdos/microsft/msc60/obj.rsp
new file mode 100644
index 000000000000..8f79a32754c9
--- /dev/null
+++ b/dmake/msdos/microsft/msc60/obj.rsp
@@ -0,0 +1,33 @@
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dirbrk.obj+
+objects\runargv.obj+
+objects\arlib.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\rmprq.obj+
+objects\tee.obj+
+objects\find.obj+
+objects\dirlib.obj+
+objects\dstrlwr.obj+
+objects\dcache.obj+
+objects\tempnam.obj
diff --git a/dmake/msdos/microsft/msc60/objswp.rsp b/dmake/msdos/microsft/msc60/objswp.rsp
new file mode 100644
index 000000000000..54524124d236
--- /dev/null
+++ b/dmake/msdos/microsft/msc60/objswp.rsp
@@ -0,0 +1,34 @@
+objects\exec.obj+
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dirbrk.obj+
+objects\runargv.obj+
+objects\arlib.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\rmprq.obj+
+objects\spawn.obj+
+objects\find.obj+
+objects\dirlib.obj+
+objects\dstrlwr.obj+
+objects\dcache.obj+
+objects\tempnam.obj
diff --git a/dmake/msdos/microsft/msc60/public.h b/dmake/msdos/microsft/msc60/public.h
new file mode 100644
index 000000000000..3130d161c24e
--- /dev/null
+++ b/dmake/msdos/microsft/msc60/public.h
@@ -0,0 +1,169 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:29 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+int If_root_path ANSI((char *));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+void Clean_up_processes ANSI(());
+int Wait_for_child ANSI((int, int));
+time_t seek_arch ANSI((char*, char*));
+int touch_arch ANSI((char*, char*));
+int dchdir ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int spawnvpe ANSI((int, char *, char **, char **));
+void Hook_std_writes ANSI((char *));
+void dstrlwr ANSI((char *, char *));
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/msdos/microsft/msc60/template.mk b/dmake/msdos/microsft/msc60/template.mk
new file mode 100644
index 000000000000..a147c694c5f7
--- /dev/null
+++ b/dmake/msdos/microsft/msc60/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= msdos
+ OSRELEASE *:= microsft
+ OSENVIRONMENT *:= msc60
diff --git a/dmake/msdos/microsft/optoff.h b/dmake/msdos/microsft/optoff.h
new file mode 100644
index 000000000000..b2426a1259ba
--- /dev/null
+++ b/dmake/msdos/microsft/optoff.h
@@ -0,0 +1,27 @@
+/* RCS $Id: optoff.h,v 1.1.1.1 2000-09-22 15:33:29 hr Exp $
+--
+-- SYNOPSIS
+-- Turn off microsoft loop optimization.
+--
+-- DESCRIPTION
+-- This is broken in some pre 600 compilers so just turn it off.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+#if _MSC_VER < 600
+# pragma loop_opt(off)
+#endif
diff --git a/dmake/msdos/microsft/tempnam.c b/dmake/msdos/microsft/tempnam.c
new file mode 100644
index 000000000000..1a105c6b0f3a
--- /dev/null
+++ b/dmake/msdos/microsft/tempnam.c
@@ -0,0 +1,110 @@
+/* RCS $Id: tempnam.c,v 1.1.1.1 2000-09-22 15:33:29 hr Exp $
+--
+-- SYNOPSIS
+-- tempnam
+--
+-- DESCRIPTION
+-- temp file name generation routines.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/*LINTLIBRARY*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dos.h>
+
+#if defined(max)
+# undef max
+#endif
+#define max(A,B) (((A)<(B))?(B):(A))
+
+extern char *mktemp();
+extern int access();
+int d_access();
+
+/* MSC stdio.h defines P_tmpdir, so let's undo it here */
+/* Under DOS leave the default tmpdir pointing here! */
+#ifdef P_tmpdir
+#undef P_tmpdir
+#endif
+static char *P_tmpdir = "";
+
+char *
+tempnam(dir, prefix)
+char *dir; /* use this directory please (if non-NULL) */
+char *prefix; /* use this (if non-NULL) as filename prefix */
+{
+ static int count = 0;
+ register char *p, *q, *tmpdir;
+ int tl=0, dl=0, pl;
+ char buf[30];
+
+ pl = strlen(P_tmpdir);
+
+ if( (tmpdir = getenv("TMPDIR")) != NULL ) tl = strlen(tmpdir);
+ else if( (tmpdir = getenv("TMP")) != NULL ) tl = strlen(tmpdir);
+ if( dir != NULL ) dl = strlen(dir);
+
+ if( (p = malloc((unsigned)(max(max(dl,tl),pl)+13))) == NULL )
+ return(NULL);
+
+ *p = '\0';
+
+ if( (tl == 0) || (d_access( strcpy(p, tmpdir), 0) != 0) )
+ if( (dl == 0) || (d_access( strcpy(p, dir), 0) != 0) )
+ if( d_access( strcpy(p, P_tmpdir), 0) != 0 )
+ if( !prefix )
+ prefix = "tp";
+
+ if(prefix)
+ {
+ *(p+strlen(p)+2) = '\0';
+ (void)strncat(p, prefix, 2);
+ }
+
+ sprintf( buf, "%08x", _psp );
+ buf[6]='\0';
+ (void)strcat(p, buf );
+ sprintf( buf, "%04d", count++ );
+ q=p+strlen(p)-6;
+ *q++ = buf[0]; *q++ = buf[1];
+ *q++ = buf[2]; *q++ = buf[3];
+
+ if( (q = strrchr(p,'.')) != NULL ) *q = '\0';
+
+ return(p);
+}
+
+
+
+d_access( name, flag )
+char *name;
+int flag;
+{
+ extern char *DirSepStr;
+ char *p;
+ int r;
+
+ if( name == NULL || !*name ) return(1); /* NULL dir means current dir */
+ r = access( name, flag );
+ p = name+strlen(name)-1;
+ if(*p != '/' && *p != '\\') strcat( p, DirSepStr );
+
+ return( r );
+}
diff --git a/dmake/msdos/rmprq.c b/dmake/msdos/rmprq.c
new file mode 100644
index 000000000000..f2194bced053
--- /dev/null
+++ b/dmake/msdos/rmprq.c
@@ -0,0 +1,38 @@
+/* RCS $Id: rmprq.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Remove prerequisites code.
+--
+-- DESCRIPTION
+-- This code is different for DOS and for UNIX and parallel make
+-- architectures since the parallel case requires the rm's to be
+-- run in parallel, whereas DOS guarantees to run them sequentially.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+PUBLIC void
+Remove_prq( tcp )
+CELLPTR tcp;
+{
+ tcp->ce_flag &= ~(F_MADE|F_VISITED);
+ tcp->ce_time = 0L;
+
+ Make( tcp, tcp );
+}
diff --git a/dmake/msdos/ruletab.c b/dmake/msdos/ruletab.c
new file mode 100644
index 000000000000..6d9d69f348a1
--- /dev/null
+++ b/dmake/msdos/ruletab.c
@@ -0,0 +1,45 @@
+/* RCS $Id: ruletab.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Default initial configuration of dmake.
+--
+-- DESCRIPTION
+-- Define here the initial set of rules that are defined before
+-- dmake performs any processing.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* These are control macros for dmake that MUST be defined at some point
+ * if they are NOT dmake will not work! These are default definitions. They
+ * may be overridden inside the .STARTUP makefile, they are here
+ * strictly so that dmake can parse the STARTUP makefile */
+
+#include <stdio.h>
+
+static char *_rules[] = {
+ "MAXLINELENGTH := 2046",
+ "MAXPROCESSLIMIT := 1",
+ "MAXPROCESS := 1",
+ ".IMPORT .IGNORE: ROOTDIR",
+ ".MAKEFILES : makefile.mk makefile",
+ ".SOURCE : .NULL",
+#include "startup.h"
+ (char *)NULL };
+
+char **Rule_tab = _rules; /* for sundry reasons in Get_environment() */
+
diff --git a/dmake/msdos/runargv.c b/dmake/msdos/runargv.c
new file mode 100644
index 000000000000..cefd5d9944b2
--- /dev/null
+++ b/dmake/msdos/runargv.c
@@ -0,0 +1,132 @@
+/* RCS $Id: runargv.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Run a sub process.
+--
+-- DESCRIPTION
+-- Use spawn to run a subprocess.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <process.h>
+#include <errno.h>
+#include "extern.h"
+#include "sysintf.h"
+
+static int _abort_flg = FALSE;
+static void _add_child ANSI((CELLPTR, int));
+static void _finished_child ANSI((int));
+
+PUBLIC int
+runargv(target, ignore, group, last, shell, cmd)
+CELLPTR target;
+int ignore;
+int group;
+int last;
+int shell;
+char *cmd;
+{
+#if ! defined(_MSC_VER)
+#if defined(__BORLANDC__) && __BORLANDC__ >= 0x500
+ extern char ** _RTLENTRY _EXPDATA environ;
+#else
+ extern char **environ;
+#endif
+#endif
+ int status;
+ char **argv;
+
+ _add_child(target, ignore);
+ /* return immediately for noop command */
+ if (strncmp(cmd, "noop", 4) == 0 && (cmd[4] == ' ' || cmd[4] == '\0')) {
+ status = 0;
+ }
+ else {
+ argv = Pack_argv( group, shell, cmd );
+
+ if ( strcmp(argv[0],"echo") == 0 ) {
+ int i;
+ int first = 1;
+ int nl = 1;
+
+ if (strcmp(argv[1],"-n") == 0) nl--;
+
+ for (i=2-nl;argv[i]; i++) {
+ if (!first) putchar(' ');
+ printf("%s", argv[i]);
+ }
+ if (nl) printf("\n");
+ fflush(stdout);
+ status = 0;
+ }
+ else {
+ status = spawnvpe(P_WAIT, *argv, argv, environ);
+ }
+ }
+
+ if( status == -1 ) Error("%s: %s", argv[0], strerror(errno));
+ _finished_child(status);
+ if( last && !Doing_bang ) Update_time_stamp( target );
+
+ return( 0 );
+}
+
+
+PUBLIC void
+Clean_up_processes()
+{
+ _abort_flg = TRUE;
+ _finished_child(-1);
+}
+
+
+PUBLIC int
+Wait_for_child( abort_flg, pid )
+int abort_flg;
+int pid;
+{
+ return(1);
+}
+
+
+static int _valid = -1;
+static CELLPTR _tg;
+static int _ignore;
+
+static void
+_add_child( target, ignore )
+CELLPTR target;
+int ignore;
+{
+ _tg = target;
+ _ignore = ignore;
+ _valid = 0;
+
+ Current_target = NIL(CELL);
+}
+
+
+static void
+_finished_child(status)
+int status;
+{
+ if( _valid == -1 ) return;
+ Unlink_temp_files( _tg );
+ _valid = -1;
+ Handle_result( status, _ignore, _abort_flg, _tg );
+}
diff --git a/dmake/msdos/spawn.c b/dmake/msdos/spawn.c
new file mode 100644
index 000000000000..e62d936ee567
--- /dev/null
+++ b/dmake/msdos/spawn.c
@@ -0,0 +1,414 @@
+/* RCS $Id: spawn.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Spawnvpe code to emulate spawnvpe call common to DOS compilers.
+--
+-- DESCRIPTION
+-- This implementation is further integrated into dmake in that it
+-- determines the program to execute and if it's extension is either
+-- .bat or .ksh it executes it using the appropriate shell based on the
+-- setting of .MKSARGS. If .MKSARGS is set then in addition
+-- to the command tail getting built the arguments are also passed in the
+-- environment pursuant to the published MKS argument passing conventions.
+-- If the variable Swap_on_exec is set and the DOS OS supports it
+-- then the dmake executable image is swapped to secondary storage prior
+-- to running the child process. This is requested by setting the
+-- appropriate flag in the call to exec.
+--
+-- This and the exec.asm routine are derived from work that was supplied
+-- to me by Kent Williams (williams@umaxc.weeg.uiowa.edu) and by
+-- Len Reed, (..!gatech!holos0!lbr or holos0!lbr@gatech.edu., Holos
+-- Software, Inc., Tucker, Ga.). I sincerely acknowledge their help since
+-- their Turbo C, and MSC 6.0 code lead directly to this combined
+-- swapping exec that hopefully works with either compiler in all memory
+-- models.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(_MSC_VER) && _MSC_VER >= 600
+ /* Ignore the MSC 6.0 library's "const"-riddled prototype
+ for spawnvpe.
+ */
+# define spawnvpe _ignore_msc_spawnvpe
+# include <process.h>
+# undef spawnvpe
+ int spawnvpe(int, char *, char **, char **);
+#else
+# include <process.h>
+#endif
+
+#include <dos.h>
+#include <errno.h>
+#include <string.h>
+#include <alloc.h>
+#include <fcntl.h>
+#include "extern.h"
+#include "dosdta.h"
+#include "exec.h"
+#include "sysintf.h"
+
+extern int Interrupted;
+
+/* variables and functions local to this file */
+static char *_findexec ANSI((char *, int *));
+static char **_getpath ANSI(());
+static char far *_dos_alloc ANSI((uint16));
+
+static uint16 _swap_mask;
+static int _mks_args;
+static char dot_com[] = ".COM",
+ dot_exe[] = ".EXE",
+ dot_bat[] = ".BAT",
+ dot_ksh[] = ".KSH";
+
+/* Kinds of executables */
+#define SCR 1
+#define COM 2
+#define EXE 4
+#define ALL (SCR|COM|EXE)
+
+/* How to make a long pointer */
+#define CF(x) (char far *)x
+
+/* Make sure we know how to get a segment out of a long pointer */
+#ifndef FP_SEG
+#define FP_SEG(fp) ((unsigned)((unsigned long)(fp) >> 16))
+#endif
+
+
+PUBLIC int
+spawnvpe(mode, program, av, ep)/*
+=================================
+ Spawn a process using an environment and a vector of arguments.
+ The code computes a new environment, puts the MKS arguments into
+ it if need be, and calls the appropriate routines to search the
+ path and to invoke the process. */
+int mode;
+char *program;
+char **av;
+char **ep;
+{
+ char pwd[PATH_MAX+1];
+ char **envp = ep; /* Cause we are going to mess with it. */
+ char **argv = av; /* Same with this one. */
+ char cmdtail[129];
+ char far *environment;
+ char *tail;
+ char *swptmp;
+ unsigned int envsize;
+ unsigned int cmdsize;
+ int cmdtailen;
+ int i;
+ int doswap;
+
+ /* First check to see if we can find the program to execute this way we
+ * don't alloc the environment and other such stuff prior to figuring out
+ * we don't know how to run the program. */
+find_program:
+ if((program = _findexec(program, &i)) == NIL(char)) {
+ errno = ENOENT;
+ return( -1 );
+ }
+
+ /* i is set to TRUE in _findexec if the exec is a shell
+ * script (either .BAT or .KSH file), returns FALSE for all others. */
+ if( i && !Packed_shell ) {
+ /* Restore the spaces into the command line that were erased by
+ * the previous call to Pack_argv. This enables us to repack the
+ * command as a shell command using Pack_argv again. */
+ for( i=0; argv[i] != NIL(char); i++ ) {
+ int x = strlen(argv[i]);
+ if( argv[i+1] != NIL(char) ) argv[i][x] = ' ';
+ }
+
+ argv = Pack_argv( FALSE, TRUE, *argv );
+
+ /* Go and find the program again, I hate goto's but it seems silly to
+ * use tail recursion here just for aesthetic purity. */
+ program = *argv;
+ goto find_program;
+ }
+
+ /* Compute size of *argv vector for passing as MKS style arguments */
+ cmdsize = strlen(*argv)+2;
+
+ /* So we have decided on a program to run, therefore pack the command tail
+ * and build the environment to pass to the exec code. This loop packs the
+ * DOS command tail, and computes the size of all arguments for the MKS
+ * argument passing convention. Note that we reserve one less byte in the
+ * command tail if we are not using MKS style argument passing.
+ *
+ * Make sure the command tail contains at leat a space. Some commands fail
+ * to work if the command tail is only a \r, STUPID DOS! */
+ cmdtailen = ((_mks_args = ((Glob_attr & A_MKSARGS) != 0)) != 0)?3:2;
+ tail = cmdtail+1;
+
+ if( argv[1] != NIL(char) )
+ for( i=1; argv[i] != NIL(char); i++ ) {
+ int arglen = strlen(argv[i]);
+
+ cmdsize += arglen+2; /* Compute all args size for MKS */
+
+ if( (cmdtailen += arglen+1) <= 128 ) {
+ register char *p = argv[i];
+ tail[-1] = ' '; /* put in the space */
+ while( *tail++ = *p++ ); /* put in the arg */
+ }
+ else if( !_mks_args ) {
+ errno = E2BIG; /* unless its MKS exit if arglist */
+ return(-1); /* is too long. */
+ }
+ }
+ else
+ *tail++ = ' ';
+
+ /* Finish the command tail set up, placing the length in the first byte,
+ * and the \r \n \0 at the end for DOS, MKS and us respectively. */
+ *cmdtail = tail-cmdtail-2;
+ tail[-1] = '\r';
+ if( _mks_args ) *tail++ = '\n';
+ *tail = '\0';
+
+ /* Compute size of environment, skipping any MKS arguments passed in our
+ * environment */
+ for(; *envp && **envp == '~'; envp++ );
+ for(i=0, envsize=_mks_args?cmdsize:1; envp[i] != NIL(char); i++ )
+ envsize += strlen(envp[i]) + 1;
+
+ /* Check the DOS version number here. If it is < 3.0 then we don't
+ * even want to think about executing the swapping code. Permanently
+ * set swap to 0. */
+ doswap = (_osmajor < 3) ? 0 : Swap_on_exec;
+
+ /* Set up temporary file for swapping */
+ swptmp = doswap?tempnam(NIL(char),"mk"):"";
+
+ /* Allocate an appropriate sized environment block and align it on a
+ * paragraph boundary. It will later get copied to an appropriately low
+ * place in the executable image so that when we swap out the environment
+ * is still present. Use
+ * _dos_alloc
+ * to allocate the environment segment. The segment is freed by the call
+ * to exec. */
+ environment = _dos_alloc( envsize = ((envsize+16)>>4) );
+ *environment = '\0';
+
+ /* First copy the arguments preceeded by ~ character if we are using
+ * MKS style argument passing */
+ if( _mks_args )
+ for(; *argv; argv++) {
+ register char *p = *argv;
+
+ *environment++ = '~';
+ while( *environment++ = *p++ ); /* Far dest, poss near ptr */
+ }
+
+ /* Now stick in the current evironment vectors. */
+ for(; *envp; envp++) {
+ register char *p = *envp;
+ while( *environment++ = *p++ ); /* Far dest, poss near ptr */
+ }
+
+ /* Clear the interrupted flag, and exec */
+ Interrupted = 0;
+
+ /* Preserve the current working directory accross a spawn call
+ * DOS is brain dead about this. This way we have some hope of cleaning
+ * up the swapping tempfiles after we return. */
+ strcpy(pwd,Get_current_dir());
+ i = exec(doswap,CF(program),CF(cmdtail),FP_SEG(environment),CF(swptmp));
+ Set_dir(pwd);
+
+ /* Now free the temporary file name */
+ if( doswap ) FREE(swptmp);
+
+ /* If swap was interrupted then quit properly from dmake. */
+ if( Interrupted ) Quit();
+
+ return(i);
+}
+
+
+PUBLIC void
+Hook_std_writes( file )
+char *file;
+{
+ if( file!= NIL(char) ) {
+ int mode = O_BINARY | O_WRONLY | O_CREAT | O_TRUNC;
+ int handle;
+
+ if (*file == '+') {
+ ++file; /* -F +file means append to file */
+ mode = O_BINARY | O_WRONLY | O_CREAT | O_APPEND;
+ }
+ handle = open(file, mode, S_IREAD | S_IWRITE);
+ if (handle < 0) {
+ Fatal( "Could not open -F file");
+ }
+ (void) lseek(handle, 0L, SEEK_END);
+ do_hook_std_writes(handle);
+ }
+ else
+ do_unhook_std_writes();
+}
+
+
+/*
+** _findexec finds executables on the path.
+** Note that it is pretty simple to add support for other executable types
+** shell scripts, etc.
+**
+** This follows the command.com behavior very closely.
+*/
+static char *
+_findexec( s, is_shell )/*
+==========================
+ Cloned closely from code provided by Kent Williams. Stripped his down to
+ a reduced search since dmake doesn't need to recompute the PATH vector
+ each time it does the search since it cannot alter the path vector once
+ it begins to make recipes. Also modified it to use findfirst and findnext
+ as provided for dirlib package that I got off the net. */
+char *s;
+int *is_shell;
+{
+ unsigned found_flags;
+ char **pathv = NIL(char *);
+ char *ext = NIL(char);
+ char *buf = NIL(char);
+ char *p[2];
+ char *dot_scr;
+ char *dot;
+
+ p[0] = ""; p[1] = NIL(char);
+ if( strchr("./\\", *s) || s[1] == ':' )
+ pathv = p;
+ else if( (pathv = _getpath()) == NIL(char *) )
+ return( NIL(char) );
+
+ /* Compute the extension we need if any. */
+ if( (dot = strrchr(s,'.')) != NIL(char) &&
+ dot > strrchr(s,'/') && dot > strrchr(s,'\\') )
+ ext = dot+1;
+
+ dot_scr = _mks_args ? dot_ksh : dot_bat;
+ *is_shell = FALSE;
+
+ for( found_flags = 0; *pathv && !found_flags; pathv++ ) {
+ DTA dta;
+
+ if( !ext ) {
+ char *name;
+ buf = Build_path( *pathv, name=DmStrJoin(s, ".???", -1, FALSE) );
+ FREE(name);
+ }
+ else
+ buf = Build_path( *pathv, s );
+
+ if( findfirst((char *)strupr(buf), &dta) != NIL(DTA) ) {
+ if( !ext ) {
+ char *dot;
+
+ /* search order is .com .exe (.ksh || .bat)
+ * there has to be a '.' */
+ do {
+ dot = strrchr(dta.name,'.');
+ if(0 == strcmp(dot,dot_com))
+ found_flags |= COM;
+ else if(0 == strcmp(dot,dot_exe))
+ found_flags |= EXE;
+ else if( 0 == strcmp(dot,dot_scr) )
+ found_flags |= SCR;
+ } while( found_flags != ALL && findnext(&dta) != NIL(DTA) );
+
+ if(found_flags & COM) ext = dot_com;
+ else if(found_flags & EXE) ext = dot_exe;
+ else if(found_flags & SCR) {
+ ext = dot_scr;
+ *is_shell = TRUE;
+ }
+
+ if( found_flags ) {
+ char *name;
+ buf = Build_path( *pathv, name=DmStrJoin(s,ext,-1,FALSE) );
+ FREE(name);
+ strupr(buf);
+ }
+ }
+ else
+ found_flags++;
+ }
+ }
+
+ return( found_flags ? buf : NIL(char) );
+}
+
+
+/*
+** getpath turns the DOS path into a char *vector, It is gotten and
+** transformed only once since dmake can't modify the value of PATH while
+** it is making targets.
+*/
+static char **
+_getpath()
+{
+ static char **dir = NIL(char *);
+ register char *p;
+
+ if( !dir ) {
+ register char *t;
+ int i;
+ char *semi = NIL(char);
+
+ if( (p = getenv("PATH")) == NIL(char) ) p = "";
+ for( i=1, t=p; *t; t++ ) if( *t == ';' ) i++;
+
+ TALLOC(dir, i+1, char *);
+ p = DmStrDup(p);
+
+ for( i=0; p; p = semi ? (semi+1):NIL(char),i++ ){
+ if( (semi = strchr(p,';')) != NIL(char) ) *semi = '\0';
+ dir[i] = p;
+ }
+ dir[i]=NIL(char);
+ }
+
+ return( dir );
+}
+
+
+static char far *
+_dos_alloc( size )/*
+====================
+ This routine allocates size paragraphs from DOS. It changes the memory
+ allocation strategy to allocate from the tail and then changes it back.
+ to using first fit. */
+uint16 size;
+{
+ union REGS r;
+
+ r.h.ah = 0x48;
+ r.x.bx = size;
+
+ intdos( &r, &r );
+ if( r.x.cflag ) No_ram();
+
+ return( (char far *) MK_FP(r.x.ax, 0) );
+}
diff --git a/dmake/msdos/startup.h b/dmake/msdos/startup.h
new file mode 100644
index 000000000000..22eeb863e809
--- /dev/null
+++ b/dmake/msdos/startup.h
@@ -0,0 +1,26 @@
+/* RCS $Id: startup.h,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Dmake startup header file definition.
+--
+-- DESCRIPTION
+-- Where we define the default value of MAKESTARTUP.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+"MAKESTARTUP := $(MAKECMD:d)startup/startup.mk",
diff --git a/dmake/msdos/switchar.c b/dmake/msdos/switchar.c
new file mode 100644
index 000000000000..8879a9ad7c44
--- /dev/null
+++ b/dmake/msdos/switchar.c
@@ -0,0 +1,55 @@
+/* RCS $Id: switchar.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- switch char query.
+--
+-- DESCRIPTION
+-- Get the current value of the command line switch char. Only useful
+-- in a DOS environment, otherwise we #define it to be '-'.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+#if defined(_MSC_VER)
+#include <stdlib.h>
+#endif
+#include <dos.h>
+#include <stdio.h>
+#include "stdmacs.h"
+
+getswitchar()/*
+===============
+ Try the environment first. If you don't find SWITCHAR there, then use
+ the DOS call. The call is undocumented, and doesn't work for DOS versions
+ 4.0 and up, so the check of the environment will fix that. */
+{
+#if defined(__MSDOS__) || defined(M_I86)
+ union REGS rg;
+ static char *_env_switchar = NIL(char);
+
+ if( _env_switchar != NIL(char) ||
+ (_env_switchar = (char *)getenv("SWITCHAR")) != NIL(char) )
+ return(*_env_switchar);
+
+ rg.h.ah = 0x37; /* switch char request */
+ rg.h.al = 0; /* get (not set) */
+
+ intdos(&rg, &rg);
+ return (rg.h.dl);
+#endif /* M_I86 */
+
+ return ('-');
+}
diff --git a/dmake/msdos/sysintf.h b/dmake/msdos/sysintf.h
new file mode 100644
index 000000000000..2a6d92a59329
--- /dev/null
+++ b/dmake/msdos/sysintf.h
@@ -0,0 +1,53 @@
+/* RCS $Id: sysintf.h,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Interfaces for sysintf.c
+--
+-- DESCRIPTION
+-- Abstractions of functions in sysintf.c
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+#define DMSTAT stat
+#define VOID_LCACHE(l,m)
+#define GETPID _psp
+#define DMSTRLWR(A,B) dstrlwr(A,B)
+
+extern char * tempnam();
+extern char * getcwd();
+
+/*
+** standard C items
+*/
+
+/*
+** DOS interface standard items
+*/
+#define chdir(p) dchdir(p)
+
+/*
+** make parameters
+*/
+#ifdef _POSIX_NAME_MAX
+#undef _POSIX_NAME_MAX
+#endif
+#define _POSIX_NAME_MAX 12
+
+#ifdef _POSIX_PATH_MAX
+#undef _POSIX_PATH_MAX
+#endif
+#define _POSIX_PATH_MAX 64
diff --git a/dmake/msdos/tee.c b/dmake/msdos/tee.c
new file mode 100644
index 000000000000..f2c8b5de6543
--- /dev/null
+++ b/dmake/msdos/tee.c
@@ -0,0 +1,31 @@
+/* RCS $Id: tee.c,v 1.1.1.1 2000-09-22 15:33:27 hr Exp $
+--
+-- SYNOPSIS
+-- Hook_std_writes() dummy call for non swapping MSDOS versions.
+--
+-- DESCRIPTION
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+PUBLIC void
+Hook_std_writes( file )
+char *file;
+{
+}
diff --git a/dmake/msdos/zortech/config.h b/dmake/msdos/zortech/config.h
new file mode 100644
index 000000000000..096498844fc9
--- /dev/null
+++ b/dmake/msdos/zortech/config.h
@@ -0,0 +1,52 @@
+/* RCS $Id: config.h,v 1.1.1.1 2000-09-22 15:33:29 hr Exp $
+--
+-- SYNOPSIS
+-- Configurarion include file.
+--
+-- DESCRIPTION
+-- There is one of these for each specific machine configuration.
+-- It can be used to further tweek the machine specific sources
+-- so that they compile.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* in sysintf.c: SIGQUIT is used, this is not defined in ZTC */
+#ifndef SIGQUIT
+# define SIGQUIT SIGTERM
+#endif
+
+/* in sysintf.c: tzset is not supported by ZTC */
+#define tzset()
+
+/* ZTC uses it's own swapping spawn. */
+#define spawnvpe(a,b,c,d) spawnvp(a,b,c)
+
+#ifndef CONST
+# define CONST const
+#endif
+
+#ifndef MSDOS
+# define MSDOS 1
+#endif
+
+extern unsigned _psp;
+
+/* a small problem with pointer to voids on some unix machines needs this */
+#define PVOID void *
+
+#include <io.h>
diff --git a/dmake/msdos/zortech/config.mk b/dmake/msdos/zortech/config.mk
new file mode 100644
index 000000000000..e947dc87620b
--- /dev/null
+++ b/dmake/msdos/zortech/config.mk
@@ -0,0 +1,73 @@
+# This is the ZTC DOS configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+TMPDIR :=
+.EXPORT : TMPDIR
+
+# Definition of macros for library, and C startup code.
+# Swapping for DOS versions is enabled by default. ZTC will automatically
+# perform swapping to XMS, EMS or disk by including _swapl.obj at link time.
+# To be most effective, _swapl.obj should be the first file linked so we
+# assign it to CSTARTUP if needed.
+.IF $(SWAP) == y
+ CSTARTUP = _swapl.obj
+.END
+
+# The following sources are required for ZTC
+# The tempnam supplied with ZTC doesn't handle a NULL dir.
+OSR_SRC = tempnam.c environ.c
+.SETDIR=$(osrdir) : $(OSR_SRC)
+
+SRC += $(OSR_SRC)
+.SOURCE.h : $(osrdir)
+
+# Local configuration modifications for CFLAGS
+# If you have a 286, you can use -2 or appropriate to get better code,
+# in that case uncomment the line below. (You can also simply set
+# it in the CL environment variable.)
+#CFLAGS += -2
+ASFLAGS += -t -mx $(S_$(MODEL))
+
+# Redefine this, it isn't needed!
+LDTAIL = ;
+
+# Debugging libraries
+DB_LDFLAGS += -g
+DB_LDLIBS +=
+
+# NO Debug ZTC flags:
+#
+
+CFLAGS += -I$(osrdir) $(C_$(MODEL))
+CFLAGS += -DM_I86=1 -DMSDOS
+CFLAGS += -b # use large compiler
+#CFLAGS += -w # no warnings
+CFLAGS += -mi # integer only
+CFLAGS += -p # no auto-prototyping
+NDB_CFLAGS += -o
+DB_CFLAGS += -g
+
+# Redefine rule for making our objects, we don't need mv
+%$O : %.c ;% $(CC) -c $(CFLAGS) -o$@ $<
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
+
+C_s =
+C_m = -mM
+C_c = -mC
+C_l = -mL
+
+S_s = -Dmsmall
+S_m = -Dmmedium
+S_c = -Dmcompact
+S_l = -Dmlarge
diff --git a/dmake/msdos/zortech/environ.c b/dmake/msdos/zortech/environ.c
new file mode 100644
index 000000000000..c76d9a4831a6
--- /dev/null
+++ b/dmake/msdos/zortech/environ.c
@@ -0,0 +1,59 @@
+/* RCS $Id: environ.c,v 1.1.1.1 2000-09-22 15:33:29 hr Exp $
+--
+-- SYNOPSIS
+-- environment routines.
+--
+-- DESCRIPTION
+-- Someone thought that Zortech needs this.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+/*LINTLIBRARY*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "alloc.h"
+
+/* ZTC++ doesn't have environ, so we have to create one. */
+
+extern char *_envptr;
+char **environ = { NULL };
+
+void
+make_env()
+{
+ int i;
+ char *cp;
+
+ for (i = 0, cp = _envptr; *cp; i++, cp += strlen(cp)+1)
+ ;
+
+ TALLOC(environ, i+1, char*);
+
+ for (i = 0, cp = _envptr; *cp; i++, cp += strlen(cp)+1)
+ environ[i] = cp;
+
+ return;
+}
+
+void
+free_env()
+{
+ FREE(environ);
+
+ return;
+}
diff --git a/dmake/msdos/zortech/lib.rsp b/dmake/msdos/zortech/lib.rsp
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/dmake/msdos/zortech/lib.rsp
@@ -0,0 +1 @@
+
diff --git a/dmake/msdos/zortech/libswp.rsp b/dmake/msdos/zortech/libswp.rsp
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/dmake/msdos/zortech/libswp.rsp
@@ -0,0 +1 @@
+
diff --git a/dmake/msdos/zortech/mkswp.bat b/dmake/msdos/zortech/mkswp.bat
new file mode 100755
index 000000000000..60c12d37217e
--- /dev/null
+++ b/dmake/msdos/zortech/mkswp.bat
@@ -0,0 +1,36 @@
+md objects
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\infer.obj infer.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\make.obj make.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\stat.obj stat.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\expand.obj expand.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dmstring.obj dmstring.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\hash.obj hash.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dag.obj dag.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dmake.obj dmake.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\path.obj path.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\imacs.obj imacs.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\sysintf.obj sysintf.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\parse.obj parse.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\getinp.obj getinp.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\quit.obj quit.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\state.obj state.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dmdump.obj dmdump.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\macparse.obj macparse.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\rulparse.obj rulparse.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\percent.obj percent.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\function.obj function.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\ruletab.obj msdos\ruletab.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dirbrk.obj msdos\dirbrk.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\runargv.obj msdos\runargv.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\arlib.obj msdos\arlib.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dchdir.obj msdos\dchdir.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\switchar.obj msdos\switchar.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\rmprq.obj msdos\rmprq.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\tee.obj msdos\tee.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\find.obj msdos\find.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dirlib.obj msdos\dirlib.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dstrlwr.obj msdos\dstrlwr.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dcache.obj unix\dcache.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\tempnam.obj msdos\zortech\tempnam.c
+ztc -c -I. -Imsdos -Imsdos\zortech -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\environ.obj msdos\zortech\environ.c
+blink @msdos\zortech\objswp.rsp,dmake.exe,NUL.MAP;
diff --git a/dmake/msdos/zortech/obj.rsp b/dmake/msdos/zortech/obj.rsp
new file mode 100644
index 000000000000..c97a42f9f0aa
--- /dev/null
+++ b/dmake/msdos/zortech/obj.rsp
@@ -0,0 +1,34 @@
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dirbrk.obj+
+objects\runargv.obj+
+objects\arlib.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\rmprq.obj+
+objects\tee.obj+
+objects\find.obj+
+objects\dirlib.obj+
+objects\dstrlwr.obj+
+objects\dcache.obj+
+objects\tempnam.obj+
+objects\environ.obj
diff --git a/dmake/msdos/zortech/objswp.rsp b/dmake/msdos/zortech/objswp.rsp
new file mode 100644
index 000000000000..60a33c4eb523
--- /dev/null
+++ b/dmake/msdos/zortech/objswp.rsp
@@ -0,0 +1,35 @@
+_swapl.obj+
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dirbrk.obj+
+objects\runargv.obj+
+objects\arlib.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\rmprq.obj+
+objects\tee.obj+
+objects\find.obj+
+objects\dirlib.obj+
+objects\dstrlwr.obj+
+objects\dcache.obj+
+objects\tempnam.obj+
+objects\environ.obj
diff --git a/dmake/msdos/zortech/public.h b/dmake/msdos/zortech/public.h
new file mode 100644
index 000000000000..89c586b44e5a
--- /dev/null
+++ b/dmake/msdos/zortech/public.h
@@ -0,0 +1,168 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:29 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+int If_root_path ANSI((char *));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+void Clean_up_processes ANSI(());
+int Wait_for_child ANSI((int, int));
+time_t seek_arch ANSI((char*, char*));
+int touch_arch ANSI((char*, char*));
+int dchdir ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+void Hook_std_writes ANSI((char *));
+void dstrlwr ANSI((char *, char *));
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/msdos/zortech/startup.mk b/dmake/msdos/zortech/startup.mk
new file mode 100644
index 000000000000..3c167a02e400
--- /dev/null
+++ b/dmake/msdos/zortech/startup.mk
@@ -0,0 +1,153 @@
+# MSDOS DMAKE startup file. Customize to suit your needs.
+# Assumes MKS toolkit for the tool commands, and Zortech C. Change as req'd.
+# See the documentation for a description of internally defined macros.
+#
+# Disable warnings for macros redefined here that were given
+# on the command line.
+__.SILENT !:= $(.SILENT)
+.SILENT !:= yes
+
+# Configuration parameters for DMAKE startup.mk file
+# Set these to NON-NULL if you wish to turn the parameter on.
+_HAVE_RCS := yes # yes => RCS is installed.
+_HAVE_SCCS := # yes => SCCS is installed.
+
+# Applicable suffix definitions
+A := .lib # Libraries
+E := .exe # Executables
+F := .for # Fortran
+O := .obj # Objects
+P := .pas # Pascal
+S := .asm # Assembler sources
+V := # RCS suffix
+
+# See if these are defined
+TMPDIR := $(ROOTDIR)/tmp
+.IMPORT .IGNORE : TMPDIR SHELL COMSPEC
+
+# Recipe execution configurations
+# First set SHELL, If it is not defined, use COMSPEC, otherwise
+# it is assumed to be MKS Korn SHELL.
+.IF $(SHELL) == $(NULL)
+.IF $(COMSPEC) == $(NULL)
+ SHELL := $(ROOTDIR)/bin/sh$E
+.ELSE
+ SHELL := $(COMSPEC)
+.END
+.END
+GROUPSHELL := $(SHELL)
+
+# Now set remaining arguments depending on which SHELL we
+# are going to use. COMSPEC (assumed to be command.com) or
+# MKS Korn Shell.
+.IF $(SHELL)==$(COMSPEC)
+ SHELLFLAGS := $(SWITCHAR)c
+ GROUPFLAGS := $(SHELLFLAGS)
+ SHELLMETAS := *"?<>
+ GROUPSUFFIX := .bat
+ DIRSEPSTR := \\\
+ DIVFILE = $(TMPFILE:s,/,\)
+.ELSE
+ SHELLFLAGS := -c
+ GROUPFLAGS :=
+ SHELLMETAS := *"?<>|()&][$$\#`'
+ GROUPSUFFIX := .ksh
+ .MKSARGS := yes
+ DIVFILE = $(TMPFILE:s,/,${DIVSEP_shell_${USESHELL}})
+ DIVSEP_shell_yes := \\\
+ DIVSEP_shell_no := \\
+.END
+
+# Standard C-language command names and flags
+ CC := ztc # C-compiler and flags
+ CFLAGS +=
+
+ AS := masm # Assembler and flags
+ ASFLAGS +=
+
+ LD = blink # Loader and flags
+ LDFLAGS +=
+ LDLIBS =
+
+# Definition of $(MAKE) macro for recursive makes.
+ MAKE = $(MAKECMD) -S $(MFLAGS)
+
+# Language and Parser generation Tools and their flags
+ YACC := yacc # standard yacc
+ YFLAGS +=
+ YTAB := ytab # yacc output files name stem.
+
+ LEX := lex # standard lex
+ LFLAGS +=
+ LEXYY := lex_yy # lex output file
+
+# Other Compilers, Tools and their flags
+ PC := any_pc # pascal compiler
+ RC := anyf77 # ratfor compiler
+ FC := anyf77 # fortran compiler
+
+ CO := co # check out for RCS
+ COFLAGS += -q
+
+ AR := ar # archiver
+ ARFLAGS+= ruv
+
+ RM := rm # remove a file command
+ RMFLAGS +=
+
+# Implicit generation rules for making inferences.
+# We don't provide .yr or .ye rules here. They're obsolete.
+# Rules for making *$O
+ %$O : %.c ; $(CC) $(CFLAGS) -c $<
+ %$O : %.cpp ; $(CC) $(CFLAGS) -c $<
+ %$O : %$P ; $(PC) $(PFLAGS) -c $<
+ %$O : %$S ; $(AS) $(ASFLAGS) $(<:s,/,\);
+ %$O : %.cl ; class -c $<
+ %$O :| %.e %.r %.F %$F ; $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $<
+
+# Executables
+ %$E : %$O ; $(CC) $(LDFLAGS) -o$@ $< $(LDLIBS)
+
+# lex and yacc rules
+ %.c : %.y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@
+ %.c : %.l ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@
+
+# RCS support
+.IF $(_HAVE_RCS)
+ % : $$(@:d)RCS$$(DIRSEPSTR)$$(@:f)$V;- $(CO) $(COFLAGS) $@
+ .NOINFER : $$(@:d)RCS$$(DIRSEPSTR)$$(@:f)$V
+.END
+
+# SCCS support
+.IF $(_HAVE_SCCS)
+ % : s.% ; get $<
+ .NOINFER : s.%
+.END
+
+# Recipe to make archive files.
+%$A .SWAP .GROUP :
+ $(AR) $(ARFLAGS) $@ $?
+ $(RM) $(RMFLAGS) $?
+
+# DMAKE uses this recipe to remove intermediate targets
+.REMOVE :; $(RM) -f $<
+
+# AUGMAKE extensions for SYSV compatibility
+"@B" = $(@:b)
+"@D" = $(@:d)
+"@F" = $(@:f)
+"*B" = $(*:b)
+"*D" = $(*:d)
+"*F" = $(*:f)
+"<B" = $(<:b)
+"<D" = $(<:d)
+"<F" = $(<:f)
+"?B" = $(?:b)
+"?F" = $(?:f)
+"?D" = $(?:d)
+
+# Turn warnings back to previous setting.
+.SILENT !:= $(__.SILENT)
+
+# Local init file if any, gets parsed before user makefile
+.INCLUDE .IGNORE: "_startup.mk"
diff --git a/dmake/msdos/zortech/tempnam.c b/dmake/msdos/zortech/tempnam.c
new file mode 100644
index 000000000000..91ce19c490ad
--- /dev/null
+++ b/dmake/msdos/zortech/tempnam.c
@@ -0,0 +1,106 @@
+/* RCS $Id: tempnam.c,v 1.1.1.1 2000-09-22 15:33:29 hr Exp $
+--
+-- SYNOPSIS
+-- temname
+--
+-- DESCRIPTION
+-- temp file name generation code.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+/*LINTLIBRARY*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dos.h>
+
+#if defined(max)
+# undef max
+#endif
+#define max(A,B) (((A)<(B))?(B):(A))
+
+extern char *mktemp();
+extern int access();
+int d_access();
+
+/* Zortech C stdio.h doesn't define P_tmpdir, so let's do it here */
+/* Under DOS leave the default tmpdir pointing here! */
+static char *P_tmpdir = "";
+
+char *
+tempnam(dir, prefix)
+const char *dir; /* use this directory please (if non-NULL) */
+const char *prefix; /* use this (if non-NULL) as filename prefix */
+{
+ static int count = 0;
+ register char *p, *q, *tmpdir;
+ int tl=0, dl=0, pl;
+ char buf[30];
+
+ pl = strlen(P_tmpdir);
+
+ if( (tmpdir = getenv("TMPDIR")) != NULL ) tl = strlen(tmpdir);
+ else if( (tmpdir = getenv("TMP")) != NULL ) tl = strlen(tmpdir);
+ if( dir != NULL ) dl = strlen(dir);
+
+ if( (p = malloc((unsigned)(max(max(dl,tl),pl)+13))) == NULL )
+ return(NULL);
+
+ *p = '\0';
+
+ if( (tl == 0) || (d_access( strcpy(p, tmpdir), 0) != 0) )
+ if( (dl == 0) || (d_access( strcpy(p, dir), 0) != 0) )
+ if( d_access( strcpy(p, P_tmpdir), 0) != 0 )
+ if( !prefix )
+ prefix = "tp";
+
+ if(prefix)
+ {
+ *(p+strlen(p)+2) = '\0';
+ (void)strncat(p, prefix, 2);
+ }
+
+ sprintf( buf, "%08x", _psp );
+ buf[6]='\0';
+ (void)strcat(p, buf );
+ sprintf( buf, "%04d", count++ );
+ q=p+strlen(p)-6;
+ *q++ = buf[0]; *q++ = buf[1];
+ *q++ = buf[2]; *q++ = buf[3];
+
+ if( (q = strrchr(p,'.')) != NULL ) *q = '\0';
+
+ return(p);
+}
+
+
+
+d_access( name, flag )
+char *name;
+int flag;
+{
+ extern char *DirSepStr;
+ char *p;
+ int r;
+
+ if( name == NULL || !*name ) return(1); /* NULL dir means current dir */
+ r = access( name, flag );
+ p = name+strlen(name)-1;
+ if(*p != '/' && *p != '\\') strcat( p, DirSepStr );
+
+ return( r );
+}
diff --git a/dmake/os2/config.mk b/dmake/os2/config.mk
new file mode 100644
index 000000000000..5e2b7689bd82
--- /dev/null
+++ b/dmake/os2/config.mk
@@ -0,0 +1,54 @@
+# This is an OS specific configuration file
+# It assumes that OBJDIR, TARGET and DEBUG are previously defined.
+# It defines CFLAGS, LDARGS, CPPFLAGS, STARTUPFILE, LDOBJS
+# It augments SRC, OBJDIR, TARGET, CFLAGS, LDLIBS
+#
+OSRELEASE *= ibm
+- := $(SWITCHAR)
+
+# Memory model to compile for
+# set to s - small, m - medium, c - compact, l - large
+# Use only large model now.
+MODEL = l
+
+STARTUPFILE = $(OS)/startup.mk
+
+CPPFLAGS = $(CFLAGS)
+LDOBJS = $(CSTARTUP) $(OBJDIR)/{$(<:f)}
+LDARGS = $(LDHEAD) @$(LDTMPOBJ),$(TARGET),NUL.MAP,,$(LDTAIL)
+LDTAIL = $(_libs)$(LDFLAGS:s/ //)
+_libs = $(!null,$(LDLIBS) ,@$(LDTMPLIB))
+LDTMPOBJ = $(mktmp,,$(DIVFILE) $(LDOBJS:s,/,\\,:t"+\n")\n)
+LDTMPLIB = $(mktmp,,$(DIVFILE) $(LDLIBS)\n)
+
+# Debug flags
+DB_CFLAGS = -DDBUG
+DB_LDFLAGS =
+DB_LDLIBS =
+
+# NO Debug flags
+NDB_CFLAGS =
+NDB_LDFLAGS =
+NDB_LDLIBS =
+
+# Local configuration modifications for CFLAGS.
+CFLAGS += $-I$(OS)
+
+# OS2 does not have a swap version. The operating system will
+# handle all swapping.
+# To save copying unchanged files in from elsewhere, I shall use them in situ.
+OS_SRC += ruletab.c dchdir.c switchar.c
+DOS_SRC += dirbrk.c arlib.c dstrlwr.c runargv.c rmprq.c
+
+SRC += $(OS_SRC) $(DOS_SRC)
+.SETDIR=$(OS) : $(ASRC) $(OS_SRC)
+.SETDIR=msdos : $(DOS_SRC)
+
+# Set source dirs so that we can find files named in this
+# config file.
+.SOURCE.h : $(OS)
+
+# See if we modify anything in the lower levels.
+.IF $(OSRELEASE) != $(NULL)
+ .INCLUDE .IGNORE : $(OS)$(DIRSEPSTR)$(OSRELEASE)$(DIRSEPSTR)config.mk
+.END
diff --git a/dmake/os2/dchdir.c b/dmake/os2/dchdir.c
new file mode 100644
index 000000000000..6244c630d2a6
--- /dev/null
+++ b/dmake/os2/dchdir.c
@@ -0,0 +1,41 @@
+/* RCS $Id: dchdir.c,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+--
+-- SYNOPSIS
+-- Change directory.
+--
+-- DESCRIPTION
+-- Under DOS change the current drive as well as the current directory.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <os2.h>
+#include "extern.h"
+
+PUBLIC int
+_dchdir(path)
+char *path;
+{
+ int res;
+
+ res = _chdir(path);
+
+ if (res == 0 && path[1] == ':')
+ DosSelectDisk((*path & ~0x20) - '@');
+
+ return (res);
+}
diff --git a/dmake/os2/dirent.h b/dmake/os2/dirent.h
new file mode 100644
index 000000000000..eafaccbcc38a
--- /dev/null
+++ b/dmake/os2/dirent.h
@@ -0,0 +1,36 @@
+/* DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89 */
+
+#ifndef _DIRLIB_h_
+#define _DIRLIB_h_
+
+#define INCL_DOSFILEMGR
+#include <os2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "stdmacs.h"
+
+#define MAXNAMLEN _MAX_FNAME
+
+struct dirent {
+ long d_ino;
+ unsigned short d_reclen;
+ unsigned short d_namlen;
+ char d_name[MAXNAMLEN+1];
+};
+
+typedef struct {
+ HDIR dd_handle; /* Handle for FindFirst/Next */
+ FILEFINDBUF3 dd_dta; /* Disk transfer area for this dir. */
+ ULONG dd_count; /* Count for FindFirst/Next */
+ APIRET dd_stat; /* Status return from last lookup */
+ char dd_name[1]; /* Full name of file -- struct is extended */
+} DIR;
+
+extern DIR *opendir ANSI((char *));
+extern struct dirent *readdir ANSI((DIR *));
+extern long telldir ANSI((DIR *));
+extern void seekdir ANSI((DIR *, long));
+extern void closedir ANSI((DIR *));
+
+#define rewinddir(dirp) seekdir(dirp,0L)
+#endif
diff --git a/dmake/os2/ibm/config.h b/dmake/os2/ibm/config.h
new file mode 100644
index 000000000000..afff0f203845
--- /dev/null
+++ b/dmake/os2/ibm/config.h
@@ -0,0 +1,78 @@
+/* RCS $Id: config.h,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+--
+-- SYNOPSIS
+-- Configurarion include file.
+--
+-- DESCRIPTION
+-- There is one of these for each specific machine configuration.
+-- It can be used to further tweek the machine specific sources
+-- so that they compile.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#if defined (_MSC_VER)
+# if _MSC_VER < 500
+ Force a compile-time blowup.
+ Do not define define _MSC_VER for MSC compilers ealier than 5.0.
+# endif
+#endif
+
+/* define this for configurations that don't have the coreleft function
+ * so that the code compiles. To my knowledge coreleft exists only on
+ * Turbo C, but it is needed here since the function is used in many debug
+ * macros. */
+#define coreleft() 0L
+
+/* MSC Version 4.0 doesn't understand SIGTERM, later versions do. */
+#ifndef SIGTERM
+# define SIGTERM SIGINT
+#endif
+
+/* This should already be defined under C6.0, also for OS/2 we want buffering
+ * to minimise the mess during parallel makes.
+ */
+#ifndef _IOLBF
+# define _IOLBF _IOFBF
+#endif
+
+/* in alloc.h: size_t is redefined
+ * defined in stdio.h which is included by alloc.h
+ */
+#if defined(MSDOS) && defined (_MSC_VER)
+# define _TYPES_
+#endif
+
+/* Don't need this one either */
+#define CONST
+
+/* in sysintf.c: SIGQUIT is used, this is not defined in MSC */
+#ifndef SIGQUIT
+# define SIGQUIT SIGTERM
+#endif
+
+/* a small problem with pointer to voids on some unix machines needs this */
+#define PVOID void *
+
+/* C-lib redefinitions... */
+#define dup _dup
+#define close _close
+#define utime _utime
+#define tzset _tzset
+#define access _access
+#define getpid _getpid
+#define getcwd _getcwd
diff --git a/dmake/os2/ibm/config.mk b/dmake/os2/ibm/config.mk
new file mode 100644
index 000000000000..716addd82abf
--- /dev/null
+++ b/dmake/os2/ibm/config.mk
@@ -0,0 +1,54 @@
+# This is the MSC 4.0 and higher DOS configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+TMPDIR :=
+.EXPORT : TMPDIR
+
+# Definition of macros for library, and C startup code.
+
+# The following sources are required for MSC
+OSR_SRC = tempnam.c
+.SETDIR=$(osrdir) : $(OSR_SRC)
+
+SRC += $(OSR_SRC)
+.SOURCE.h : $(osrdir)
+
+SET_STACK = $-stack:32768
+NDB_LDFLAGS +=
+
+ASFLAGS += -t -mx $(S_$(MODEL))
+
+# Microsoft C doesn't need tail but needs head
+LDTAIL = ,;
+LDHEAD = $(LDFLAGS)
+
+# Debugging libraries
+DB_LDFLAGS += $-co $-li $-map $(SET_STACK)
+DB_LDLIBS +=
+
+# NO Debug MSC flags:
+# Set the environment variable MSC_VER to be one of 5.1, 6.0, 8.0 (for VC++4.0)
+# to get these by default when you make dmake using 'dmake'.
+#
+# Setting MSC_VER to one of the above sets the variable _MSC_VER appropriately
+# and sets the flags appropriately.
+
+CFLAGS += $-I$(osrdir)
+DB_CFLAGS += $-Ti+
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
+
+S_s = -Dmsmall
+S_m = -Dmmedium
+S_c = -Dmcompact
+S_l = -Dmlarge
diff --git a/dmake/os2/ibm/icc/config.mk b/dmake/os2/ibm/icc/config.mk
new file mode 100644
index 000000000000..2042f5636262
--- /dev/null
+++ b/dmake/os2/ibm/icc/config.mk
@@ -0,0 +1,11 @@
+# Definition of macros for library, and C startup code.
+osedir = $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)
+
+.IMPORT .IGNORE : MSC_VER
+MSC_VER *= 6.0
+
+CFLAGS += $-I$(osedir) $-Sp1 $-Q $-Fi-
+
+NDB_CFLAGS += $-O
+NDB_LDFLAGS += $-de $-pmtype:vio $-align:16 $-nologo $-m $-stack:32768
+NDB_LDLIBS +=
diff --git a/dmake/os2/ibm/icc/lib.rsp b/dmake/os2/ibm/icc/lib.rsp
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/dmake/os2/ibm/icc/lib.rsp
@@ -0,0 +1 @@
+
diff --git a/dmake/os2/ibm/icc/mk.cmd b/dmake/os2/ibm/icc/mk.cmd
new file mode 100755
index 000000000000..563a88aad43c
--- /dev/null
+++ b/dmake/os2/ibm/icc/mk.cmd
@@ -0,0 +1,96 @@
+md objects
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O infer.c
+copy infer.obj objects
+del infer.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O make.c
+copy make.obj objects
+del make.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O stat.c
+copy stat.obj objects
+del stat.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O expand.c
+copy expand.obj objects
+del expand.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O dmstring.c
+copy dmstring.obj objects
+del dmstring.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O hash.c
+copy hash.obj objects
+del hash.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O dag.c
+copy dag.obj objects
+del dag.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O dmake.c
+copy dmake.obj objects
+del dmake.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O path.c
+copy path.obj objects
+del path.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O imacs.c
+copy imacs.obj objects
+del imacs.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O sysintf.c
+copy sysintf.obj objects
+del sysintf.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O parse.c
+copy parse.obj objects
+del parse.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O getinp.c
+copy getinp.obj objects
+del getinp.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O quit.c
+copy quit.obj objects
+del quit.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O state.c
+copy state.obj objects
+del state.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O dmdump.c
+copy dmdump.obj objects
+del dmdump.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O macparse.c
+copy macparse.obj objects
+del macparse.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O rulparse.c
+copy rulparse.obj objects
+del rulparse.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O percent.c
+copy percent.obj objects
+del percent.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O function.c
+copy function.obj objects
+del function.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O os2\ruletab.c
+copy ruletab.obj objects
+del ruletab.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O os2\dchdir.c
+copy dchdir.obj objects
+del dchdir.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O os2\switchar.c
+copy switchar.obj objects
+del switchar.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O os2\dirlib.c
+copy dirlib.obj objects
+del dirlib.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O os2\runargv.c
+copy runargv.obj objects
+del runargv.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O msdos\dirbrk.c
+copy dirbrk.obj objects
+del dirbrk.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O msdos\arlib.c
+copy arlib.obj objects
+del arlib.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O msdos\dstrlwr.c
+copy dstrlwr.obj objects
+del dstrlwr.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O unix\rmprq.c
+copy rmprq.obj objects
+del rmprq.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O unix\dcache.c
+copy dcache.obj objects
+del dcache.obj
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc /Sp1 /Q /Fi- /O os2\ibm\tempnam.c
+copy tempnam.obj objects
+del tempnam.obj
+link386 /de /pmtype:vio /align:16 /nologo /m /stack:32768 @os2\ibm\icc\obj.rsp,dmake.exe,NUL.MAP,,,;
+copy os2\ibm\icc\template.mk startup\config.mk
diff --git a/dmake/os2/ibm/icc/obj.rsp b/dmake/os2/ibm/icc/obj.rsp
new file mode 100644
index 000000000000..594535036c87
--- /dev/null
+++ b/dmake/os2/ibm/icc/obj.rsp
@@ -0,0 +1,31 @@
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\dirlib.obj+
+objects\runargv.obj+
+objects\dirbrk.obj+
+objects\arlib.obj+
+objects\dstrlwr.obj+
+objects\rmprq.obj+
+objects\dcache.obj+
+objects\tempnam.obj
diff --git a/dmake/os2/ibm/icc/public.h b/dmake/os2/ibm/icc/public.h
new file mode 100644
index 000000000000..1a9d48a358ea
--- /dev/null
+++ b/dmake/os2/ibm/icc/public.h
@@ -0,0 +1,168 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+int _dchdir ANSI((char *));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+void SetSessionTitle ANSI((char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+int If_root_path ANSI((char *));
+time_t seek_arch ANSI((char*, char*));
+int touch_arch ANSI((char*, char*));
+void dstrlwr ANSI((char *, char *));
+void Remove_prq ANSI((CELLPTR));
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/os2/ibm/icc/template.mk b/dmake/os2/ibm/icc/template.mk
new file mode 100644
index 000000000000..c9c5adbf21ae
--- /dev/null
+++ b/dmake/os2/ibm/icc/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= os2
+ OSRELEASE *:= ibm
+ OSENVIRONMENT *:= icc
diff --git a/dmake/os2/ibm/icc3/config.mk b/dmake/os2/ibm/icc3/config.mk
new file mode 100644
index 000000000000..2042f5636262
--- /dev/null
+++ b/dmake/os2/ibm/icc3/config.mk
@@ -0,0 +1,11 @@
+# Definition of macros for library, and C startup code.
+osedir = $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)
+
+.IMPORT .IGNORE : MSC_VER
+MSC_VER *= 6.0
+
+CFLAGS += $-I$(osedir) $-Sp1 $-Q $-Fi-
+
+NDB_CFLAGS += $-O
+NDB_LDFLAGS += $-de $-pmtype:vio $-align:16 $-nologo $-m $-stack:32768
+NDB_LDLIBS +=
diff --git a/dmake/os2/ibm/icc3/lib.rsp b/dmake/os2/ibm/icc3/lib.rsp
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/dmake/os2/ibm/icc3/lib.rsp
@@ -0,0 +1 @@
+
diff --git a/dmake/os2/ibm/icc3/mk.cmd b/dmake/os2/ibm/icc3/mk.cmd
new file mode 100755
index 000000000000..f45e63e64318
--- /dev/null
+++ b/dmake/os2/ibm/icc3/mk.cmd
@@ -0,0 +1,192 @@
+md objects
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O infer.c
+
+copy infer.obj objects
+
+del infer.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O make.c
+
+copy make.obj objects
+
+del make.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O stat.c
+
+copy stat.obj objects
+
+del stat.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O expand.c
+
+copy expand.obj objects
+
+del expand.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O dmstring.c
+
+copy dmstring.obj objects
+
+del dmstring.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O hash.c
+
+copy hash.obj objects
+
+del hash.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O dag.c
+
+copy dag.obj objects
+
+del dag.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O dmake.c
+
+copy dmake.obj objects
+
+del dmake.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O path.c
+
+copy path.obj objects
+
+del path.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O imacs.c
+
+copy imacs.obj objects
+
+del imacs.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O sysintf.c
+
+copy sysintf.obj objects
+
+del sysintf.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O parse.c
+
+copy parse.obj objects
+
+del parse.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O getinp.c
+
+copy getinp.obj objects
+
+del getinp.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O quit.c
+
+copy quit.obj objects
+
+del quit.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O state.c
+
+copy state.obj objects
+
+del state.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O dmdump.c
+
+copy dmdump.obj objects
+
+del dmdump.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O macparse.c
+
+copy macparse.obj objects
+
+del macparse.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O rulparse.c
+
+copy rulparse.obj objects
+
+del rulparse.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O percent.c
+
+copy percent.obj objects
+
+del percent.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O function.c
+
+copy function.obj objects
+
+del function.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O os2\ruletab.c
+
+copy ruletab.obj objects
+
+del ruletab.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O os2\dchdir.c
+
+copy dchdir.obj objects
+
+del dchdir.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O os2\switchar.c
+
+copy switchar.obj objects
+
+del switchar.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O msdos\dirlib.c
+
+copy dirlib.obj objects
+
+del dirlib.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O msdos\runargv.c
+
+copy runargv.obj objects
+
+del runargv.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O msdos\dirbrk.c
+
+copy dirbrk.obj objects
+
+del dirbrk.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O msdos\arlib.c
+
+copy arlib.obj objects
+
+del arlib.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O msdos\dstrlwr.c
+
+copy dstrlwr.obj objects
+
+del dstrlwr.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O unix\rmprq.c
+
+copy rmprq.obj objects
+
+del rmprq.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O unix\dcache.c
+
+copy dcache.obj objects
+
+del dcache.obj
+
+icc /c /I. /Ios2 /Ios2\ibm /Ios2\ibm\icc3 /Sp1 /Q /Fi- /O tempnam.c
+
+copy tempnam.obj objects
+
+del tempnam.obj
+
+ilink /NOFREE /de /pmtype:vio /align:16 /nologo /m /stack:32768 @os2\ibm\icc3\obj.rsp,,,,,
+
+copy os2\ibm\icc3\template.mk startup\config.mk
+
diff --git a/dmake/os2/ibm/icc3/obj.rsp b/dmake/os2/ibm/icc3/obj.rsp
new file mode 100644
index 000000000000..6309577681b9
--- /dev/null
+++ b/dmake/os2/ibm/icc3/obj.rsp
@@ -0,0 +1,30 @@
+objects\dmake.obj+
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\ruletab.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\runargv.obj+
+objects\dirbrk.obj+
+objects\arlib.obj+
+objects\dstrlwr.obj+
+objects\rmprq.obj+
+objects\tempnam.obj
+
diff --git a/dmake/os2/ibm/icc3/public.h b/dmake/os2/ibm/icc3/public.h
new file mode 100644
index 000000000000..1a9d48a358ea
--- /dev/null
+++ b/dmake/os2/ibm/icc3/public.h
@@ -0,0 +1,168 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+int _dchdir ANSI((char *));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+void SetSessionTitle ANSI((char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+int If_root_path ANSI((char *));
+time_t seek_arch ANSI((char*, char*));
+int touch_arch ANSI((char*, char*));
+void dstrlwr ANSI((char *, char *));
+void Remove_prq ANSI((CELLPTR));
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/os2/ibm/icc3/template.mk b/dmake/os2/ibm/icc3/template.mk
new file mode 100644
index 000000000000..c9c5adbf21ae
--- /dev/null
+++ b/dmake/os2/ibm/icc3/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= os2
+ OSRELEASE *:= ibm
+ OSENVIRONMENT *:= icc
diff --git a/dmake/os2/ibm/tempnam.c b/dmake/os2/ibm/tempnam.c
new file mode 100644
index 000000000000..5bf5c21b3544
--- /dev/null
+++ b/dmake/os2/ibm/tempnam.c
@@ -0,0 +1,111 @@
+/* RCS $Id: tempnam.c,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+--
+-- SYNOPSIS
+-- tempnam
+--
+-- DESCRIPTION
+-- temp file name generation routines.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/*LINTLIBRARY*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "config.h"
+
+#if defined(max)
+# undef max
+#endif
+#define max(A,B) (((A)<(B))?(B):(A))
+
+extern int access();
+int d_access();
+
+/* MSC stdio.h defines P_tmpdir, so let's undo it here */
+/* Under DOS leave the default tmpdir pointing here! */
+#ifdef P_tmpdir
+#undef P_tmpdir
+#endif
+static char *P_tmpdir = "";
+
+char *
+tempnam(dir, prefix)
+char *dir; /* use this directory please (if non-NULL) */
+char *prefix; /* use this (if non-NULL) as filename prefix */
+{
+ static int count = 0;
+ register char *p, *q, *tmpdir;
+ int tl=0, dl=0, pl;
+ char buf[30];
+
+ pl = strlen(P_tmpdir);
+
+ if( (tmpdir = getenv("TMPDIR")) != NULL )
+ tl = strlen(tmpdir);
+ else if( (tmpdir = getenv("TMP")) != NULL )
+ tl = strlen(tmpdir);
+ if( dir != NULL ) dl = strlen(dir);
+
+ if( (p = malloc((unsigned)(max(max(dl,tl),pl)+13))) == NULL )
+ return(NULL);
+
+ *p = '\0';
+
+ if( (tl == 0) || (d_access( strcpy(p, tmpdir), 0) != 0) )
+ if( (dl == 0) || (d_access( strcpy(p, dir), 0) != 0) )
+ if( d_access( strcpy(p, P_tmpdir), 0) != 0 )
+ if( !prefix )
+ prefix = "tp";
+
+ if(prefix)
+ {
+ *(p+strlen(p)+2) = '\0';
+ (void)strncat(p, prefix, 2);
+ }
+
+ sprintf( buf, "%08x", getpid() );
+ buf[6]='\0';
+ (void)strcat(p, buf );
+ sprintf( buf, "%04d", count++ );
+ q=p+strlen(p)-6;
+ *q++ = buf[0]; *q++ = buf[1];
+ *q++ = buf[2]; *q++ = buf[3];
+
+ if( (q = strrchr(p,'.')) != NULL ) *q = '\0';
+
+ return strlwr(p);
+}
+
+
+
+d_access( name, flag )
+char *name;
+int flag;
+{
+ char *p;
+ int r;
+
+ if( name == NULL || !*name ) return(1); /* NULL dir means current dir */
+ p = name+strlen(name)-1;
+ if(*p == ':' ) strcat( p++, "\\" );
+ r = access( name, flag );
+ if(*p != '/' && *p != '\\') strcat( p, "\\" );
+
+ return( r );
+}
diff --git a/dmake/os2/ruletab.c b/dmake/os2/ruletab.c
new file mode 100644
index 000000000000..8620556393de
--- /dev/null
+++ b/dmake/os2/ruletab.c
@@ -0,0 +1,46 @@
+/* RCS $Id: ruletab.c,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+--
+-- SYNOPSIS
+-- Default initial configuration of dmake.
+--
+-- DESCRIPTION
+-- Define here the initial set of rules that are defined before
+-- dmake performs any processing.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* These are control macros for dmake that MUST be defined at some point
+ * if they are NOT dmake will not work! These are default definitions. They
+ * may be overridden inside the .STARTUP makefile, they are here
+ * strictly so that dmake can parse the STARTUP makefile */
+/*
+ * For OS/2 these are close to the Unix definitions in terms of limits.
+ * We dont need the two different cases of Makefile, so only keep the
+ * pretty one.
+ */
+static char *_rules[] = {
+ "MAXLINELENGTH := 2046",
+ "MAXPROCESSLIMIT := 16",
+ ".IMPORT .IGNORE: DMAKEROOT SOLARVER UPD INPATH OS UPDMINOREXT"
+ ".MAKEFILES : makefile.mk Makefile",
+ ".SOURCE : .NULL",
+#include "startup.h"
+ 0 };
+
+char **Rule_tab = _rules; /* for sundry reasons in Get_environment() */
+
diff --git a/dmake/os2/startup.h b/dmake/os2/startup.h
new file mode 100644
index 000000000000..bf6c94ff939f
--- /dev/null
+++ b/dmake/os2/startup.h
@@ -0,0 +1,27 @@
+/* RCS $Id: startup.h,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+--
+-- SYNOPSIS
+-- Definition of MAKESTARTUP
+--
+-- DESCRIPTION
+-- Default MAKESTARTUP value defining where dmake locates the
+-- startup file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+"MAKESTARTUP := $(DMAKEROOT)\\startup.mk",
diff --git a/dmake/os2/switchar.c b/dmake/os2/switchar.c
new file mode 100644
index 000000000000..458030993d57
--- /dev/null
+++ b/dmake/os2/switchar.c
@@ -0,0 +1,43 @@
+/* RCS $Id: switchar.c,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+--
+-- SYNOPSIS
+-- switch char query.
+--
+-- DESCRIPTION
+-- Get the current value of the command line switch char. Only useful
+-- in a DOS environment, otherwise we #define it to be '-'.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include "stdmacs.h"
+
+getswitchar()/*
+===============
+ Try the environment first. If you don't find SWITCHAR there, then use
+ the DOS call. The call is undocumented, and doesn't work for DOS versions
+ 4.0 and up, so the check of the environment will fix that. */
+{
+ static char *_env_switchar = NIL(char);
+
+ if( _env_switchar != NIL(char) ||
+ (_env_switchar = (char *)getenv("SWITCHAR")) != NIL(char) )
+ return(*_env_switchar);
+
+ return ('/');
+}
diff --git a/dmake/os2/sysintf.h b/dmake/os2/sysintf.h
new file mode 100644
index 000000000000..ab842c26c34f
--- /dev/null
+++ b/dmake/os2/sysintf.h
@@ -0,0 +1,60 @@
+/* RCS $Id: sysintf.h,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+--
+-- SYNOPSIS
+-- Interfaces for sysintf.c
+--
+-- DESCRIPTION
+-- Abstractions of functions in sysintf.c
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#define DMSTAT stat
+#define VOID_LCACHE(l,m)
+#define Hook_std_writes(A)
+#define GETPID getpid()
+#define DMSTRLWR(A,B) dstrlwr(A,B)
+#define S_IFMT (S_IFDIR|S_IFCHR|S_IFREG)
+
+extern char * tempnam();
+extern char * getcwd();
+
+/* for directory cache */
+/* #define CacheStat(A,B) really_dostat(A,&buf)*/
+
+/*
+** standard C items
+*/
+
+/*
+** DOS interface standard items
+*/
+#define chdir(p) _dchdir(p)
+#define CacheStat(A,B) really_dostat(A,&buf)
+
+/*
+** make parameters
+*/
+#ifdef _POSIX_NAME_MAX
+#undef _POSIX_NAME_MAX
+#endif
+#define _POSIX_NAME_MAX 12
+
+#ifdef _POSIX_PATH_MAX
+#undef _POSIX_PATH_MAX
+#endif
+#define _POSIX_PATH_MAX 255
diff --git a/dmake/parse.c b/dmake/parse.c
new file mode 100644
index 000000000000..c7bf8bf76880
--- /dev/null
+++ b/dmake/parse.c
@@ -0,0 +1,168 @@
+/* RCS $Id: parse.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Parse the input, and perform semantic analysis
+--
+-- DESCRIPTION
+-- This file contains the routines that parse the input makefile and
+-- call the appropriate routines to perform the semantic analysis and
+-- build the internal dag.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+
+PUBLIC void
+Parse( fil )/*
+============== Parse the makefile input */
+FILE *fil;
+{
+ int rule = FALSE; /* have seen a recipe line */
+ char *p; /* termporary pointer into Buffer */
+ char *pTmpBuf;
+
+ DB_ENTER( "Parse" );
+
+ State = NORMAL_SCAN;
+ Group = FALSE; /* true if scanning a group rcpe */
+ while( TRUE ) {
+ if( Get_line( Buffer, fil ) ) {
+ if( fil != NIL( FILE ) ) /* end of parsable input */
+ Closefile();
+
+ Bind_rules_to_targets( F_DEFAULT );
+ if( Group ) Fatal( "Incomplete rule recipe group detected" );
+
+ DB_VOID_RETURN;
+ }
+ else {
+
+#ifdef _MPW
+ if ( Buffer[0] == 10 )
+ pTmpBuf = Buffer+1;
+ else
+#endif
+ pTmpBuf = Buffer;
+
+#ifdef _MPW
+ p = pTmpBuf;
+ while ( *p )
+ {
+ if ( *p == 10 )
+ *p = '\t';
+ p++;
+ }
+#endif
+
+ switch( State ) {
+ case RULE_SCAN:
+
+ /* Check for the `[' that starts off a group rule definition.
+ * It must appear as the first non-white space
+ * character in the line. */
+
+ p = DmStrSpn( Buffer, " \t\r\n" );
+ if( Set_group_attributes( p ) ) {
+ if( rule && Group )
+ Fatal( "Cannot mix single and group recipe lines" );
+ else
+ Group = TRUE;
+
+ rule = TRUE;
+
+ break; /* ignore the group start */
+ }
+
+ if( Group ) {
+ if( *p != ']' ) {
+ Add_recipe_to_list( pTmpBuf, TRUE, TRUE );
+ rule = TRUE;
+ }
+ else
+ State = NORMAL_SCAN;
+ }
+ else {
+ if( *pTmpBuf == '\t'
+ || (Notabs && *pTmpBuf == ' ') ) {
+ Add_recipe_to_list( pTmpBuf, FALSE, FALSE );
+ rule = TRUE;
+ }
+ else if( *p == ']' )
+ Fatal( "Found unmatched ']'" );
+ else if( *pTmpBuf && *p || (Notabs && !*pTmpBuf && !*p))
+ State = NORMAL_SCAN;
+ }
+
+ if( State == RULE_SCAN ) break; /* ie. keep going */
+
+ Bind_rules_to_targets( (Group) ? F_GROUP: F_DEFAULT );
+
+ rule = FALSE;
+ if( Group ) {
+ Group = FALSE;
+ break;
+ }
+ /*FALLTRHOUGH*/
+
+ /* In this case we broke out of the rule scan because we do not
+ * have a recipe line that begins with a <TAB>, so lets
+ * try to scan the thing as a macro or rule definition. */
+
+
+ case NORMAL_SCAN:
+ if( !*pTmpBuf ) continue; /* we have null input line */
+
+ /* STUPID AUGMAKE uses "include" at the start of a line as
+ * a signal to include a new file, so let's look for it.
+ * if we see it replace it by .INCLUDE: and stick this back
+ * into the buffer. */
+ if( !strncmp( "include", pTmpBuf, 7 ) &&
+ (pTmpBuf[7] == ' ' || pTmpBuf[7] == '\t') )
+ {
+ char *tmp;
+
+ tmp = DmStrJoin( ".INCLUDE:", pTmpBuf+7, -1, FALSE );
+ strcpy( pTmpBuf, tmp );
+ FREE( tmp );
+ }
+
+ /* look for a macro definition, they all contain an = sign
+ * if we fail to recognize it as a legal macro op then try to
+ * parse the same line as a rule definition, it's one or the
+ * other */
+
+ if( Parse_macro(pTmpBuf, M_DEFAULT) ) break;/* it's a macro def*/
+ if( Parse_rule_def( &State ) ) break;/* it's a rule def */
+
+ /* if just blank line then ignore it */
+ if( *DmStrSpn( Buffer, " \t\r\n" ) == '\0' ) break;
+
+ /* otherwise assume it was a line of unrecognized input, or a
+ * recipe line out of place so print a message */
+
+ Fatal( "Expecting macro or rule defn, found neither" );
+ break;
+
+ default:
+ Fatal( "Internal -- UNKNOWN Parser state %d", State );
+ }
+ }
+ }
+}
+
diff --git a/dmake/path.c b/dmake/path.c
new file mode 100644
index 000000000000..a4c2f9af7031
--- /dev/null
+++ b/dmake/path.c
@@ -0,0 +1,161 @@
+/* RCS $Id: path.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Pathname manipulation code
+--
+-- DESCRIPTION
+-- Pathname routines to handle building and pulling appart
+-- pathnames.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+
+/*
+** Return the suffix portion of a filename, assumed to begin with a `.'.
+*/
+PUBLIC char *
+Get_suffix(name)
+char *name;
+{
+ char *suff;
+
+ if(name == NIL(char) || (suff = strrchr(name, '.')) == NIL(char))
+ suff = ".NULL";
+
+ return (suff);
+}
+
+
+PUBLIC char *
+Basename(path)
+char *path;
+{
+ char *p;
+ char *q;
+
+ if( path && *(q = path) ) {
+ for(; *(p=DmStrPbrk(q, DirBrkStr)) != '\0'; q = p+1 );
+ if( !*q ) {
+ for( p=q-1; p != path; --p )
+ if( strchr( DirBrkStr, *p ) == NIL(char) ) return( p+1 );
+ return( strchr(DirBrkStr, *p)?path:(p+1) );
+ }
+ path = q;
+ }
+ return( path );
+}
+
+
+PUBLIC char *
+Filedir(path)
+char *path;
+{
+ char *p;
+ char *q;
+
+ if( path && *(q = path) ) {
+ for(; *(p=DmStrPbrk(q,DirBrkStr)) != '\0'; q=p+1 );
+
+ if (q == path) return("");
+
+ for(p=q-1; p!=path; --p)
+ if( strchr(DirBrkStr,*p) == NIL(char) )
+ break;
+
+ p[1] = '\0';
+ }
+
+ return(path);
+}
+
+
+
+/*
+** Take dir and name, and return a path which has dir as the directory
+** and name afterwards.
+**
+** N.B. Assumes that the dir separator string is in DirSepStr.
+** Return path is built in a static buffer, if you need to use it
+** again you must strdup the result returned by Build_path.
+*/
+PUBLIC char *
+Build_path(dir, name)
+char *dir;
+char *name;
+{
+ register char *p;
+ register char *q;
+ static char *path = NIL(char);
+ static unsigned buflen = 0;
+ int plen = 0;
+ int dlen = 0;
+ int len;
+
+ if( dir != NIL(char) ) dlen = strlen( dir );
+ if( name != NIL(char) ) plen = strlen( name );
+ len = plen+dlen+strlen(DirSepStr)+1;
+
+ if( len > buflen ) {
+ buflen = (len+16) & ~0xf; /* buf is always multiple of 16 */
+
+ if( path == NIL(char) )
+ path = MALLOC( buflen, char );
+ else
+ path = realloc( path, (unsigned) (buflen*sizeof(char)) );
+ }
+
+ *path = '\0';
+
+ if( dlen ) {
+ strcpy( path, dir );
+ if( *path && strchr(DirBrkStr, dir[dlen-1]) == NIL(char) )
+ strcat( path, DirSepStr );
+ }
+
+ if ( plen ) {
+ while ( *name && strchr(DirBrkStr,*name) != 0 ) name++;
+ strcat( path, name );
+ }
+
+ q=path;
+ while( *q ) {
+ char *t;
+
+ p=DmStrPbrk(q,DirBrkStr);
+ t=DmStrPbrk(p+1,DirBrkStr);
+ if( !*p || !*t ) break;
+
+ if ( p-q == 1 && *q == '.' ) {
+ strcpy(q,DmStrSpn(p,DirBrkStr));
+ q = path;
+ }
+ else if (
+ !(p-q == 2 && strncmp(q,"..",2) == 0)
+ && (t-p-1 == 2 && strncmp(p+1,"..",2) == 0)
+ ) {
+ strcpy(q,DmStrSpn(t,DirBrkStr));
+ q = path;
+ }
+ else
+ q = p+1;
+ }
+
+ return( path );
+}
diff --git a/dmake/percent.c b/dmake/percent.c
new file mode 100644
index 000000000000..8ecac4ce764d
--- /dev/null
+++ b/dmake/percent.c
@@ -0,0 +1,251 @@
+/* RCS $Id: percent.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Handle building or %-rule meta-target nfa.
+--
+-- DESCRIPTION
+-- Builds the NFA used by dmake to match targets against %-meta
+-- rule constructs. The NFA is built as a set of DFA's.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+static DFAPTR _build_dfa ANSI((char *));
+static char _shift_dfa ANSI((DFAPTR, char *));
+
+
+#define NO_ACTION 0
+#define START_PERCENT 1
+#define END_PERCENT 2
+#define ACCEPT 4
+#define FAIL -1
+
+static NFAPTR _nfa = NIL( NFA );
+
+
+PUBLIC DFALINKPTR
+Match_dfa( buf )/*
+==================
+ This routines runs all DFA's in parrallel and selects the one that best
+ matches the string. If no match then it returns NIL( DFA ) */
+char *buf;
+{
+ register NFAPTR nfa;
+ int adv;
+ DFALINKPTR dfa_list = NIL(DFALINK);
+
+ DB_ENTER( "Match_dfa" );
+ DB_PRINT( "dfa", ("Matching %s", buf) );
+
+ /* Run each of the DFA's on the input string in parallel, we terminate
+ * when all DFA's have either failed or ACCEPTED, if more than one DFA
+ * accepts we build a list of all accepting DFA's sorted on states with
+ * those matching in a higher numbered state heading the list. */
+
+ do {
+ adv = FALSE;
+
+ for( nfa = _nfa; nfa != NIL( NFA ); nfa = nfa->next )
+ if( nfa->status != (char) FAIL && nfa->status != (char) ACCEPT ) {
+ adv++;
+ nfa->status = _shift_dfa( nfa->dfa, buf );
+
+ /* Construct the list of matching DFA's */
+ if( nfa->status == (char) ACCEPT ) {
+ DFALINKPTR dl;
+
+ TALLOC( dl, 1, DFALINK );
+ dl->dl_meta = nfa->dfa->node;
+ dl->dl_per = DmSubStr( nfa->dfa->pstart, nfa->dfa->pend );
+ dl->dl_state = nfa->dfa->states - nfa->dfa->c_state;
+
+ if( dfa_list == NIL(DFALINK) )
+ dfa_list = dl;
+ else {
+ DFALINKPTR tdli = dfa_list;
+ DFALINKPTR tdlp = NIL(DFALINK);
+
+ for( ; tdli != NIL(DFALINK); tdli = tdli->dl_next ) {
+ if( dl->dl_state >= tdli->dl_state )
+ break;
+ tdlp = tdli;
+ }
+
+ if( tdli != NIL(DFALINK) ) {
+ tdli->dl_prev = dl;
+ dl->dl_next = tdli;
+ }
+
+ if( tdlp != NIL(DFALINK) ) {
+ tdlp->dl_next = dl;
+ dl->dl_prev = tdlp;
+ }
+ else
+ dfa_list = dl;
+ }
+
+ DB_PRINT( "dfa", ("Matched [%s]", dl->dl_meta->CE_NAME) );
+ }
+ }
+
+ buf++;
+ }
+ while ( adv );
+
+ for( nfa = _nfa; nfa != NIL( NFA ); nfa = nfa->next ) {
+ nfa->status = 0;
+ nfa->dfa->c_state = nfa->dfa->states;
+ }
+
+ DB_RETURN( dfa_list );
+}
+
+
+PUBLIC void
+Check_circle_dfa()/*
+====================
+ This function is called to test for circularities in the DFA lists
+ constructed from %-meta targets. */
+{
+ register NFAPTR nfa;
+
+ for( nfa = _nfa; nfa != NIL(NFA); nfa = nfa->next )
+ if( Test_circle( nfa->dfa->node, FALSE ) )
+ Fatal( "Detected circular dependency in inference graph at [%s]",
+ nfa->dfa->node->CE_NAME );
+}
+
+
+PUBLIC void
+Add_nfa( name )/*
+=================
+ Given name, build a DFA and add it to the NFA. The NFA is maintained as
+ a singly linked list of DFA's. */
+char *name;
+{
+ NFAPTR nfa;
+
+ TALLOC(nfa, 1, NFA);
+ nfa->dfa = _build_dfa(name);
+
+ if( _nfa != NIL(NFA) ) nfa->next = _nfa;
+
+ _nfa = nfa;
+}
+
+
+static DFAPTR
+_build_dfa( name )/*
+====================
+ Construct a dfa for the passed in cell name. The routine returns a struct
+ that represents a finite state machine that can recognize a regular
+ expression with exactly one '%' sign in it. The '%' symbol is used as a
+ wildcard character that will match anything except the character that
+ immediately follows it or NUL.
+
+ The Construction of DFA's is well known and can be found in Hopcroft and
+ Ullman or any other book discussing formal language theory.
+ A more practical treatise can be found in Compilers, Aho, Sethi and Ullman.
+*/
+char *name;
+{
+ DFAPTR dfa;
+ int nstates;
+ register STATEPTR sp;
+ STATEPTR per_state = NIL(STATE);
+ int pcount=0;
+ int end_percent=FALSE;
+
+ nstates = strlen(name)+2;
+
+ /* Allocate a DFA node and the right number of states. */
+ TALLOC(dfa, 1, DFA);
+ TALLOC(sp=dfa->c_state=dfa->states, nstates, STATE);
+ dfa->node = Def_cell( name );
+
+ /* Now construct the state table for the DFA */
+ do {
+ if( *name == '%' ) {
+ if( pcount++ > 0 )
+ Error( "Only one %% allowed within a %%-meta target" );
+
+ sp->symbol = 0;
+ sp->action = START_PERCENT;
+ sp->no_match = sp->match = per_state = sp+1;
+ end_percent = TRUE;
+ }
+ else {
+ sp->symbol = *name;
+ sp->no_match = per_state;
+
+ if( *name == '\0' ) {
+ sp->action = ACCEPT;
+ sp->match = dfa->states;
+ }
+ else {
+ sp->action = NO_ACTION;
+ sp->match = sp+1;
+ }
+
+ if( end_percent ) {
+ sp->action |= END_PERCENT;
+ end_percent = FALSE;
+ }
+ }
+
+ sp++;
+ }
+ while( *name++ );
+
+ return(dfa);
+}
+
+
+static char
+_shift_dfa( dfa, data )/*
+=========================
+ Take a given dfa and advance it based on the current state, the shift
+ action in that state, and the current data value. */
+DFAPTR dfa;
+char *data;
+{
+ register STATEPTR sp = dfa->c_state;
+ char c = *data;
+
+ /* Check if it is a START_PERCENT action if so then we need to save
+ * a pointer to the start of the string and advance to the next state. */
+ if( sp->action & START_PERCENT ) {
+ dfa->pstart = data;
+ sp++;
+ }
+
+ /* Now check if the current char matches the character expected in the
+ * current state. If it does then perform the specified action, otherwise
+ * either shift it or fail. We fail if the next state on no-match is
+ * NIL. */
+ if( sp->symbol == c ) {
+ if( sp->action & END_PERCENT ) dfa->pend = data;
+ if( sp->action & ACCEPT ) return(ACCEPT);
+ dfa->c_state = sp->match;
+ }
+ else if( (dfa->c_state = sp->no_match) == NIL(STATE) || !c )
+ return((unsigned char) FAIL);
+
+ return(NO_ACTION);
+}
diff --git a/dmake/posix.h b/dmake/posix.h
new file mode 100644
index 000000000000..b28dca36f010
--- /dev/null
+++ b/dmake/posix.h
@@ -0,0 +1,54 @@
+/* RCS $Id: posix.h,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Definition for POSIX conforming defines in dmake.
+--
+-- DESCRIPTION
+-- This file is intended to make certain that defines used within dmake
+-- for file name lengths, and number of children processes are defined.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* Define the minimum values that each system requires, and do so only if
+ * we have not defined these includes elsewhere. These should already be
+ * defined in <limits.h> if you have a C compiler that is POSIX compliant.
+ */
+#ifndef _POSIX_NAME_MAX
+#define _POSIX_NAME_MAX 14
+#endif
+
+#ifndef _POSIX_PATH_MAX
+#define _POSIX_PATH_MAX 64
+#endif
+
+#ifndef _POSIX_CHILD_MAX
+#define _POSIX_CHILD_MAX 1
+#endif
+
+/* Now define the actual manifests used in the code. */
+#ifndef NAME_MAX
+#define NAME_MAX _POSIX_NAME_MAX
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX _POSIX_PATH_MAX
+#endif
+
+#ifndef CHILD_MAX
+#define CHILD_MAX _POSIX_CHILD_MAX
+#endif
diff --git a/dmake/qssl/config.mk b/dmake/qssl/config.mk
new file mode 100644
index 000000000000..d5d1534996eb
--- /dev/null
+++ b/dmake/qssl/config.mk
@@ -0,0 +1,43 @@
+# This is an OS specific configuration file
+# It assumes that OBJDIR, TARGET and DEBUG are previously defined.
+# It defines CFLAGS, LDARGS, CPPFLAGS, STARTUPFILE, LDOBJS
+# PRINTER, PRINTFLAGS
+# It augments SRC, OBJDIR, TARGET, CFLAGS, LDLIBS
+#
+PRINTER = hw
+PRINTFLAGS = -P$(PRINTER)
+STARTUPFILE = $(OS)/startup.mk
+CPPFLAGS = $(CFLAGS)
+LDOBJS = $(CSTARTUP) $(OBJDIR)/{$(<:f)}
+LDARGS = $(LDFLAGS) -o $@ $(LDOBJS) $(LDLIBS)
+
+# Debug flags
+DB_CFLAGS = -g -DDBUG
+DB_LDFLAGS = -g
+DB_LDLIBS =
+
+# NO Debug flags
+NDB_CFLAGS = -O
+NDB_LDFLAGS = -N 8192
+NDB_LDLIBS =
+
+# Local configuration modifications for CFLAGS.
+CFLAGS += -I$(OS) -3
+
+# Sources that must be defined for each different version
+OSSRC := ruletab.c runargv.c tempnam.c
+UNIXSRC := dcache.c rmprq.c dirbrk.c
+DOSSRC := arlib.c
+SRC += $(OSSRC) $(UNIXSRC) $(DOSSRC)
+.SETDIR=$(OS) : $(OSSRC)
+.SETDIR=unix : $(UNIXSRC)
+.SETDIR=msdos : $(DOSSRC)
+
+# Set source dirs so that we can find files named in this
+# config file.
+.SOURCE.h : $(OS)
+
+# See if we modify anything in the lower levels.
+.IF $(OSRELEASE) != $(NULL)
+ .INCLUDE .IGNORE : $(OS)$(DIRSEPSTR)$(OSRELEASE)$(DIRSEPSTR)config.mk
+.END
diff --git a/dmake/qssl/make.sh b/dmake/qssl/make.sh
new file mode 100644
index 000000000000..042e219adde7
--- /dev/null
+++ b/dmake/qssl/make.sh
@@ -0,0 +1,62 @@
+mkdir objects
+cc -c -I. -Iqssl -3 -O infer.c
+mv infer.o objects
+cc -c -I. -Iqssl -3 -O make.c
+mv make.o objects
+cc -c -I. -Iqssl -3 -O stat.c
+mv stat.o objects
+cc -c -I. -Iqssl -3 -O expand.c
+mv expand.o objects
+cc -c -I. -Iqssl -3 -O dmstring.c
+mv dmstring.o objects
+cc -c -I. -Iqssl -3 -O hash.c
+mv hash.o objects
+cc -c -I. -Iqssl -3 -O dag.c
+mv dag.o objects
+cc -c -I. -Iqssl -3 -O dmake.c
+mv dmake.o objects
+cc -c -I. -Iqssl -3 -O path.c
+mv path.o objects
+cc -c -I. -Iqssl -3 -O imacs.c
+mv imacs.o objects
+cc -c -I. -Iqssl -3 -O sysintf.c
+mv sysintf.o objects
+cc -c -I. -Iqssl -3 -O parse.c
+mv parse.o objects
+cc -c -I. -Iqssl -3 -O getinp.c
+mv getinp.o objects
+cc -c -I. -Iqssl -3 -O quit.c
+mv quit.o objects
+cc -c -I. -Iqssl -3 -O state.c
+mv state.o objects
+cc -c -I. -Iqssl -3 -O dmdump.c
+mv dmdump.o objects
+cc -c -I. -Iqssl -3 -O macparse.c
+mv macparse.o objects
+cc -c -I. -Iqssl -3 -O rulparse.c
+mv rulparse.o objects
+cc -c -I. -Iqssl -3 -O percent.c
+mv percent.o objects
+cc -c -I. -Iqssl -3 -O function.c
+mv function.o objects
+cc -c -I. -Iqssl -3 -O qssl/ruletab.c
+mv ruletab.o objects
+cc -c -I. -Iqssl -3 -O qssl/runargv.c
+mv runargv.o objects
+cc -c -I. -Iqssl -3 -O qssl/tempnam.c
+mv tempnam.o objects
+cc -c -I. -Iqssl -3 -O unix/dcache.c
+mv dcache.o objects
+cc -c -I. -Iqssl -3 -O unix/rmprq.c
+mv rmprq.o objects
+cc -c -I. -Iqssl -3 -O unix/dirbrk.c
+mv dirbrk.o objects
+cc -c -I. -Iqssl -3 -O msdos/arlib.c
+mv arlib.o objects
+cc -N 8192 -o dmake objects/infer.o objects/make.o objects/stat.o \
+objects/expand.o objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o \
+objects/path.o objects/imacs.o objects/sysintf.o objects/parse.o \
+objects/getinp.o objects/quit.o objects/state.o objects/dmdump.o \
+objects/macparse.o objects/rulparse.o objects/percent.o objects/function.o \
+objects/ruletab.o objects/runargv.o objects/tempnam.o objects/dcache.o objects/rmprq.o objects/dirbrk.o objects/arlib.o
+cp qssl/template.mk startup/config.mk
diff --git a/dmake/qssl/public.h b/dmake/qssl/public.h
new file mode 100644
index 000000000000..2b977c4ed6b6
--- /dev/null
+++ b/dmake/qssl/public.h
@@ -0,0 +1,165 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+void Remove_prq ANSI((CELLPTR));
+int If_root_path ANSI((char *));
+time_t seek_arch ANSI((char*, char*));
+int touch_arch ANSI((char*, char*));
+
+#endif
diff --git a/dmake/qssl/ruletab.c b/dmake/qssl/ruletab.c
new file mode 100644
index 000000000000..4bdd0be36314
--- /dev/null
+++ b/dmake/qssl/ruletab.c
@@ -0,0 +1,41 @@
+/* RCS $Id: ruletab.c,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+--
+-- SYNOPSIS
+-- Default initial configuration of dmake.
+--
+-- DESCRIPTION
+-- Define here the initial set of rules that are defined before
+-- dmake performs any processing.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* These are control macros for dmake that MUST be defined at some point
+ * if they are NOT dmake will not work! These are default definitions. They
+ * may be overridden inside the .STARTUP makefile, they are here
+ * strictly so that dmake can parse the STARTUP makefile */
+
+static char *_rules[] = {
+ "MAXPROCESSLIMIT := 10",
+ "MAXLINELENGTH := 8190",
+ ".IMPORT .IGNORE: ROOTDIR",
+ ".MAKEFILES : makefile.mk Makefile makefile",
+ ".SOURCE : .NULL",
+#include "startup.h"
+ 0 };
+
+char **Rule_tab = _rules; /* for sundry reasons in Get_environment() */
diff --git a/dmake/qssl/runargv.c b/dmake/qssl/runargv.c
new file mode 100644
index 000000000000..552ce846c7e4
--- /dev/null
+++ b/dmake/qssl/runargv.c
@@ -0,0 +1,296 @@
+/* RCS $Id: runargv.c,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+--
+-- SYNOPSIS
+-- Invoke a sub process.
+--
+-- DESCRIPTION
+-- Use the standard methods of executing a sub process.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <signal.h>
+#include "extern.h"
+#include "sysintf.h"
+
+typedef struct prp {
+ char *prp_cmd;
+ int prp_group;
+ int prp_ignore;
+ int prp_last;
+ int prp_shell;
+ struct prp *prp_next;
+} RCP, *RCPPTR;
+
+typedef struct pr {
+ int pr_valid;
+ int pr_pid;
+ CELLPTR pr_target;
+ int pr_ignore;
+ int pr_last;
+ RCPPTR pr_recipe;
+ RCPPTR pr_recipe_end;
+ char *pr_dir;
+} PR;
+
+static PR *_procs = NIL(PR);
+static int _proc_cnt = 0;
+static int _abort_flg= FALSE;
+static int _use_i = -1;
+static int _do_upd = 0;
+
+static void _add_child ANSI((int, CELLPTR, int, int));
+static void _attach_cmd ANSI((char *, int, int, CELLPTR, int, int));
+static void _finished_child ANSI((int, int));
+static int _running ANSI((CELLPTR));
+
+PUBLIC int
+runargv(target, ignore, group, last, shell, cmd)
+CELLPTR target;
+int ignore;
+int group;
+int last;
+int shell;
+char *cmd;
+{
+ extern int errno;
+ int pid;
+ char **argv;
+
+ if( _running(target) /*&& Max_proc != 1*/ ) {
+ /* The command will be executed when the previous recipe
+ * line completes. */
+ _attach_cmd( cmd, group, ignore, target, last, shell );
+ return(1);
+ }
+
+ while( _proc_cnt == Max_proc )
+ if( Wait_for_child(FALSE, -1) == -1 ) Fatal( "Lost a child %d", errno );
+
+ argv = Pack_argv( group, shell, cmd );
+
+ switch( pid=fork() ){
+ int wid;
+ int status;
+
+ case -1: /* fork failed */
+ Error("%s: %s", argv[0], strerror(errno));
+ Handle_result(-1, ignore, _abort_flg, target);
+ return(-1);
+
+ case 0: /* child */
+ execvp(argv[0], argv);
+ Continue = TRUE; /* survive error message */
+ Error("%s: %s", argv[0], strerror(errno));
+ kill(getpid(), SIGTERM);
+ /*NOTREACHED*/
+
+ default: /* parent */
+ _add_child(pid, target, ignore, last);
+ }
+
+ return(1);
+}
+
+
+PUBLIC int
+Wait_for_child( abort_flg, pid )
+int abort_flg;
+int pid;
+{
+ int wid;
+ int status;
+ int waitchild;
+
+ waitchild = (pid == -1)? FALSE : Wait_for_completion;
+
+ do {
+ if( (wid = wait(&status)) == -1 ) return(-1);
+
+ _abort_flg = abort_flg;
+ _finished_child(wid, status);
+ _abort_flg = FALSE;
+ }
+ while( waitchild && pid != wid );
+
+ return(0);
+}
+
+
+PUBLIC void
+Clean_up_processes()
+{
+ register int i;
+
+ if( _procs != NIL(PR) ) {
+ for( i=0; i<Max_proc; i++ )
+ if( _procs[i].pr_valid )
+ kill(_procs[i].pr_pid, SIGTERM);
+
+ while( Wait_for_child(TRUE, -1) != -1 );
+ }
+}
+
+
+static void
+_add_child( pid, target, ignore, last )
+int pid;
+CELLPTR target;
+int ignore;
+int last;
+{
+ register int i;
+ register PR *pp;
+
+ if( _procs == NIL(PR) ) {
+ TALLOC( _procs, Max_proc, PR );
+ }
+
+ if( (i = _use_i) == -1 )
+ for( i=0; i<Max_proc; i++ )
+ if( !_procs[i].pr_valid )
+ break;
+
+ pp = _procs+i;
+
+ pp->pr_valid = 1;
+ pp->pr_pid = pid;
+ pp->pr_target = target;
+ pp->pr_ignore = ignore;
+ pp->pr_last = last;
+ pp->pr_dir = DmStrDup(Get_current_dir());
+
+ Current_target = NIL(CELL);
+
+ _proc_cnt++;
+
+ if( Wait_for_completion ) Wait_for_child( FALSE, pid );
+}
+
+
+static void
+_finished_child(pid, status)
+int pid;
+int status;
+{
+ register int i;
+ register PR *pp;
+ char *dir;
+
+ for( i=0; i<Max_proc; i++ )
+ if( _procs[i].pr_valid && _procs[i].pr_pid == pid )
+ break;
+
+ /* Some children we didn't make esp true if using /bin/sh to execute a
+ * a pipe and feed the output as a makefile into dmake. */
+ if( i == Max_proc ) return;
+ _procs[i].pr_valid = 0;
+ _proc_cnt--;
+ dir = DmStrDup(Get_current_dir());
+ Set_dir( _procs[i].pr_dir );
+
+ if( _procs[i].pr_recipe != NIL(RCP) && !_abort_flg ) {
+ RCPPTR rp = _procs[i].pr_recipe;
+
+
+ Current_target = _procs[i].pr_target;
+ Handle_result( status, _procs[i].pr_ignore, FALSE, _procs[i].pr_target );
+ Current_target = NIL(CELL);
+
+ if ( _procs[i].pr_target->ce_attr & A_ERROR ) {
+ Unlink_temp_files( _procs[i].pr_target );
+ _procs[i].pr_last = TRUE;
+ goto ABORT_REMAINDER_OF_RECIPE;
+ }
+
+ _procs[i].pr_recipe = rp->prp_next;
+
+ _use_i = i;
+ runargv( _procs[i].pr_target, rp->prp_ignore, rp->prp_group,
+ rp->prp_last, rp->prp_shell, rp->prp_cmd );
+ _use_i = -1;
+
+ FREE( rp->prp_cmd );
+ FREE( rp );
+
+ if( _proc_cnt == Max_proc ) Wait_for_child( FALSE, -1 );
+ }
+ else {
+ Unlink_temp_files( _procs[i].pr_target );
+ Handle_result(status,_procs[i].pr_ignore,_abort_flg,_procs[i].pr_target);
+
+ ABORT_REMAINDER_OF_RECIPE:
+ if( _procs[i].pr_last ) {
+ FREE(_procs[i].pr_dir );
+
+ if( !Doing_bang ) Update_time_stamp( _procs[i].pr_target );
+ }
+ }
+
+ Set_dir(dir);
+ FREE(dir);
+}
+
+
+static int
+_running( cp )
+CELLPTR cp;
+{
+ register int i;
+
+ if( !_procs ) return(FALSE);
+
+ for( i=0; i<Max_proc; i++ )
+ if( _procs[i].pr_valid &&
+ _procs[i].pr_target == cp )
+ break;
+
+ return( i != Max_proc );
+}
+
+
+static void
+_attach_cmd( cmd, group, ignore, cp, last, shell )
+char *cmd;
+int group;
+int ignore;
+CELLPTR cp;
+int last;
+int shell;
+{
+ register int i;
+ RCPPTR rp;
+
+ for( i=0; i<Max_proc; i++ )
+ if( _procs[i].pr_valid &&
+ _procs[i].pr_target == cp )
+ break;
+
+ TALLOC( rp, 1, RCP );
+ rp->prp_cmd = DmStrDup(cmd);
+ rp->prp_group = group;
+ rp->prp_ignore= ignore;
+ rp->prp_last = last;
+ rp->prp_shell = shell;
+
+ if( _procs[i].pr_recipe == NIL(RCP) )
+ _procs[i].pr_recipe = _procs[i].pr_recipe_end = rp;
+ else {
+ _procs[i].pr_recipe_end->prp_next = rp;
+ _procs[i].pr_recipe_end = rp;
+ }
+}
diff --git a/dmake/qssl/setup b/dmake/qssl/setup
new file mode 100644
index 000000000000..9aa004cd604f
--- /dev/null
+++ b/dmake/qssl/setup
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+if [ ! -d /usr/local ]; then mkdir /usr/local ; fi
+if [ ! -d /usr/local/bin ]; then mkdir /usr/local/bin ; fi
+if [ ! -d /usr/local/lib ]; then mkdir /usr/local/lib ; fi
+if [ ! -d /usr/local/lib/dmake-4.1 ]; then mkdir /usr/local/lib/dmake-4.1 ; fi
+
+
+if [ -d /usr/local/lib/dmake-4.1/startup ]
+then
+ if [ -f /usr/local/lib/dmake-4.1/startup/local.mk ]; then
+ cp /usr/local/lib/dmake-4.1/startup/local.mk /tmp/local$$
+ elif [ -d /usr/local/lib/dmake ]; then
+ if [ -f /usr/local/lib/dmake/startup/local.mk ]; then
+ cp /usr/local/lib/dmake/startup/local.mk /tmp/local$$
+ fi
+ fi
+ /bin/rm -rf /usr/local/lib/dmake-4.1/startup /usr/local/lib/dmake
+fi
+
+mkdir /usr/local/lib/dmake-4.1/startup
+
+echo "Installing Dmake into /usr/local/bin"
+
+cp dmake-4.1g/dmake /usr/local/bin/dmake-4.1;
+/bin/rm -f /usr/local/bin/dmake
+(cd /usr/local/bin; ln -s dmake-4.1 dmake; chmod a+x,og-w dmake-4.1)
+cp -r dmake-4.1g/startup /usr/local/lib/dmake-4.1/startup
+(cd /usr/local/lib; ln -s dmake-4.1 dmake)
+find /usr/local/lib/dmake-4.1 -type d -exec chmod a+x {} \;
+find /usr/local/lib/dmake-4.1 -type f -exec chmod og-w,a+r {} \;
+
+if [ -f /tmp/local$$ ]
+then
+ cp /tmp/local$$ /usr/local/lib/dmake/startup/local.mk
+fi
+
+/bin/rm -rf dmake-4.1g
+
+echo "Dmake setup is complete"
diff --git a/dmake/qssl/startup.h b/dmake/qssl/startup.h
new file mode 100644
index 000000000000..051ed555774d
--- /dev/null
+++ b/dmake/qssl/startup.h
@@ -0,0 +1,27 @@
+/* RCS $Id: startup.h,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+--
+-- SYNOPSIS
+-- Definition of MAKESTARTUP
+--
+-- DESCRIPTION
+-- Default MAKESTARTUP value defining where dmake locates the
+-- startup file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+"MAKESTARTUP := $(ROOTDIR)/usr/local/lib/dmake/startup/startup.mk",
diff --git a/dmake/qssl/stdlib.h b/dmake/qssl/stdlib.h
new file mode 100644
index 000000000000..c599d7104363
--- /dev/null
+++ b/dmake/qssl/stdlib.h
@@ -0,0 +1,48 @@
+/* RCS $Id: stdlib.h,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+--
+-- SYNOPSIS
+-- stdlib interface
+--
+-- DESCRIPTION
+-- Specially needed pieces of interface to the standard C lib.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+#ifndef _STDLIB_INCLUDED_
+#define _STDLIB_INCLUDED_
+
+extern /*GOTO*/ _exit();
+extern /*GOTO*/ exit();
+extern /*GOTO*/ abort();
+extern int system();
+extern char *getenv();
+extern char *calloc();
+extern char *malloc();
+extern char *realloc();
+
+#ifndef _AIX
+/* The AIX compiler dies on illegal redefinition of free */
+extern free();
+#endif
+
+extern int errno;
+
+#ifndef EIO
+# include <errno.h>
+#endif
+
+#endif /* _STDLIB_INCLUDED_ */
diff --git a/dmake/qssl/sysintf.h b/dmake/qssl/sysintf.h
new file mode 100644
index 000000000000..2ab5ecb63855
--- /dev/null
+++ b/dmake/qssl/sysintf.h
@@ -0,0 +1,43 @@
+/* RCS $Id: sysintf.h,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+--
+-- SYNOPSIS
+-- Interfaces for sysintf.c
+--
+-- DESCRIPTION
+-- Abstractions of functions in sysintf.c
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#define DMSTAT stat
+#define VOID_LCACHE(l,m)
+#define Hook_std_writes(A)
+#define GETPID getpid()
+#define DMSTRLWR(A,B)
+
+/*
+** standard C items
+*/
+
+/*
+** DOS interface standard items
+*/
+#define getswitchar() '-'
+
+/*
+** make parameters
+*/
diff --git a/dmake/qssl/template.mk b/dmake/qssl/template.mk
new file mode 100644
index 000000000000..e7e9837ae671
--- /dev/null
+++ b/dmake/qssl/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= qssl
+ OSRELEASE *:=
+ OSENVIRONMENT *:=
diff --git a/dmake/qssl/tempnam.c b/dmake/qssl/tempnam.c
new file mode 100644
index 000000000000..eb683da7ee4c
--- /dev/null
+++ b/dmake/qssl/tempnam.c
@@ -0,0 +1,102 @@
+/* RCS $Id: tempnam.c,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+--
+-- SYNOPSIS
+-- tempnam
+--
+-- DESCRIPTION
+-- temp file name generation routines.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/*LINTLIBRARY*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define max(A,B) (((A)<(B))?(B):(A))
+
+extern int access();
+
+static char *cpdir();
+static char seed[4]="AAA";
+
+/* BSD stdio.h doesn't define P_tmpdir, so let's do it here */
+#ifndef P_tmpdir
+static char *P_tmpdir = "/tmp";
+#endif
+
+char *
+tempnam(dir, prefix)
+char *dir; /* use this directory please (if non-NULL) */
+char *prefix; /* use this (if non-NULL) as filename prefix */
+{
+ register char *p, *q, *tmpdir;
+ int tl=0, dl=0, pl;
+
+ pl = strlen(P_tmpdir);
+
+ if( (tmpdir = getenv("TMPDIR")) != NULL ) tl = strlen(tmpdir);
+ if( dir != NULL ) dl = strlen(dir);
+
+ if( (p = malloc((unsigned)(max(max(dl,tl),pl)+16))) == NULL )
+ return(NULL);
+
+ *p = '\0';
+
+ if( (tl == 0) || (access( cpdir(p, tmpdir), 3) != 0) )
+ if( (dl == 0) || (access( cpdir(p, dir), 3) != 0) )
+ if( access( cpdir(p, P_tmpdir), 3) != 0 )
+ if( access( cpdir(p, "/tmp"), 3) != 0 )
+ return(NULL);
+
+ (void) strcat(p, "/");
+ if(prefix)
+ {
+ *(p+strlen(p)+5) = '\0';
+ (void)strncat(p, prefix, 5);
+ }
+
+ (void)strcat(p, seed);
+ (void)strcat(p, "XXXXXX");
+
+ q = seed;
+ while(*q == 'Z') *q++ = 'A';
+ ++*q;
+
+ if(*tmpnam(p) == '\0') return(NULL);
+ return(p);
+}
+
+
+
+static char *
+cpdir(buf, str)
+char *buf;
+char *str;
+{
+ char *p;
+
+ if(str != NULL)
+ {
+ (void) strcpy(buf, str);
+ p = buf - 1 + strlen(buf);
+ if(*p == '/') *p = '\0';
+ }
+
+ return(buf);
+}
diff --git a/dmake/qssl/time.h b/dmake/qssl/time.h
new file mode 100644
index 000000000000..f3ddaf7962dd
--- /dev/null
+++ b/dmake/qssl/time.h
@@ -0,0 +1,32 @@
+/* RCS $Id: time.h,v 1.1.1.1 2000-09-22 15:33:30 hr Exp $
+--
+-- SYNOPSIS
+-- time_t
+--
+-- DESCRIPTION
+-- Fix broken time_t definition.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef TIME_h
+#define TIME_h
+
+typedef long time_t; /* this is the thing we use */
+
+#endif TIME_h
+
diff --git a/dmake/quit.c b/dmake/quit.c
new file mode 100644
index 000000000000..ffb4eda74d4c
--- /dev/null
+++ b/dmake/quit.c
@@ -0,0 +1,69 @@
+/* RCS $Id: quit.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- End the dmake session.
+--
+-- DESCRIPTION
+-- Handles dmake termination.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+static void _handle_quit ANSI((char*));
+static int _dont_quit = 0;
+
+
+PUBLIC void
+Quit()/*
+======== Error or quit */
+{
+ if( _dont_quit ) return;
+
+ while( Closefile() != NIL( FILE ) );
+ Clean_up_processes();
+
+ if( Current_target != NIL(CELL) )
+ Unlink_temp_files(Current_target);
+
+ if( _dont_quit == 0 ) _handle_quit( ".ERROR" );
+
+ Set_dir( Makedir ); /* No Error message if we can't do it */
+ Epilog( ERROR_EXIT_VALUE );
+}
+
+
+static void
+_handle_quit( err_target )/*
+============================
+ Called by quit and the others to handle the execution of termination code
+ from within make */
+char *err_target;
+{
+ HASHPTR hp;
+ CELLPTR cp;
+
+ if( (hp = Get_name(err_target, Defs, FALSE)) != NIL(HASH) ) {
+ cp = hp->CP_OWNR;
+ Glob_attr |= A_IGNORE;
+
+ _dont_quit = 1;
+ cp->ce_flag |= F_TARGET;
+ Make( cp, NIL(CELL) );
+ }
+}
diff --git a/dmake/rcsclean.awk b/dmake/rcsclean.awk
new file mode 100644
index 000000000000..8fdba716bacd
--- /dev/null
+++ b/dmake/rcsclean.awk
@@ -0,0 +1,57 @@
+/^\/\* RCS/ { print "/* RCS $Id: rcsclean.awk,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $"; next }
+/^-- LOG/,/^\*\// {
+ if( ! flag ) {
+ print "-- LOG";
+ print "-- Use cvs log to obtain detailed change logs.";
+ print "*/";
+ flag = 1;
+ }
+
+ next;
+}
+/^-- SYNOPSIS --/ {
+ print "--";
+ print "-- SYNOPSIS";
+ printf "-- %s%s\n", toupper(substr($0, 16,1)), substr($0,17);
+ next;
+}
+/^-- WWW/,/^--$/ {
+ if( !wflag ) {
+ print "-- WWW";
+ print "-- http://dmake.wticorp.com/";
+ print "--";
+ wflag = 1;
+ }
+ next;
+}
+/^-- AUTHOR/,/^--$/ {
+ if( !aflag ) {
+ print "-- AUTHOR";
+ print "-- Dennis Vadura, dvadura@dmake.wticorp.com";
+ print "--";
+ aflag = 1;
+ }
+ next;
+}
+/^-- COPYRIGHT/,/^--$/ {
+ if( !wflag ) {
+ print "-- WWW";
+ print "-- http://dmake.wticorp.com/";
+ print "--";
+ wflag = 1;
+ }
+
+ if( !cflag ) {
+print "-- COPYRIGHT";
+print "-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.";
+print "-- ";
+print "-- This program is NOT free software; you can redistribute it and/or";
+print "-- modify it under the terms of the Software License Agreement Provided";
+print "-- in the file <distribution-root>/readme/license.txt.";
+print "--";
+cflag = 1;
+ }
+ next;
+}
+
+{ print; }
diff --git a/dmake/readme/intro.txt b/dmake/readme/intro.txt
new file mode 100644
index 000000000000..c68ef005dd23
--- /dev/null
+++ b/dmake/readme/intro.txt
@@ -0,0 +1,43 @@
+DMAKE 4.1 [http://dmake.wticorp.com/]
+----------------------------------------------------
+
+The dmake home page can be found at:
+
+ http://dmake.wticorp.com/
+
+Visit there for the latest in dmake related information.
+
+dmake is different from other versions of Make in that it supports significant
+enhancements (See the WWW page). A short summary of the more important
+features follows:
+
+ . support for portable makefiles
+ . portable accross many platforms
+ . significantly enhanced macro facilities
+ . sophisticated inference algorithm supporting transitive closure
+ over the inference graph
+ . support for traversing the file sytem both during making of targets
+ and during inference
+ . %-meta rules for specifying rules to be used for inferring
+ prerequisites
+ . conditional macros
+ . local rule macro variables
+ . proper support for libraries
+ . parallel making of targets on architectures that support it
+ . attributed targets
+ . text diversions
+ . group recipes
+ . swapping itself to DISK under MSDOS
+ . supports MKS extended argument passing convention
+ . directory caching
+ . highly configurable
+
+Additional information pertaining to installation can be found in either the
+
+ gold/ - sub-folder for the Dmake Gold release
+ public/ - sub-folder for the Damke public release
+
+Release notes for this release of dmake can be found in the file
+
+ release.txt
+
diff --git a/dmake/readme/license.txt b/dmake/readme/license.txt
new file mode 100644
index 000000000000..3c68f02bb420
--- /dev/null
+++ b/dmake/readme/license.txt
@@ -0,0 +1,248 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The license agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License. The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications. Each
+licensee is addressed as "you".
+
+ 1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program. You may charge a fee for the physical act of
+transferring a copy.
+
+ 2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating that
+ you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish, that
+ in whole or in part contains the Program or any part thereof, either
+ with or without modifications, to be licensed at no charge to all
+ third parties under the terms of this General Public License (except
+ that you may choose to grant warranty protection to some or all
+ third parties, at your option).
+
+ c) If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the simplest and most usual way, to print or display an
+ announcement including an appropriate copyright notice and a notice
+ that there is no warranty (or else, saying that you provide a
+ warranty) and that users may redistribute the program under these
+ conditions, and telling the user how to view a copy of this General
+ Public License.
+
+ d) You may charge a fee for the physical act of transferring a
+ copy, and you may at your option offer warranty protection in
+ exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+ 3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal charge
+ for the cost of distribution) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it. For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+ 4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License. However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+ 5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+ 7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+ 8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19xx name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ program `Gnomovision' (a program to direct compilers to make passes
+ at assemblers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/dmake/readme/public/install.txt b/dmake/readme/public/install.txt
new file mode 100644
index 000000000000..a5ee339d2730
--- /dev/null
+++ b/dmake/readme/public/install.txt
@@ -0,0 +1,203 @@
+ DMAKE UNPACKING AND INSTALLATION INSTRUCTIONS
+
+
+We attempt to keep the information presented here accurate. However, the
+defacto location of the most up to date information is the dmake WWW site
+found at:
+
+ http://dmake.wticorp.com/
+
+DMAKE is available in several formats: a compressed tar src archive,
+a pkzip src archive, a variety of executable archives. Refer to the
+appropriate section below for unpacking instructions.
+
+
+1. UNPACKING THE DISTRIBUTION FILES
+
+ OPTION 'A' (compressed tar src archive):
+ --------------------------------------
+ Assumption: The current directory contains the latest version of dmake in
+ the file 'dm41src.tgz'.
+
+ This file is a standard GNU zip compressed tar archive. To unpack the file
+ issue the following command. gunzip is available for most UNIX platforms
+ as well as DOS.
+
+ gunzip -c dm41src.tgz | tar xf -
+
+
+ OPTION 'B' (src zip archive):
+ -----------------------------
+ Assumption: The current directory contains the latest version of DMAKE in
+ the file dm41src.zip.
+
+ To unpack the full zip distribution simply use pkunzip with the
+ following command:
+
+ pkunzip dm41src.zip
+ or
+ unzip dm41src.zip
+
+
+ Instructions for unpacking executable only versions are given on the
+ dmake WWW site.
+
+
+2. BUILDING THE EXECUTABLE
+
+ Skip this step if you have purchased a prebuilt binary distribution.
+
+ The only supported method for building a new executable from a fresh or
+ patched distribution is to use the self building scripts rather than DMAKE
+ itself. This is necessary in order to allow for the use of new DMAKE
+ features and functionality in the DMAKE 'makefile' itself. Once built
+ the DMAKE executable can be used to rebuild DMAKE.
+
+ To determine the set of supported environments issue the following
+ commands:
+
+ cd src
+ make
+
+ The output of this command will be a set of arguments representing the
+ supported environments that DMAKE can be compiled in. Choose the one
+ that most closely represents your environment and issue the command:
+
+ make environ_tag
+
+ where 'environ_tag' is from the previous list, for example on a Solaris
+ System the option is Solaris, so you would issue the command 'make Solaris'.
+
+ The script runs the appropriate set of commands; upon completion the file
+ 'dmake' or 'dmake.exe' is found in the current directory.
+ This is the binary executable.
+
+ Note: before issuing the build command please read Section 3 and decide
+ if you need or want to modify the pre-compiled value of MAKESTARTUP.
+
+ During the build it is safe to ignore any warnings that may
+ be generated by your build. If you get errors from the build then
+ it is probably the case that you have chosen a build target that is
+ not compatible with your environment.
+
+
+3. INSTALLING AND CONFIGURING THE EXECUTABLE
+
+ To install the dmake executable place the executable into the
+ location where your system normally finds executables. That is
+ place dmake into a subdirectory that is or will be in your
+ executable search PATH.
+
+ You can now issue the command 'dmake -V'; the output will be
+ similar to:
+
+ dmake - Copyright (c) 1990,...,1996 by Dennis Vadura, Version 4.10, PL 0
+
+ Default Configuration:
+ MAXPROCESSLIMIT := 10
+ MAXLINELENGTH := 8190
+ .IMPORT .IGNORE: ROOTDIR
+ .MAKEFILES : makefile.mk Makefile makefile
+ .SOURCE : .NULL
+ MAKESTARTUP := $(ROOTDIR)/usr/local/lib/dmake/startup/startup.mk
+
+ Please read the file readme/release for the latest release notes.
+
+
+ Take note of the line defining the value of MAKESTARTUP; to configure
+ the executable you must perform two steps:
+
+ 1. Copy the <dmake-distdir>/startup subtree to a suitable location,
+ 2. Tell dmake where you put it,
+
+
+ Step 1:
+ -------
+ The above example build of dmake assumes that the directory path (assuming
+ ROOTDIR is NULL)
+
+ /usr/local/lib/dmake/
+
+ is a directory which contains a copy of the "<dmake-distdir>/startup"
+ subtree. Thus to properly configure dmake so that the precompiled
+ defaults would be used you would have to perform the following:
+
+ cd <dmake-distdir>
+ mkdir /usr/local/lib/dmake
+ cp -r startup /usr/local/lib/dmake
+
+ or if you are in the MSDOS or Windows-95/NT world:
+
+ cd <dmake-distdir>
+ md \usr\local\lib\dmake
+ xcopy startup \usr\local\lib\dmake
+
+ and you are done Step 1.
+
+
+ Step 2:
+ -------
+ You must tell dmake where it is that you placed the "startup" subtree. If
+ the location is the directory that is pre-compiled into dmake then you
+ are done. If the directory where you copied the dmake subtree is not the
+ precompiled value you must either set the global environment variable
+ MAKESTARTUP to point at the new location of "startup/startup.mk" or you
+ must rebuild dmake with a new precompiled value of MAKESTARTUP. To do the
+ latter create the file:
+
+ src/startup.h
+
+ and make sure that it contains an entry similar to the following:
+
+ /* This file contains the default value of the MAKESTARTUP variable.
+ * You must set the quoted string below to the default path to the startup
+ * variable, so that it gets compiled in. LEAVE ROOTDIR at the front of
+ * the path. This allows the user to customize his environment for dmake
+ * by setting up a new ROOTDIR environment variable. */
+
+ "MAKESTARTUP := $(ROOTDIR)/usr/local/lib/dmake/startup/startup.mk",
+
+ (See src/msdos/startup.h for an example). Once set properly rerun your
+ previous build. In the rare instance that your compiler has broken
+ #include search rules, the shipped "startup.h" files are located in
+ architecture specific subdirectories as described in the file
+ "readme/srcorg".
+
+
+4. DMAKE SPECIFIC ENVIRONMENT VARIABLES
+
+ Once you have built dmake, the dmake startup directory contains the file
+ "config.mk". This file contains definitions corresponding to your installed
+ target environment for the variables:
+
+ OS - Specifies the flavour of operating system.
+ OSRELEASE - Specifies the particular version of the operating
+ system.
+ OSENVIRONMENT - An optional configuration parameter for the operating
+ system release.
+
+ Appropriate values for these variables are found in the
+
+ <install-dir>/startup/templates/<OS>/<OSRELEASE>/<OSENVIRONMENT>/template.mk
+
+ file. Select the OS, OSRELEASE, and OSENVIRONMENT that best suits your
+ setup (check readme.1st) for hints on selecting the most appropriate
+ settings.
+
+ These three variables are used to determine the correct dmake configuration
+ when dmake starts up, and loads its builtin definitions from the startup
+ subtree hierarchy. The only time you should have a need to change these
+ values or the contents of the startup subtree is when you wish to supply
+ your own customized default environment or you are building dmake for a
+ new as yet unsupported target environment.
+
+
+5. LOCALE SPECIFIC CONFIGURATION
+
+ Locale specific macro definitions that are not part of the predefined macro
+ set should be placed into the file "startup/local.mk". This ensures that
+ future dmake releases will not overwrite your prior definitions. We
+ guarantee that the file "startup/local.mk" will never be part of any future
+ dmake distribution.
+
+
diff --git a/dmake/readme/public/mac.txt b/dmake/readme/public/mac.txt
new file mode 100644
index 000000000000..34a2dca5f820
--- /dev/null
+++ b/dmake/readme/public/mac.txt
@@ -0,0 +1,43 @@
+MAC specific information for dmake. This information is provided in the
+hope that it makes it easier to install and recompile dmake in a MAC
+environment.
+
+
+1. ENVIRONMENT VARIABLE SETTINGS
+
+Only a single set of settings is available for the macintosh. There are no
+sub-selections for specific OS release and/or environment.
+
+ OS - mac
+ OSRELEASE - NULL
+ OSENVIRONMENT - NULL
+
+
+2. IMPLEMENTATION NOTES
+
+This port for the Macintosh is specifically designed to be run
+under MPW.
+
+I had to make a couple of changes to dmake in order to get it to work
+on the Mac. First, MPW provides no documented way to run a
+subprocess, so when you use dmake, you MUST use the -n option and
+execute the output. Typically, you will probably want to write a
+simple script file to do these operations for you.
+
+I added some code so that the Macintosh version of dmake can
+use UNIX-style directories to specify include paths and target
+and dependency file names. I.e., if you specify a file "/dir/file",
+dmake will look at the file "dir:file". However, Mac dmake does not
+do any translation from files specified by UNIX-style directories
+in the recipe line that gets executed. If you need to translate,
+you can use substitution commands. (For example,
+":$(RELATIVEUNIXFILE:s,/,:,)".) This code was added so one could
+execute dmake's makefile, and also so one would have an easier time
+porting other UNIX makefiles. I would suggest you stick with
+Macintosh-style directories for all other makefiles.
+
+In order to run dmake, you must set (and export) the environmental
+variable "OS" to "mac".
+
+Micah Doyle
+micah@leland.Stanford.EDU
diff --git a/dmake/readme/public/msdos.txt b/dmake/readme/public/msdos.txt
new file mode 100644
index 000000000000..72664843a644
--- /dev/null
+++ b/dmake/readme/public/msdos.txt
@@ -0,0 +1,124 @@
+MSDOS specific information for dmake. This information is provided in the
+hope that it makes it easier to install and recompile dmake under MSDOS.
+I will be happy to hear of erroneous information and will make every effort
+to correct it.
+
+NOTE: If you are seeking information for Win32 compiles please refer to
+ the file "readme/winnt".
+
+
+1. ENVIRONMENT VARIABLE SETTINGS
+
+There are many environment variable settings available for MSDOS. Each
+option is described below.
+
+ OS - msdos
+
+ OSRELEASE - borland # Borland compilers
+ - microsft # Microsoft compilers
+ - zortech # zortech compilers (unsupported)
+
+ OSENVIRONMENT - tcc20 # Borland Turbo C 2.0
+ - bcc30 # Borland C++ V3.0 MSDOS compile
+ - bcc40 # Borland C++ V4.0 MSDOS compile
+ - bcc45 # Borland C++ V4.5 MSDOS compile
+ - bcc50 # Borland C++ V5.0 MSDOS compile
+
+ - msc51 # Microsoft 5.1 Compiler MSDOS compile
+ - msc60 # Microsoft 6.0 Compiler MSDOS compile
+
+ MSC_VER - 5.1 # Microsoft Compiler version
+ - 6.0 # Microsoft Compiler version
+
+
+2. IMPLEMENTATION NOTES
+
+Bootstrapping the binary:
+-------------------------
+ A make.bat file is provided to bootstrap the binary. The file contains
+ several targets for bootstrapping. Invoking the batch file with no
+ arguments lists the possibilities shown below.
+
+ INDEX: You must specify one of:
+ tccswp - Turbo C 2.0 compile of swapping dmake.
+ bcc30swp - Borland C++ 3.0 compile of swapping dmake.
+ bcc40swp - Borland C++ 4.0 compile of swapping dmake.
+ bcc45swp - Borland C++ 4.5 compile of swapping dmake.
+ bcc50swp - Borland C++ 5.0 compile of swapping dmake.
+
+ msc51 - Microsoft C 5.1 compile.
+ msc51swp - Microsoft C 5.1, MASM 5.1 compile of swapping dmake.
+ msc60 - Microsoft C 6.0 compile.
+ msc60swp - Microsoft C 6.0, MASM 5.1 compile of swapping dmake.
+
+ Based on the compiler you have installed and whether or not you
+ want the swapping version of dmake, you should select the appropriate
+ target and issue 'make.bat target'.
+
+ The batch file runs a second batch script that comes with the distribution
+ which compiles the sources using the appropriate compiler and flags. The
+ MSC Versions of the batch files should not require any further user
+ intervention during the build. The Borland versions, as a final step,
+ invoke tlink with two response files. The second of these response files,
+ named in msdos/borland/{bcc*,tcc20}/mk*.bat, contains absolute path names to
+ Borland's libraries. You likely need to edit these before getting a
+ successful binary linked. The reason for this is that not all of us
+ install the Borland compiler in the same place.
+
+ Note that the file msdos/exec.uue is a uuencoded version of a BCC++
+ compiled exec.obj (from exec.asm). If you do not have an assembler
+ either microsoft MASM or Borland TASM (or some other), you can uudecode
+ this file and put it into src/objects/exec.obj. The build will then
+ link against it to build your binary.
+
+
+Using dmake to Make itself:
+---------------------------
+ See the file "readme/install" for information on building dmake by using
+ dmake itself. Once successfully built using the presupplied scripts it
+ should be straight forward to rebuild dmake.
+
+
+Memory Requirements and Swapping:
+---------------------------------
+ The swapping code currently only swaps to DISK, there are hooks
+ in the code to accomodate XMS and EMS, but have not been used (and
+ probably never will).
+
+ It appears that a ramdisk seems to work just fine. If anyone
+ wishes to fill in the hooks please do so and send us the differences.
+
+
+^C and stopping a make:
+-----------------------
+ Thanks to the efforts of Len Reed, appears to now work. I have been unable
+ to hang my machine if it's swapped out and I hit ^C a couple thousand times.
+
+
+Other notes:
+------------
+ dmake does not care if you are running command.com or some other command
+ interpretter, you must however specify the proper values of the environment
+ variables SHELL, SHELLFLAGS, GROUPSHELL, and GROUPFLAGS in order for things
+ to work correctly. Read the man page FIRST, if you still have trouble
+ then send email.
+
+ Group recipes under DOS that use command.com as the command interpretter
+ require you to set the GROUPSUFFIX macro.
+
+ As shipped the startup.mk files for the DOS version try to figure out what
+ command interpretter you are using and set things up appropriately.
+ Two command interpretters are supported in the shipped startup.mk file,
+ command.com, and the MKS Korn shell.
+
+ The dos version of dmake contains one builtin command. noop which
+ simply ignores the remainder of the line and always retuns success,
+
+ dmake supports the MKS argument passing conventions. The facility is
+ enabled by setting .MKSARGS:=1. It is set by default in the startup.mk file
+ if an MKS Korn shell is detected as being the active command interpretter.
+
+ At this time there are no plans to support the other popular UNIX like
+ argument passing conventions available under DOS. We recommend you get
+ a copy of the MKS Toolkit from Mortice Kern Systems in Waterloo, Ontario,
+ Canada [http://www.mks.com/].
diff --git a/dmake/readme/public/os2.txt b/dmake/readme/public/os2.txt
new file mode 100644
index 000000000000..5acf4cc6ab0a
--- /dev/null
+++ b/dmake/readme/public/os2.txt
@@ -0,0 +1,76 @@
+OS/2 specific information for dmake. This information is provided in the
+hope that it makes it easier to install and recompile dmake in a OS/2
+environment.
+
+Notes on the OS/2 implementation of dmake:
+==========================================
+
+As shipped the DOS versions of dmake will run under OS/2 protected mode.
+However, support for a full OS/2 version is also provided. The OS/2 version
+will run in parallel under OS/2.
+
+Bootstrapping the binary:
+-------------------------
+ A make.cmd file is provided to bootstrap the binary. The file contains
+ several targets for bootstrapping. Invoking the batch file with no
+ arguments lists the possibilities shown below.
+
+ INDEX: You must specify one of:
+ ibm - IBM C2 compile.
+
+ The only supported compiler under OS/2 is the Visual Age ICC compiler.
+ I have tested the build using this compiler. The resulting binary
+ performs proper directory caching and file-name case mapping for cached
+ directories and is capable of parallel target builds. The only known
+ limitation of the OS/2 implementation is the treatment of library time
+ stamps. Libraries do not have time stamps on members and the timestamp
+ of the library is used instead.
+
+
+OS/2 Specifics
+--------------
+
+ There is a small number of OS/2 specific features that need to be
+ stated.
+
+ 1. The environment variables TMP as well as TMPDIR are checked for the
+ location of the directory where dmake should place any temporary files.
+ TMPDIR is checked before TMP.
+
+ 2. Appropriate limits are setup for MAXPROCESSES and buffer sizes etc.
+ See output of 'dmake -V'.
+
+ 3. By default dmake will look for the startup.mk file in the path:
+
+ $(ROOTDIR)/dmake/startup/startup.mk
+
+ This is more in keeping with OS/2 philosophy. You may still rename
+ and put it anywhere else you like by defining the MAKESTARTUP
+ environment variable.
+
+ 4. Swapping the dmake binary to disk is not supported under OS/2.
+
+
+Other notes:
+------------
+ dmake does not care if you are running cmd.exe or some other command
+ interpretter, you must however specify the proper values of the environment
+ variables SHELL, SHELLFLAGS, GROUPSHELL, and GROUPFLAGS in order for things
+ to work correctly. Read the man page first.
+
+ Group recipes under OS/2 that use cmd.exe as the command interpretter
+ require you to set the GROUPSUFFIX macro.
+
+ As shipped the startup.mk files try to figure out what
+ command interpretter you are using and set things up appropriately.
+ Two command interpretters are supported in the shipped startup.mk file,
+ cmd.exe (via COMSPEC), and the MKS Korn shell.
+
+ dmake does not contain any builtin commands. It gets all commands it
+ executes from an external file system. It is therefore most useful if it
+ is used in conjunction with an environment similar to that provided by
+ the MKS Tool kit, or equivalent.
+
+ dmake now supports the MKS argument passing conventions. The facility is
+ enabled by setting .MKSARGS:=1 and is set by default in the startup.mk file
+ if an MKS Korn shell is detected as being the active command interpretter.
diff --git a/dmake/readme/public/qssl-qnx.txt b/dmake/readme/public/qssl-qnx.txt
new file mode 100644
index 000000000000..80fc8b56aa4d
--- /dev/null
+++ b/dmake/readme/public/qssl-qnx.txt
@@ -0,0 +1,5 @@
+QNX differs from UNIX only in that the library format is that of MSDOS and
+as such the normal stating of library members does not work. QNX versions of
+dmake stat the library instead of the members (as does the MSDOS
+implementation). Otherwise see the readme/unix file for further unix related
+information.
diff --git a/dmake/readme/public/srcorg.txt b/dmake/readme/public/srcorg.txt
new file mode 100644
index 000000000000..89ff914eec4b
--- /dev/null
+++ b/dmake/readme/public/srcorg.txt
@@ -0,0 +1,74 @@
+SOURCE CODE ORGANIZATION:
+-------------------------
+The source code is organized as follows:
+
+ dmake [source for all common functions]
+ |
+ |
+ ----------------------------
+ | | | | |
+ unix tos qnx os2 msdos [source for OS specific functions]
+ | | |
+ -------------------- | -------------------
+ | | | | | | |
+386ix bsd43 sysvr[134] | tccdos bccdos mscdos [source for OSRELEASE
+ | | | specific functions]
+ | --------- ------------------
+ | | | | | |
+ | ibm mscdos bcc30 bcc32 bcc40
+ |
+ |
+ |
+ --------
+ | |
+ uw vf [source for OSENVIRONMENT specific functions]
+
+
+Each of the directories (eg. bsd43, mscdos, tccdos, and sysvr3) contain source
+that is specific to that release of the OS (and possibly C-library)
+
+
+CREATING A NEW VERSION:
+-----------------------
+To create yet another version of dmake you should follow the following steps.
+
+The sysvr3 version as sent is the base version, all dmake versions must provide
+the equivalent of the functions defined in the sysvr3 directory, and MUST
+provide the same semantics (MSDOS archive lib searches are an exception since
+we cannot search libraries for timestamps in MSDOS, Actually the MKS version
+of dmake does this, I don't have the inclination to add this code though).
+
+1. Create a new directory for the version you will be making at the level
+ that is appropriate. If it is a new OS then add the dir at the top level,
+ if it is a new version of UNIX then add it below the unix directory.
+
+2. Copy the files from the unix and unix/sysvr3 directories to the new dir.
+ (Or from any other directory sub-tree that is more appropriate)
+
+3. Not all OS/OSRELEASE combinations are compatible so in order to make
+ dmake on each, the particular directory may contain C-source for functions
+ present in the SVID SysV R3 distribution which are used by dmake but are
+ not supplied by the C-library in the target system. For example the bsd43
+ directory contains source for tempnam.c since it is not provided with
+ the BSD C-library. Before writing a new version of the source file
+ check the other directories to see if one already exists.
+
+4. Under some systems the standard include files may be missing or incorrect.
+ eg. under BSD stdarg.h and string.h. If this is the case
+ you should create the proper .h file in the proper directory.
+ This works as expected as the compile line includes the flag -Idir
+ where dir is the configuration dir, (bsd43 for example) and any
+ standard include files will be searched for in dir before the compiler
+ looks in the normal places (if you have a sane compiler :-).
+
+5. Modify dmake.sh to contain the appropriate C compiler flags and link command
+ and to include any specific C files that you have had to add for this
+ version of dmake, and run the result through the shell.
+ (make the same changes to config.mk so that once you have a working copy of
+ dmake you can use it to bring itself up to date)
+
+6. Send me the changes :-) so that I can incorporate them into future
+ distributions.
+
+7. This should be all that you require to create a new version of dmake.
+ If you have any questions send e-mail to dvadura@plg.uwaterloo.ca
diff --git a/dmake/readme/public/tos.txt b/dmake/readme/public/tos.txt
new file mode 100644
index 000000000000..ddcc43104483
--- /dev/null
+++ b/dmake/readme/public/tos.txt
@@ -0,0 +1,31 @@
+Atari TOS specific information for dmake. This information is provided in the
+hope that it makes it easier to install and recompile dmake in a TOS
+environment. I do not own an ST. As a result I rely on others to insure that
+this version of dmake works as advertized. If you have any problems with it
+please fix them and send me the differences so that I can incorporate them
+into future releases and patches.
+
+
+1. ENVIRONMENT VARIABLE SETTINGS
+
+Only a single set of settings is available for Atari TOS. There are no
+sub-selections for specific OS release and/or environment.
+
+ OS - tos
+ OSRELEASE - NULL
+ OSENVIRONMENT - NULL
+
+
+2. IMPLEMENTATION NOTES
+
+The code to compile on an Atari-ST using GCC was supplied by Edgar Roeder
+(roeder@cs.uni-sb.de). I do not have an ST on which to verify the
+distribution sources but I have no reason to believe them to not work.
+If there are any problems please let Edgar or myself know.
+
+I know of no bugs or limitation to the Atari-ST implementation. Note that
+it is similar to the DOS version but it does not swap itself out. This does
+not appear to be as much of a problem on the Atari as it is on MSDOS boxes :-).
+See the msdos specific info file for further information.
+
+-dennis
diff --git a/dmake/readme/public/unix.txt b/dmake/readme/public/unix.txt
new file mode 100644
index 000000000000..b50ab9afad1c
--- /dev/null
+++ b/dmake/readme/public/unix.txt
@@ -0,0 +1,171 @@
+UNIX specific information for dmake. This information is provided in the
+hope that it makes it easier to install and recompile dmake under UNIX.
+I will be happy to hear of erroneous information and will make every effort
+to correct it.
+
+
+1. ENVIRONMENT VARIABLE SETTINGS
+
+There are many environment variable settings available for UNIX. Each
+option is described below.
+
+ OS - unix
+
+ OSRELEASE - bsd43 # generic BSD 4.3
+ - solaris # Solaris environments
+ - sysvr1 # System V R1
+ - sysvr3 # System V R3
+ - sysvr4 # System V R4
+ - xenix # Xenix
+ - 386ix # Sun IPX 386 boxen
+ - coherent # Coherent...
+ - qnx # QNX
+
+ OSENVIRONMENT - uw # U of Waterloo mfcf environment for BSD4.3
+ - vf # for environments needing vfprintf
+ - pwd # for environments needing new pwd
+ - gcc # for GCC compiles with Solaris2.3 and greater
+ - verxx # for specific OS versions.
+
+
+The table below lists valid combinations for settings of OS, OSRELEASE, and
+OSENVIRONMENT.
+
+ OS OSRELEASE OSENVIRONMENT
+ -- --------- -------------
+ unix bsd43
+ unix bsd43 uw
+ unix bsd43 vf
+ unix solaris
+ unix solaris gcc
+ unix sysvr1
+ unix sysvr3
+ unix sysvr3 pwd
+ unix sysvr4
+ unix xenix
+ unix xenix pwd
+ unix 386ix
+ unix coherent ver40
+ unix coherent ver42
+
+You must set OS and OSRELEASE, OSENVIRONMENT to correspond to one of the
+configurations in the above table.
+
+
+2. IMPLEMENTATION NOTES
+
+Bootstrapping the binary:
+-------------------------
+ A 'makefile' file is provided to bootstrap the binary. The file contains
+ many targets for bootstrapping. Issuing 'make' will provide the list of
+ possible targets that can be built. A restricted sample is shown below:
+
+ INDEX: You must specify 'make target' where target is one of:
+ -------------
+ make bsd43 - Generic BSD 4.3 System
+ make bsd43uw - Generic BSD 4.3 at U of Waterloo
+ make bsd43vf - Generic BSD 4.3 that needs vfprintf
+ make sysvr4 - Generic SysV R4 UNIX System
+ make sysvr3 - Generic SysV R3 UNIX System
+ make sysvr3pwd - Generic SysV R3 UNIX System, our PWD
+ make sysvr1 - Generic SysV R1 UNIX System
+ make dynix - Sequent DYNIX System
+ make linux - Linux
+ make ultrix - Ultrix 3.0 System
+ make mips - Any MIPS System
+ make coherent40 - Any Coherent Version 4.0 System
+ make coherent42 - Any Coherent Version 4.2 or greater System
+ make hpux - HP Unix
+ make 386ix - 386/ix (SysV R3) System
+ make xenix - 386 Xenix System
+ make xenixpwd - 386 Xenix System, our PWD
+ make aix - IBM RS6000/AIX System
+ make Solaris - SUN Solaris 1.0 to 2.0
+ make Solaris2.1 - SUN Solaris 2.1 or greater
+ make gccSolaris2.1 - SUN Solaris 2.1 or greater with gcc
+
+ The above shows only the possible builds for UNIX like operating systems.
+ Choose the one that best suits your needs and issue the command
+
+ 'make target'
+
+
+Using dmake to Make itself:
+---------------------------
+ If you use dmake to make itself you must first set a number of makefile
+ control variables, either through the environment or on the command line.
+
+ The following variables must be set:
+
+ OS - defines operating system (must be set)
+ OSRELEASE - particular version of it.
+ OSENVIRNOMENT - more customization
+
+ These three variables should be defined in your environment. Valid values
+ for UNIX are listed above in Section 1. You must chose one a setting from
+ the table that best matches your system.
+
+ Once set simply issue the command: 'dmake' and the sources will be
+ automatically rebuilt. You do not need to specify a target when you
+ use dmake and the environment variables are correctly set.
+
+
+.NAMEMAX and length of file names:
+----------------------------------
+dmake assumes that no file name component has a name longer than .NAMEMAX
+(a user-settable variable, see the man page). Files whose basename is
+longer than .NAMEMAX return a timestamp of 0 when statted. The reason for
+this test is to handle broken versions of stat that return non-zero times
+for stating files that are longer than the legal file name length but for
+which a file whose name is the legal maximum file name length and is a prefix
+of the longer name exists. This used to cause infinite loops in the inference
+engine.
+
+As a result the value of .NAMEMAX is important. dmake attempts to determine
+it at from your system header files when compiled however sometimes even these
+may be erroneous thus as a result as of dmake 4.0 users may set the value of
+.NAMEMAX to any value they wish.
+
+
+Library Name Length:
+--------------------
+By default the maximum length of library member names is defined in the the
+ar.h header file and is usually 14. Elf libraries allow for a arbitrarily
+long member names, if your archiver supports the elf archiver extension for
+long member names then edit the file unix/arlib.c and set the CHECKELF define
+to indicate that the Elf archiver extension is to be checked for.
+
+If Elf is not supported and your archiver truncates member names you should
+set (in unix/arlib.c) the macro AR_TRUNCATE_MEMBER_NAMES. dmake will then
+also truncate member names and perform a length limitted comparison when
+scanning the library for matching member names.
+
+
+UNIX Sysv R3 and getcwd:
+------------------------
+Some versions of UNIX SysV R3 and Xenix use the popen call to capture the
+output of pwd when invoking the C library function getcwd(). These versions
+of the function cause dmake to terminate with the "lost a child" message
+due to the fact that the parent dmake process may catch the pwd and not
+recognize it as a child. For systems that have this problem use the version
+of dmake that supplies its own getcwd function. The settings are:
+
+ OS = unix
+ OSRELEASE = sysvr3
+ OSENVIRONMENT = pwd
+
+It is directly available through the 'makefile' by typing one of:
+
+ make sysvr3pwd
+ make xenixpwd
+
+both include the getcwd code but the xenixpwd target compiles for a Xenix
+system.
+
+
+UNIX and "limits.h":
+--------------------
+Some compilers do not yet provide the "limits.h" file, if yours is one of
+these then simply copy the file "namemax.h" in the source root directory to
+"limits.h". Make sure the length of a file name is correctly set in
+"limits.h" as it is processed prior to "namemax.h".
diff --git a/dmake/readme/read1st.txt b/dmake/readme/read1st.txt
new file mode 100644
index 000000000000..4c981d5f818d
--- /dev/null
+++ b/dmake/readme/read1st.txt
@@ -0,0 +1,41 @@
+DMAKE 4.1 [http://dmake.wticorp.com/]
+-------------------------------------
+
+This directory tree contains a number of files. Here is a short
+description of what each file contains so that you do not need to
+search as much. There is also a recommended order for reading them.
+
+ read1st.txt - index of files found in the readme directory.
+ intro.txt - short note describing what 'dmake' is and where to
+ get it from.
+ release.txt - changes from previous release, and release specific
+ notes.
+ ../man - directory containing DMAKE manual page.
+
+ patchX - release notes for patchX to the current release.
+
+ gold/install.txt - installation instructions for the Dmake Gold release
+ public/install.txt - installation files for the Dmake public release
+
+The next group of files provides additional information for specific
+platforms. These are found in the appropriate gold and public release
+sub-folders.
+
+ apple.mac - information for macintosh users
+ atari.tos - information for ATARI TOS users
+ msdos - information for MSDOS users
+ winnt - information for Win95 and WinNT users
+ os2 - information for OS/2 users
+ unix - information for UNIX users
+ qssl-qnx - information for QNX users
+ srcorg - information on the source code organization
+
+You should read the information in the first group of files. The
+second group of files contains platform specific configuration
+information and information that may assist you in building dmake on
+the related target system. You need to read the relevant file only if
+you are building the dmake executable from the source distribution
+using 'dmake' itself, or if you want to create a new version of dmake.
+
+You can also obtain relevant dmake information by checking out the
+Official Dmake Web pages at "http://dmake.wticorp.com/".
diff --git a/dmake/readme/release.txt b/dmake/readme/release.txt
new file mode 100644
index 000000000000..65a250dee881
--- /dev/null
+++ b/dmake/readme/release.txt
@@ -0,0 +1,194 @@
+DMAKE Version 4.1
+=================
+FINAL FREE RELEASE OF DMAKE, REPLACES VERSION 4.0
+
+Nature: This distribution advances dmake to Version 4.1, patch level 0.
+------- This release adds significant functionality and eliminates
+ bugs that were introduced with release 4.0.
+
+
+DETAILS OF ENHANCEMENTS/TWEAKS:
+===============================
+
+BUG FIXES:
+----------
+
+1. General clean up all over to fix small incompatibilities and obvious
+ typos.
+
+2. Fixed bug in getinp.c where buffer was being erroneously overwritten,
+ this caused the invalidation of the return address on the stack on
+ DOS systems.
+
+3. Fixed a bug that caused the "<target> is up to date" message to be
+ suppressed.
+
+4. Fixed a bug involving the value of $@ in conjunction with dynamic
+ prerequisites.
+
+5. Relegated the warning associated with duplicate entries in prerequisite
+ lists to a non-essential warning. Added an option flag -Vw to display
+ it if you wish to check your makefile for duplicate entries. Either way
+ the parser ignores duplicates.
+
+6. Better default action on checking out RCS targets. If an RCS target has
+ no directory prefix of its own it is checked out into the directory
+ which contains the RCS subdirectory, otherwise it ends up in its directory
+ qualified location.
+
+7. Improved the speed of lookups in the directory cache; handle mixed case
+ file name entries on OS/2 and Win95/NT.
+
+8. Improved prerequisite list generation for long prerequisite lists.
+
+9. Rearanged startup macro files to form an architectural hierarchy.
+ This greatly simplifies the maintenance of the startup files. They
+ might even be right at some point in the future. Please let me know if
+ you encounter difficulties, as I don't have access to all possible
+ platforms, this sub-hierarchy is bound to have ommisions at this release
+ and hence is intended to be evolutionary over time.
+
+10. A build that only touches targets (-t) uses the same algorithm to decide
+ valid names as a normal build.
+
+11. Conditional macro assignments fixed, and now work for builtin macro
+ variables as well.
+
+
+NEW FEATURES:
+-------------
+
+0. Complete reorganization of Dmake STARTUP scripts. Please refer to the
+ installation notes for details. THIS ONE IS IMPORTANT!!!
+
+1. Support for long archive member names if Elf is available, plus better
+ support for archivers that truncate member names (see comments in
+ unix/arlib.c for details).
+
+2. Added variable MAKEVERSION which contains a string indicating the current
+ version of dmake.
+
+3. Added the .EXECUTE attribute, see man page for details.
+
+4. Added the .ERRREMOVE attribute, see man page for details.
+
+5. Added support for gmake style if/else/endif, but only if not part of
+ a Group recipe.
+
+6. Added initial build target for Coherent version 4.2 UNIX
+ and for Windows-NT/Windows-95 32-bit app using Borland C++ 4.0,4.5, 5.0,
+ and Microsoft Visual C++ 4.0.
+
+7. MSDOS version now supports two builtin runtime commands, noop, and echo.
+
+8. Added new macro $(uniq list) which returns a sorted version of the
+ white space separated tokens in list such that there are no repetitions.
+
+9. Added the function macro $(echo list) which simply returns list.
+ This is most useful in conjunction with the new $(foreach ...)
+ function macro.
+
+10. Added gmake style function macro
+
+ $(foreach,var,list data)
+
+ where var and list are expanded, and the result is the concatenation of
+ expanding data with var being set to each white space separated token in
+ list in turn. For example:
+
+ list = a b c
+ all :
+ echo [$(foreach,i,$(list) [$i])]
+
+ will output
+
+ [[a] [b] [c]]
+
+ The iterator variable is defined as a local variable to this foreach
+ instance. The following expression illustrates this:
+
+ $(foreach,i,$(foreach,i,$(sort c a b) root/$i) [$i/f.h])
+
+ when evaluated the result is:
+
+ [root/a/f.h] [root/b/f.h] [root/c/f.h]
+
+ The specification of list must be a valid macro expression, such as:
+
+ $($(assign list=a b c))
+ $(sort d a b c)
+ $(echo a b c)
+
+ and cannot just be the list itself. That is, the following foreach
+ expression:
+
+ $(foreach,i,a b c [$i])
+
+ yields:
+
+ "b c [a]"
+
+ when evaluated.
+
+11. Added the macro $(and list).
+
+12. Added the macro $(or list).
+
+13. Added the macro $(not term).
+
+14. Added the .NOINFER attribute to the .INCLUDE directive. When specified
+ any prerequisite of the .INCLUDE directive which cannot be found in
+ the .INCLUDEDIRS search list is not automatically made.
+
+15. Improved the handling of internal macros for proper functioning of the *=
+ and *:= assignment constructs. Macros that are internally initially
+ defined are considered to be undefined for the purpose of *= and *:=
+ assignment until they are the target of an explicit assignment operation.
+
+16. Improved the caching of file names, and their matching on case insensitive
+ file systems. Two control macros help to manage the functionality:
+
+ .DIRCACHE := yes
+
+ Implies that the directory cache will be used. This is on by default for
+ systems that support the reading of directories. Setting the value of this
+ macro to 'no' is equivalent to supplying the '-d' command line switch.
+
+ .DIRCACHERESPCASE := yes
+
+ Causes dmake to respect the case of the directory entries when the cache
+ is enabled, thereby treating directory entries in a case sensitive manner.
+ Setting this to 'no' disables the matching of case. This macro has effect
+ only if .DIRCACHE := yes. Otherwise the facilities provided by the native
+ OS are used to match file names using 'stat'.
+
+17. Added parameterized user defined function macros. Yes it's true
+ you may now define your own parametized function macros. Here is
+ how it works. Any macro that is not a predefined function macro and
+ is invoked with parameters is looked up as a user defined function
+ macro. A new macro scope is created. The n'th argument to the
+ macro is then assigned to the value of the the macro $n where n is 0
+ for the first argument, 1 for the second argument and so on. The
+ argument is expanded before it is assigned. The original macro is
+ then expanded. For example:
+
+ FOO = a $0 b $1 c $2 d
+ echo :; $(FOO x y z)
+
+ Will produce the result string "a z b y c z d". The
+ expansion of $(FOO) on it's own behaves as expected and returns the
+ string "a b c d" (assuming that each of $0, $1, $2
+ are undefined). The only restriction when specifying function
+ macro arguments is as before: they cannot contain spaces
+ themselves.
+
+
+ACKNOWLEDGEMENTS:
+=================
+ Thanks to all who submitted code for new features, suggestions for
+ improvements, and bug fixes. I have tried to make sure no gotchas
+ remain, if you encounter problems installing or running dmake please
+ let me know. As always, I am always happy to receive e-mail.
+
+ Many have contributed suggestions and bug fixes that make this
+ release possible. The NET thanks you.
diff --git a/dmake/rulparse.c b/dmake/rulparse.c
new file mode 100644
index 000000000000..f0e9f0cb390f
--- /dev/null
+++ b/dmake/rulparse.c
@@ -0,0 +1,1473 @@
+/* RCS $Id: rulparse.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Perform semantic analysis on input
+--
+-- DESCRIPTION
+-- This code performs semantic analysis on the input, and builds
+-- the complex internal datastructure that is used to represent
+-- the user makefile.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+/* prototypes for local functions */
+static void _add_global_prereq ANSI((CELLPTR));
+static int _add_root ANSI((CELLPTR));
+static CELLPTR _build_graph ANSI((int, CELLPTR, CELLPTR));
+static char* _build_meta ANSI((char*));
+static int _do_magic ANSI((int, char*, CELLPTR, CELLPTR, t_attr, char*));
+static void _do_special ANSI((int, int, t_attr,char*,CELLPTR,CELLPTR,int*));
+static int _do_targets ANSI((int, t_attr, char*, CELLPTR, CELLPTR));
+static t_attr _is_attribute ANSI((char*));
+static int _is_special ANSI((char*));
+static char* _is_magic ANSI((char*));
+static int _is_percent ANSI((char*));
+static CELLPTR _make_multi ANSI((CELLPTR));
+static CELLPTR _replace_cell ANSI((CELLPTR,CELLPTR,CELLPTR));
+static void _set_attributes ANSI((t_attr, char*, CELLPTR ));
+static void _stick_at_head ANSI((CELLPTR, CELLPTR));
+static void _set_global_attr ANSI((t_attr));
+
+
+/* static variables that must persist across invocation of Parse_rule_def */
+static CELLPTR _sv_targets = NIL(CELL);
+static STRINGPTR _sv_rules = NIL(STRING);
+static STRINGPTR _sv_crule = NIL(STRING);
+static CELLPTR _sv_edgel = NIL(CELL);
+static LINKPTR _sv_glb_prq = NIL(LINK);
+static int _sp_target = FALSE;
+static t_attr _sv_attr;
+static int _sv_flag;
+static int _sv_op;
+static char *_sv_setdir;
+static char _sv_globprq_only = 0;
+
+/* Define for global attribute mask */
+#define A_GLOB (A_PRECIOUS | A_SILENT | A_IGNORE | A_EPILOG | A_SWAP |\
+ A_SHELL | A_PROLOG | A_NOINFER | A_SEQ | A_MKSARGS )
+
+
+PUBLIC int
+Parse_rule_def( state )/*
+=========================
+ Parse the rule definition contained in Buffer, and modify the state
+ if appropriate. The function returns 0, if the definition is found to
+ be an illegal rule definition, and it returns 1 if it is a rule definition.
+ */
+int *state;
+{
+ TKSTR input; /* input string struct for token search */
+ CELLPTR targets; /* list of targets if any */
+ CELLPTR prereq; /* list of prereq if any */
+ CELLPTR prereqtail; /* tail of prerequisite list */
+ CELLPTR cp; /* temporary cell pointer for list making */
+ char *result; /* temporary storage for result */
+ char *tok; /* temporary pointer for tokens */
+ char *set_dir; /* value of setdir attribute */
+ char *brk; /* break char list for Get_token */
+ char *firstrcp; /* first recipe line, from ; in rule line */
+ t_attr attr; /* sum of attribute flags for current tgts*/
+ t_attr at; /* temp place to keep an attribute code */
+ int op; /* rule operator */
+ int special; /* indicate special targets in rule */
+ int percent; /* indicate percent rule target */
+ int mixed_glob_prq; /* indicate mixed %-rule prereq possible */
+
+ DB_ENTER( "Parse_rule_def" );
+
+ op = 0;
+ attr = 0;
+ special = 0;
+ percent = 0;
+ set_dir = NIL( char );
+ targets = NIL(CELL);
+ prereq = NIL(CELL);
+ prereqtail = NIL(CELL);
+ mixed_glob_prq = 0;
+
+ /* Check to see if the line is of the form:
+ * targets : prerequisites; first recipe line
+ * If so remember the first_recipe part of the line. */
+
+ firstrcp = strchr( Buffer, ';' );
+ if( firstrcp != NIL( char ) ) {
+ *firstrcp++ = 0;
+ firstrcp = DmStrSpn( firstrcp, " \t" );
+ }
+
+ result = Expand( Buffer );
+ for( brk=strchr(result,'\\'); brk != NIL(char); brk=strchr(brk,'\\') )
+ if( brk[1] == '\n' )
+ *brk = ' ';
+ else
+ brk++;
+
+ DB_PRINT( "par", ("Scanning: [%s]", result) );
+
+ SET_TOKEN( &input, result );
+ brk = ":-^!|";
+ Def_targets = TRUE;
+
+ /* Scan the input rule line collecting targets, the operator, and any
+ * prerequisites. Stop when we run out of targets and prerequisites. */
+
+ while( *(tok = Get_token( &input, brk, TRUE )) != '\0' )
+ if( !op ) {
+ /* we are scanning targets and attributes
+ * check to see if token is an operator. */
+
+ op = Rule_op( tok );
+
+ if( !op ) {
+ /* define a new cell, or get old cell */
+ cp = Def_cell( tok );
+ DB_PRINT( "par", ("tg_cell [%s]", tok) );
+
+ if( (at = _is_attribute(tok)) != 0 ) {
+ /* Logically OR the attributes specified into one main
+ * ATTRIBUTE mask. */
+
+ if( at == A_SETDIR )
+ if( set_dir != NIL( char ) )
+ Warning( "Multiple .SETDIR attribute ignored" );
+ else
+ set_dir = DmStrDup( tok );
+
+ attr |= at;
+ }
+ else {
+ int tmp;
+
+ tmp = _is_special( tok );
+ if( _is_percent( tok ) ) percent++;
+
+ if( percent )
+ cp->ce_flag |= F_PERCENT;
+
+ if( special )
+ Fatal( "Special target must appear alone", tok );
+ else if( !(cp->ce_flag & F_MARK) ) {
+ /* Targets are kept in this list in lexically sorted order.
+ * This allows for easy equality comparison of target
+ * sets.*/
+ CELLPTR prev,cur;
+ for(prev=NIL(CELL),cur=targets;cur;prev=cur,cur=cur->ce_link)
+ if(strcmp(cur->CE_NAME,cp->CE_NAME) > 0)
+ break;
+
+ cp->ce_link = cur;
+
+ if (!prev)
+ targets = cp;
+ else
+ prev->ce_link = cp;
+
+ cp->ce_flag |= F_MARK | F_EXPLICIT;
+ special = tmp;
+ }
+ }
+ }
+ else {
+ /* found an operator so empty out break list
+ * and clear mark bits on target list, setting them all to F_USED*/
+
+ brk = "";
+ for( cp=targets; cp != NIL(CELL); cp=cp->ce_link ) {
+ cp->ce_flag ^= F_MARK;
+ cp->ce_flag |= F_USED;
+ }
+
+ Def_targets = FALSE;
+ }
+ }
+ else {
+ /* Scanning prerequisites so build the prerequisite list. We use
+ * F_MARK flag to make certain we have only a single copy of the
+ * prerequisite in the list */
+
+ cp = Def_cell( tok );
+
+ if( _is_percent( tok ) ) {
+ if( !percent && !attr )
+ Fatal( "Syntax error in %% rule, missing %% target");
+ mixed_glob_prq = 1;
+ }
+
+ if( cp->ce_flag & F_USED ) {
+ if( cp->ce_attr & A_COMPOSITE )
+ continue;
+ else
+ Fatal( "Detected circular dependency in graph at [%s]",
+ cp->CE_NAME );
+ }
+ else if( !(cp->ce_flag & F_MARK) ) {
+ DB_PRINT( "par", ("pq_cell [%s]", tok) );
+ cp->ce_flag |= F_MARK;
+
+ if( prereqtail == NIL(CELL) ) /* keep prereq's in order */
+ prereq = cp;
+ else
+ prereqtail->ce_link = cp;
+
+ prereqtail = cp;
+ cp->ce_link = NIL(CELL);
+ }
+ else if( !(cp->ce_attr & A_LIBRARY) && (Verbose & V_WARNALL))
+ Warning("Duplicate entry [%s] in prerequisite list",cp->CE_NAME);
+ }
+
+ /* Check to see if we have a percent rule that has only global
+ * prerequisites. If so then set the flag so that later on, we don't issue
+ * an error if such targets supply an empty set of rules. */
+
+ if( percent && !mixed_glob_prq && (prereq != NIL(CELL)) )
+ _sv_globprq_only = 1;
+
+ /* It's ok to have targets with attributes, and no prerequisites, but it's
+ * not ok to have no targets and no attributes, or no operator */
+
+ if( !op ) {
+ CLEAR_TOKEN( &input );
+ DB_PRINT( "par", ("Not a rule [%s]", Buffer) );
+ DB_RETURN( 0 );
+ }
+
+ if( !attr && targets == NIL(CELL) ) {
+ Fatal( "Missing targets or attributes in rule" );
+ if( set_dir != NIL( char )) FREE( set_dir );
+ DB_RETURN( 0 );
+ }
+
+ /* We have established we have a legal rules line, so we must process it.
+ * In doing so we must handle any special targets. Special targets must
+ * appear alone possibly accompanied by attributes.
+ * NOTE: special != 0 ==> targets != NIL(CELL) */
+
+ if( prereqtail != NIL(CELL) ) prereqtail->ce_link = NIL(CELL);
+
+ /* Clear out MARK bits used in duplicate checking. I originally wanted
+ * to do this as the lists get processed but that got too error prone
+ * so I bit the bullit and added these two loops. */
+
+ for( cp=prereq; cp != NIL(CELL); cp=cp->ce_link ) cp->ce_flag &= ~F_MARK;
+ for( cp=targets; cp != NIL(CELL); cp=cp->ce_link ) cp->ce_flag &= ~F_USED;
+
+ /* Check to see if the previous rule line was bound if, not the call
+ * Bind_rules_to_targets to go and bind the line */
+
+ if( _sv_rules != NIL(STRING) ) Bind_rules_to_targets( F_DEFAULT );
+
+ /* Add the first recipe line to the list */
+ if( firstrcp != NIL( char ) )
+ Add_recipe_to_list( firstrcp, TRUE, FALSE );
+
+ /* Save these prior to calling _do_targets, since _build_graph needs the
+ * _sv_setdir value for matching edges. */
+ _sv_op = op;
+ _sv_setdir = set_dir;
+
+ if( special )
+ _do_special( special, op, attr, set_dir, targets, prereq, state );
+ else
+ *state = _do_targets( op, attr, set_dir, targets, prereq );
+
+ DB_RETURN( 1 );
+}
+
+
+PUBLIC int
+Rule_op( op )/*
+================
+ Check the passed in op string and map it to one of the rule operators */
+char *op;
+{
+ int ret = 0;
+
+ DB_ENTER( "rule_op" );
+
+ if( *op == TGT_DEP_SEP ) {
+ ret = R_OP_CL;
+ op++;
+
+ /* All rule operations begin with a :, but may include any one of the
+ * four modifiers. In order for the rule to be properly mapped we must
+ * check for each of the modifiers in turn, building up our return bit
+ * string. */
+
+ while( *op && ret )
+ switch( *op ) {
+ case ':': ret |= R_OP_DCL; op++; break;
+ case '!': ret |= R_OP_BG; op++; break;
+ case '^': ret |= R_OP_UP; op++; break;
+ case '-': ret |= R_OP_MI; op++; break;
+ case '|': ret |= R_OP_OR; op++; break;
+
+ default : ret = 0; /* an invalid modifier, chuck whole string */
+ }
+
+ if( *op != '\0' ) ret = 0;
+ }
+
+ DB_RETURN( ret );
+}
+
+
+PUBLIC void
+Add_recipe_to_list( rule, white_too, no_check )/*
+=================================================
+ Take the provided string and add it to the list of recipe lines
+ we are saving to be added to the list of targets we have built
+ previously. If white_too == TRUE add the rule EVEN IF it contains only
+ whitespace. */
+char *rule;
+int white_too;
+int no_check;
+{
+ DB_ENTER( "Add_recipe_to_list" );
+
+ if( rule != NIL( char ) && (*rule != '\0' || white_too) ) {
+ DB_PRINT( "par", ("Adding recipe [%s]", rule) );
+ _sv_crule = Def_recipe( rule, _sv_crule, white_too, no_check );
+
+ if( _sv_rules == NIL(STRING) )
+ _sv_rules = _sv_crule;
+ }
+
+ DB_VOID_RETURN;
+}
+
+
+PUBLIC void
+Bind_rules_to_targets( flag )/*
+===============================
+ Take the rules we have defined and bind them with proper attributes
+ to the targets that were previously defined in the parse. The
+ attributes that get passed here are merged with those that are were
+ previously defined. (namely F_SINGLE) */
+int flag;
+{
+ CELLPTR tg; /* pointer to current target in list */
+ LINKPTR lp; /* pointer to link cell */
+ int magic; /* TRUE if target is .xxx.yyy form */
+ int tflag; /* TRUE if we assigned targets here */
+
+ DB_ENTER( "Bind_rules_to_targets" );
+
+ /* This line is needed since Parse may call us twice when the last
+ * GROUP rule appears at the end of file. In this case the rules
+ * have already been bound and we want to ignore them. */
+
+ if( _sv_targets == NIL(CELL) ) { DB_VOID_RETURN; }
+
+ tflag = FALSE;
+ flag |= (_sv_flag & F_SINGLE);
+ flag |= ((_sv_attr & A_GROUP) ? F_GROUP : 0);
+
+ for( tg = _sv_targets; tg != NIL(CELL); tg = tg->ce_link ) {
+ DB_PRINT( "par", ("Binding to %s, %04x", tg->CE_NAME, tg->ce_flag) );
+ magic = tg->ce_flag & F_PERCENT;
+
+#if 0
+ /* Check to see if we had a rule of the form '%.o : a.h b.h ; xxx'
+ * In which case we must build a NULL prq node to hold the recipe */
+ if( _sv_globprq_only && (_sv_rules != NIL(STRING)) )
+ _build_graph( _sv_op, tg, NIL(CELL) );
+#endif
+
+ /* NOTE: For targets that are magic we ignore any previously defined
+ * rules. ie. We throw away the old definition and use the new.*/
+ if( !(tg->ce_flag & F_MULTI) && !magic && (tg->CE_RECIPE != NIL(STRING))
+ && !_sp_target && (_sv_rules != NIL(STRING)) )
+ Fatal( "Multiply defined recipe for target %s", tg->CE_NAME );
+
+ if( (magic || _sp_target) && (_sv_rules == NIL(STRING)) &&
+ !(tg->ce_flag & F_SPECIAL) && !_sv_globprq_only )
+ Warning( "Empty recipe for special target %s", tg->CE_NAME );
+
+ if( magic ) {
+ CELLPTR ep;
+
+ for( ep=_sv_edgel; ep != NIL(CELL); ep=ep->ce_link ) {
+ _set_attributes( _sv_attr, _sv_setdir, ep );
+ ep->ce_flag |= (F_TARGET|flag);
+
+ if( _sv_rules != NIL(STRING) ) {
+ ep->ce_recipe = _sv_rules;
+ ep->ce_indprq = _sv_glb_prq;
+ }
+ }
+ }
+ else {
+ tg->ce_attr |= _sv_attr;
+ tg->ce_flag |= flag;
+
+ if( _sv_rules != NIL(STRING) ) {
+ tg->ce_recipe = _sv_rules;
+ tg->ce_flag |= F_RULES | F_TARGET;
+
+ /* Bind the current set of prerequisites as belonging to the
+ * original recipe given for the target */
+ for( lp=tg->ce_prq; lp != NIL(LINK); lp = lp->cl_next )
+ if( !(lp->cl_flag & F_USED) ) lp->cl_flag |= F_TARGET;
+ }
+ else for( lp=tg->ce_prq; lp != NIL(LINK); lp = lp->cl_next )
+ lp->cl_flag |= F_USED;
+ }
+
+ tflag |= _add_root(tg);
+ }
+
+ if( tflag ) Target = TRUE;
+ if( _sv_setdir ) FREE(_sv_setdir);
+ _sv_rules = NIL(STRING);
+ _sv_crule = NIL(STRING);
+ _sv_targets = NIL(CELL);
+ _sv_glb_prq = NIL(LINK);
+ _sv_edgel = NIL(CELL);
+ _sp_target = FALSE;
+ _sv_globprq_only = 0;
+
+ DB_VOID_RETURN;
+}
+
+
+
+PUBLIC int
+Set_group_attributes( list )/*
+==============================
+ Scan list looking for the standard @ and - (as in recipe line defs)
+ and set the flags accordingly so that they apply when we bind the
+ rules to the appropriate targets. */
+char *list;
+{
+ int res = FALSE;
+
+ if ( !((_sv_attr|Glob_attr)&A_IGNOREGROUP) ) {
+ res = (*DmStrSpn(list,"@-%+ \t") == '[');
+ if( res ) _sv_attr |= Rcp_attribute(list);
+ }
+
+ return(res);
+}
+
+
+static void
+_do_special( special, op, attr, set_dir, target, prereq, state )/*
+==================================================================
+ Process a special target. So far the only special targets we have
+ are those recognized by the _is_special function.
+
+ target is always only a single special target.
+
+ NOTE: For the cases of .IMPORT, and .INCLUDE, the cells created by the
+ parser are never freed. This is due to the fact that it is too much
+ trouble to get them out of the hash table once they are defined, and
+ if they are per chance used again it will be ok, anyway, since the
+ cell is not really used by the code below. */
+
+int special;
+int op;
+t_attr attr;
+char *set_dir;
+CELLPTR target;
+CELLPTR prereq;
+int *state;
+{
+ HASHPTR hp; /* pointer to macro def cell */
+ CELLPTR cp; /* temporary pointer into cells list */
+ CELLPTR dp; /* pointer to directory dir cell */
+ LINKPTR lp; /* pointer at prerequisite list */
+ char *dir; /* current dir to prepend */
+ char *path; /* resulting path to try to read */
+ char *name; /* File name for processing a .INCLUDE */
+ char *tmp; /* temporary string pointer */
+ FILE *fil; /* File descriptor returned by Openfile */
+
+ DB_ENTER( "_do_special" );
+
+ target->ce_flag = F_SPECIAL; /* mark the target as special */
+
+ switch( special ) {
+ case ST_EXPORT:
+ for( ; prereq != NIL(CELL); prereq = prereq->ce_link ) {
+ DB_PRINT( "par", ("Exporting [%s]", prereq->CE_NAME) );
+ hp = GET_MACRO( prereq->CE_NAME );
+
+ if( hp != NIL(HASH) ) {
+ char *tmpstr = hp->ht_value;
+
+ if( tmpstr == NIL(char) ) tmpstr = "";
+
+ if( Write_env_string( prereq->CE_NAME, tmpstr ) != 0 )
+ Warning( "Could not export %s", prereq->CE_NAME );
+ }
+ }
+ break;
+
+ /* Simply cause the parser to fail on the next input read */
+ case ST_EXIT:
+ Skip_to_eof = TRUE;
+ break;
+
+ case ST_IMPORT:
+ for( ; prereq != NIL(CELL); prereq = prereq->ce_link ) {
+ char *tmpstr;
+
+ DB_PRINT( "par", ("Importing [%s]", prereq->CE_NAME) );
+
+ if( strcmp(prereq->CE_NAME, ".EVERYTHING") == 0 ) {
+ t_attr sattr = Glob_attr;
+ Glob_attr |= A_SILENT;
+
+ ReadEnvironment();
+
+ Glob_attr = sattr;
+ }
+ else {
+ tmpstr = Read_env_string( prereq->CE_NAME );
+
+ if( tmpstr != NIL(char) )
+ Def_macro(prereq->CE_NAME, tmpstr, M_EXPANDED|M_LITERAL);
+ else
+ if( !((Glob_attr | attr) & A_IGNORE) )
+ Fatal("Imported macro `%s' not found",prereq->CE_NAME);
+ }
+ }
+
+ attr &= ~A_IGNORE;
+ break;
+
+ case ST_INCLUDE:
+ {
+ int pushed = FALSE;
+ int first = (attr & A_FIRST);
+ int ignore = (((Glob_attr | attr) & A_IGNORE) != 0);
+ int found = FALSE;
+ int noinf = (attr & A_NOINFER);
+ LINKPTR prqlnk = NIL(LINK);
+ LINKPTR prqlst = NIL(LINK);
+
+ if( prereq == NIL(CELL) ) Fatal( "No .INCLUDE file(s) specified" );
+
+ dp = Def_cell( ".INCLUDEDIRS" );
+
+ if( (attr & A_SETDIR) && *(dir = strchr(set_dir, '=')+1) )
+ pushed = Push_dir( dir, ".INCLUDE", ignore );
+
+ for( cp=prereq; cp != NIL(CELL); cp = cp->ce_link ) {
+ LINKPTR ltmp;
+ TALLOC(ltmp, 1, LINK);
+ ltmp->cl_prq = cp;
+
+ if( prqlnk == NIL(LINK) )
+ prqlst = ltmp;
+ else
+ prqlnk->cl_next = ltmp;
+
+ prqlnk = ltmp;
+ }
+
+ for( ; prqlst != NIL(LINK); FREE(prqlst), prqlst=prqlnk ) {
+ prqlnk = prqlst->cl_next;
+ cp = prqlst->cl_prq;
+ name = cp->CE_NAME;
+
+ /* Leave this here, it ensures that prqlst gets propely free'd */
+ if ( first && found )
+ continue;
+
+ if( *name == '<' ) {
+ /* We have a file name enclosed in <....>
+ * so get rid of the <> arround the file name */
+
+ name++;
+ if( (tmp = strrchr( name, '>' )) != NIL( char ) )
+ *tmp = 0;
+
+ if( If_root_path( name ) )
+ fil = Openfile( name, FALSE, FALSE );
+ else
+ fil = NIL(FILE);
+ }
+ else
+ fil = Openfile( name, FALSE, FALSE );
+
+ if( fil == NIL(FILE) ) { /*if true ==> not found in current dir*/
+
+ /* Now we must scan the list of prerequisites for .INCLUDEDIRS
+ * looking for the file in each of the specified directories.
+ * if we don't find it then we issue an error. The error
+ * message is suppressed if the .IGNORE attribute of attr is
+ * set. If a file is found we call Parse on the file to
+ * perform the parse and then continue on from where we left
+ * off. */
+
+ for(lp=dp->CE_PRQ; lp && fil == NIL(FILE); lp=lp->cl_next) {
+ dir = lp->cl_prq->CE_NAME;
+ if( strchr(dir, '$') ) dir = Expand(dir);
+ path = Build_path( dir, name );
+
+ DB_PRINT( "par", ("Trying to include [%s]", path) );
+
+ fil = Openfile( path, FALSE, FALSE );
+ if( dir != lp->cl_prq->CE_NAME ) FREE(dir);
+ }
+ }
+
+ if (!noinf && fil == NIL(FILE)) {
+ t_attr glob = Glob_attr;
+ t_attr cattr = prqlst->cl_prq->ce_attr;
+
+ prqlst->cl_next = NIL(LINK);
+ Glob_attr |= ((attr&A_IGNORE)|A_SILENT);
+ prqlst->cl_prq->ce_attr &= ~A_FRINGE;
+
+ fil = TryFiles(prqlst);
+
+ Glob_attr = glob;
+ prqlst->cl_prq->ce_attr |= (cattr & A_FRINGE);
+ }
+
+ if( fil != NIL(FILE) ) {
+ Parse( fil );
+ found = TRUE;
+ }
+ else if( !(ignore || first) )
+ Fatal( "Include file %s, not found", name );
+ }
+
+ if ( !ignore && first && !found )
+ Fatal( "No include file was found" );
+
+ if( pushed ) Pop_dir(FALSE);
+ attr &= ~(A_IGNORE|A_SETDIR|A_FIRST|A_NOINFER);
+ }
+ break;
+
+ case ST_SOURCE:
+ /* case ST_SUFFIXES: */
+ if( prereq != NIL(CELL) )
+ _do_targets( op & (R_OP_CL | R_OP_MI | R_OP_UP), attr, set_dir,
+ target, prereq );
+ else {
+ /* The old semantics of .SOURCE were that an empty list of
+ * prerequisites clears the .SOURCE list. So we must implement
+ * that here as a clearout prerequisite operation. Since this is
+ * a standard operation with the :- opcode we can simply call the
+ * proper routine with the target cell and it should do the trick
+ */
+
+ if( op == R_OP_CL || (op & R_OP_MI) )
+ Clear_prerequisites( target );
+ }
+
+ op &= ~(R_OP_MI | R_OP_UP);
+ break;
+
+ case ST_KEEP:
+ if( Keep_state != NIL(char) ) break;
+ Def_macro( ".KEEP_STATE", "_state.mk", M_EXPANDED );
+ break;
+
+ case ST_REST:
+ /* The rest of the special targets can all take rules, as such they
+ * must be able to affect the state of the parser. */
+
+ {
+ int s_targ = Target;
+
+ Target = TRUE;
+ _sp_target = TRUE;
+ *state = _do_targets( op, attr, set_dir, target, prereq );
+ Target = s_targ;
+
+ target->ce_flag |= F_TARGET;
+
+ attr = A_DEFAULT;
+ op = R_OP_CL;
+ }
+ break;
+
+ default:break;
+ }
+
+ if( op != R_OP_CL ) Warning( "Modifier(s) for operator ignored" );
+ if( attr != A_DEFAULT ) Warning( "Extra attributes ignored" );
+
+ DB_VOID_RETURN;
+}
+
+
+
+static int
+_do_targets( op, attr, set_dir, targets, prereq )/*
+================================================= */
+int op;
+t_attr attr;
+char *set_dir;
+CELLPTR targets;
+CELLPTR prereq;
+{
+ CELLPTR tg1; /* temporary target pointer */
+ CELLPTR tp1; /* temporary prerequisite pointer */
+ LINKPTR prev_cell; /* pointer for .UPDATEALL processing */
+ char *p; /* temporary char pointer */
+ int tflag = FALSE; /* set to TRUE if we add target to root */
+
+ DB_ENTER( "_do_targets" );
+
+ if( attr & A_UPDATEALL ) {
+ if( targets == NIL(CELL) )
+ Fatal( ".UPDATEALL attribute requires non-empty list of targets" );
+
+ if (targets->ce_set == NIL(CELL)) {
+ for(
+ prev_cell=CeMeToo(targets),tg1=targets->ce_link;
+ tg1 != NIL(CELL);
+ tg1=tg1->ce_link
+ ) {
+ if (tg1->ce_set)
+ Fatal( "Target [%s] appears on multiple .UPDATEALL lists",
+ tg1->CE_NAME);
+ tg1->ce_set = targets;
+ TALLOC(prev_cell->cl_next, 1, LINK);
+ prev_cell = prev_cell->cl_next;
+ prev_cell->cl_prq = tg1;
+ }
+ targets->ce_set = targets;
+ }
+ else {
+ LINKPTR ap;
+ CELLPTR tp;
+
+ tp = targets;
+ ap = CeMeToo(targets);
+ while (ap && tp && ap->cl_prq == tp && tp->ce_set == targets) {
+ ap = ap->cl_next;
+ tp = tp->ce_link;
+ }
+ if (ap || tp)
+ Fatal("Inconsistent .UPDATEALL lists for target [%s]",
+ targets->CE_NAME);
+ }
+ targets->ce_link = NIL(CELL);
+ }
+
+ for( tg1 = targets; tg1 != NIL(CELL); tg1 = tg1->ce_link ) {
+ /* Check each target. Check for inconsistencies between :: and : rule
+ * sets. :: may follow either : or :: but not the reverse.
+ *
+ * Any targets that contain :: rules are represented by a prerequisite
+ * list hanging off the main target cell where each of the prerequisites
+ * is a copy of the target cell but is not entered into the hash table.
+ */
+ int magic = (tg1->ce_flag & F_PERCENT) && !(tg1->ce_flag & F_MAGIC);
+
+ if( !(op & R_OP_DCL ) && (tg1->ce_flag & F_MULTI) && !magic )
+ Fatal( "':' vs '::' inconsistency in rules for %s", tg1->CE_NAME );
+
+ if( magic ) {
+ if (op & R_OP_OR)
+ for(tp1=prereq; tp1; tp1=tp1->ce_link) {
+ CELLPTR tmpcell = tp1->ce_link;
+ tp1->ce_link = NIL(CELL);
+ _build_graph(op,tg1,tp1);
+ tp1->ce_link = tmpcell;
+ }
+ else
+ prereq = _build_graph(op,tg1,prereq);
+ }
+ else if( !(tg1->ce_flag & F_SPECIAL) &&
+ (prereq == NIL(CELL)) &&
+ (p = _is_magic( tg1->CE_NAME )) != NIL(char))
+ _do_magic( op, p, tg1, prereq, attr, set_dir );
+ else if( op & R_OP_DCL ) {
+ CELLPTR tmp_cell = _make_multi(tg1);
+ tflag |= _add_root(tg1);
+ targets = _replace_cell( targets, tg1, tmp_cell );
+ tg1 = tmp_cell;
+ }
+
+ if( !magic ) _set_attributes( attr, set_dir, tg1 );
+
+ /* Build the proper prerequisite list of the target. If the `-',
+ * modifier was used clear the prerequisite list before adding any
+ * new prerequisites. Else add them to the head/tail as appropriate.
+ *
+ * If the target has F_PERCENT set then no prerequisites are used. */
+
+ if( !(tg1->ce_flag & F_PERCENT) ) {
+ if( op & R_OP_MI ) Clear_prerequisites( tg1 );
+
+ if( (op & R_OP_UP) && (tg1->ce_prq != NIL(LINK)) )
+ _stick_at_head( tg1, prereq );
+ else for( tp1=prereq; tp1 != NIL(CELL); tp1 = tp1->ce_link )
+ Add_prerequisite( tg1, tp1, FALSE, FALSE );
+ }
+ else if( op & (R_OP_MI | R_OP_UP) )
+ Warning( "Modifier(s) `^!' for %-meta target ignored" );
+ }
+
+ if(tflag)
+ Target = TRUE;
+
+ /* Check to see if we have NO targets but some attributes. IF so then
+ * apply all of the attributes to the complete list of prerequisites.
+ */
+
+ if( (targets == NIL(CELL)) && attr )
+ if( prereq != NIL(CELL) )
+ for( tp1=prereq; tp1 != NIL(CELL); tp1 = tp1->ce_link )
+ _set_attributes( attr, set_dir, tp1 );
+ else
+ _set_global_attr( attr );
+
+ /* Now that we have built the lists of targets, the parser must parse the
+ * rules if there are any. However we must start the rule list with the
+ * rule specified as via the ; kludge, if there is one */
+ _sv_targets = targets;
+ _sv_attr = attr;
+ _sv_flag = ((op & R_OP_BG) ? F_SINGLE : F_DEFAULT);
+
+ DB_RETURN( RULE_SCAN );
+}
+
+
+static int
+_do_magic( op, dot, target, prereq, attr, set_dir )/*
+=====================================================
+ This function takes a magic target of the form .<chars>.<chars> or
+ .<chars> and builds the appropriate % rules for that target.
+
+ The function builds the % rule, `%.o : %.c' from .c.o, and
+ `%.a :' from .a */
+
+int op;
+char *dot;
+CELLPTR target;
+CELLPTR prereq;
+t_attr attr;
+char *set_dir;
+{
+ CELLPTR tg;
+ CELLPTR prq;
+ char *tmp, *tmp2;
+
+ DB_ENTER( "_do_magic" );
+
+ if( prereq != NIL(CELL) )
+ Warning( "Ignoring prerequisites of old style meta-target" );
+
+ if( dot == target->CE_NAME ) { /* its of the form .a */
+ tg = Def_cell( "%" ); /* ==> no prerequisite */
+ tmp = _build_meta( target->CE_NAME );
+ prq = Def_cell( tmp );
+ FREE( tmp );
+
+ _build_graph( op, tg, prq );
+ }
+ else {
+ tmp = _build_meta( dot );
+ tg = Def_cell( tmp );
+ FREE( tmp );
+
+ tmp = _build_meta( tmp2 = DmSubStr( target->CE_NAME, dot ) );
+ prq = Def_cell( tmp );
+ FREE( tmp );
+ FREE( tmp2 );
+
+ _build_graph( op, tg, prq );
+ }
+
+ tg->ce_flag |= F_PERCENT;
+ target->ce_flag |= (F_MAGIC|F_PERCENT);
+
+ _set_attributes( attr, set_dir, tg );
+
+ DB_RETURN(1);
+}
+
+
+static CELLPTR
+_replace_cell( lst, cell, rep )
+CELLPTR lst;
+CELLPTR cell;
+CELLPTR rep;
+{
+ register CELLPTR tp;
+
+ if( lst == cell ) {
+ rep->ce_link = lst->ce_link;
+ lst = rep;
+ }
+ else {
+ for( tp=lst; tp->ce_link != cell; tp=tp->ce_link );
+ rep->ce_link = tp->ce_link->ce_link;
+ tp->ce_link = rep;
+ }
+
+ return(lst);
+}
+
+
+static char *
+_build_meta( name )/*
+=====================
+ Check to see if the name is of the form .c~ if so and if Augmake
+ translation is enabled then return s.%.c, else return %.suff, where if the
+ suffix ends in '~' then leave it be.*/
+char *name;
+{
+ char *tmp;
+ int test = (STOBOOL(Augmake) ? name[strlen(name)-1] == '~' : 0);
+
+ tmp = DmStrJoin( test ? "s.%" : "%", name, -1, FALSE);
+ if( test ) tmp[ strlen(tmp)-1 ] = '\0';
+
+ return(tmp);
+}
+
+
+static CELLPTR
+_build_graph( op, target, prereq )/*
+====================================
+ This function is called to build the graph for the % rule given by
+ target : prereq cell combination. This function assumes that target
+ is a % target and that prereq is a single % prerequisite. R_OP_CL
+ rules replace existing rules if any, only R_OP_CL works for meta-rules.
+ %.o :: %.c is meaningless. If target has ce_all set then all the cells
+ on the list must match in order for the match to work. If prereq->ce_link
+ is not nil then all prerequisites listed by the link set must match also.
+ This latter match is more difficult because in general the prerequisite
+ sets may not be listed in the same order.
+
+ It also assumes that target cell has F_PERCENT set already. */
+int op;
+CELLPTR target;
+CELLPTR prereq;
+{
+ LINKPTR edl;
+ CELLPTR edge;
+ CELLPTR tpq,cur;
+ int match;
+
+ DB_ENTER( "_build_graph" );
+ DB_PRINT( "%", ("Building graph for [%s : %s]", target->CE_NAME,
+ (prereq == NIL(CELL)) ? "" : prereq->CE_NAME) );
+
+ tpq = NIL(CELL);
+ for(cur=prereq;cur;cur=cur->ce_link) {
+ char *name = cur->CE_NAME;
+ int len = strlen(name);
+
+ if( *name == '\'' && name[len-1]=='\'' ){
+ _add_global_prereq( cur );
+ name[len-1] = '\0';
+ strcpy(name,name+1);
+ }
+ else {
+ if (tpq)
+ tpq->ce_link = cur;
+ else
+ prereq = cur;
+ tpq = cur;
+ }
+ }
+ if(tpq)
+ tpq->ce_link=NIL(CELL);
+ else
+ prereq = NIL(CELL);
+
+ /* Search the list of prerequisites for the current target and see if
+ * any of them match the current %-meta's : prereq's pair. NOTE that
+ * %-metas are built as if they were F_MULTI targets. */
+ match = FALSE;
+ for(edl=target->ce_prq; !match && edl != NIL(LINK); edl=edl->cl_next) {
+ LINKPTR l1,l2;
+ edge = edl->cl_prq;
+
+ DB_PRINT("%", ("Trying to match [%s]",edge?edge->CE_NAME:"(nil)"));
+
+ /* First we match the target sets, if this fails then we don't have to
+ * bother with the prerequisite sets. The targets sets are sorted.
+ * this makes life very simple. */
+
+ l1 = CeMeToo(target);
+ l2 = CeMeToo(edge);
+ while(l1 && l2 && l1->cl_prq == l2->cl_prq) {
+ l1=l1->cl_next;
+ l2=l2->cl_next;
+ }
+
+ if (l1 || l2)
+ continue;
+
+ /* target sets match, so check prerequisites. */
+
+ if( (!edge->ce_prq && !prereq)
+ || ( edge->ce_prq
+ && ( edge->ce_dir == _sv_setdir
+ || ( edge->ce_dir
+ && _sv_setdir
+ && !strcmp(edge->ce_dir,strchr(_sv_setdir,'=')+1)
+ )
+ )
+ )
+ ) {
+ LINKPTR prql;
+
+ /* this is a really gross way to compare two sets, it's n^2 but
+ * since the sets are assumed to always be tiny, it should be ok. */
+ for(tpq=prereq; tpq; tpq=tpq->ce_link) {
+ for(prql=edge->ce_prq;prql;prql=prql->cl_next)
+ if (prql->cl_prq == tpq)
+ break;
+
+ if(prql == NIL(LINK))
+ break;
+
+ prql->cl_prq->ce_flag |= F_MARK;
+ }
+
+ if (tpq == NIL(CELL)) {
+ for(prql=edge->ce_prq;prql;prql=prql->cl_next)
+ if(!(prql->cl_prq->ce_flag & F_MARK))
+ break;
+
+ if(prql == NIL(LINK))
+ match = TRUE;
+ }
+
+ /* clean up the mark bits. */
+ for(prql=edge->ce_prq;prql;prql=prql->cl_next)
+ prql->cl_prq->ce_flag &= ~F_MARK;
+ }
+ }
+
+ if( match ) {
+ /* match is TRUE hence, we found an edge joining the target and the
+ * prerequisite so reset the new edge so that new values replace it. */
+ DB_PRINT( "%", ("It's an old edge") );
+
+ edge->ce_dir = NIL(char);
+ edge->ce_flag &= (F_PERCENT|F_MAGIC|F_DFA);
+ edge->ce_attr &= A_NOINFER;
+ }
+ else {
+ DB_PRINT( "%", ("Adding a new edge") );
+
+ edge = _make_multi(target);
+
+ for(edl=CeMeToo(target);edl;edl=edl->cl_next) {
+ if( !((tpq=edl->cl_prq)->ce_flag & F_DFA) ) {
+ Add_nfa( tpq->CE_NAME );
+ tpq->ce_flag |= F_DFA;
+ }
+
+ edl->cl_prq->ce_set = edge;
+ }
+
+ edge->ce_all = target->ce_all;
+ target->ce_all.cl_next = NIL(LINK);
+ target->ce_set = NIL(CELL);
+
+ for(tpq=prereq; tpq; tpq=tpq->ce_link)
+ Add_prerequisite(edge, tpq, FALSE, TRUE);
+ }
+
+ if( op & R_OP_DCL )
+ Warning("'::' operator for meta-target '%s' ignored, ':' operator assumed.",
+ target->CE_NAME );
+
+ edge->ce_link = _sv_edgel;
+ _sv_edgel = edge;
+ _sv_globprq_only = 0;
+
+ DB_RETURN(NIL(CELL));
+}
+
+
+static CELLPTR
+_make_multi( tg )
+CELLPTR tg;
+{
+ CELLPTR cp;
+
+ /* This first handles the case when a : foo ; exists prior to seeing
+ * a :: fee; */
+ if( !(tg->ce_flag & F_MULTI) && (tg->ce_prq || tg->ce_recipe) ) {
+ TALLOC(cp, 1, CELL);
+ *cp = *tg;
+
+ tg->ce_prq = NIL(LINK);
+ tg->ce_flag |= F_RULES|F_MULTI|F_TARGET;
+ tg->ce_attr |= A_SEQ;
+ tg->ce_recipe = NIL(STRING);
+ tg->ce_dir = NIL(char);
+ cp->ce_count = ++tg->ce_index;
+ cp->ce_cond = NIL(STRING);
+ cp->ce_set = NIL(CELL);
+ cp->ce_all.cl_prq = cp;
+ CeNotMe(cp) = NIL(LINK);
+
+ Add_prerequisite(tg, cp, FALSE, TRUE);
+ }
+
+ TALLOC(cp, 1, CELL);
+ *cp = *tg;
+
+ if( !(tg->ce_flag & F_MULTI) ) {
+ tg->ce_prq = NIL(LINK);
+ tg->ce_flag |= F_RULES|F_MULTI|F_TARGET;
+ tg->ce_attr |= A_SEQ;
+ tg->ce_recipe = NIL(STRING);
+ tg->ce_dir = NIL(char);
+ cp->ce_cond = NIL(STRING);
+ }
+ else {
+ cp->ce_flag &= ~(F_RULES|F_MULTI);
+ cp->ce_attr &= ~A_SEQ;
+ cp->ce_prq = NIL(LINK);
+ cp->ce_index = 0;
+ cp->ce_cond = NIL(STRING);
+ }
+ cp->ce_count = ++tg->ce_index;
+ cp->ce_flag |= F_TARGET;
+ cp->ce_set = NIL(CELL);
+ cp->ce_all.cl_prq = cp;
+ CeNotMe(cp) = NIL(LINK);
+
+ Add_prerequisite(tg, cp, FALSE, TRUE);
+ return(cp);
+}
+
+
+static void
+_add_global_prereq( pq )/*
+==========================
+ Prerequisite is a non-% prerequisite for a %-rule target, add it to
+ the target's list of global prerequsites to add on match */
+CELLPTR pq;
+{
+ register LINKPTR ln;
+
+ for(ln=_sv_glb_prq; ln; ln=ln->cl_next)
+ if(strcmp(ln->cl_prq->CE_NAME,pq->CE_NAME) == 0)
+ return;
+
+ TALLOC( ln, 1, LINK );
+ ln->cl_next = _sv_glb_prq;
+ ln->cl_prq = pq;
+ _sv_glb_prq = ln;
+}
+
+
+
+static void
+_set_attributes( attr, set_dir, cp )/*
+======================================
+ Set the appropriate attributes for a cell */
+t_attr attr;
+char *set_dir;
+CELLPTR cp;
+{
+ char *dir;
+
+ DB_ENTER( "_set_attributes" );
+
+ /* If .SETDIR attribute is set then we have at least .SETDIR= in the
+ * set_dir string. So go and fishout what is at the end of the =.
+ * If not set and not NULL then propagate it to the target cell. */
+
+ if( attr & A_SETDIR ) {
+ char *p;
+ if( (p = strchr( set_dir, '=' )) != NULL )
+ dir = p + 1;
+
+ if( cp->ce_dir )
+ Warning( "Multiple .SETDIR for %s ignored", cp->CE_NAME );
+ else if( *dir )
+ cp->ce_dir = DmStrDup(dir);
+ }
+ cp->ce_attr |= attr; /* set rest of attributes for target */
+
+ DB_VOID_RETURN;
+}
+
+
+
+static void
+_set_global_attr( attr )/*
+==========================
+ Handle the setting of the global attribute functions based on
+ The attribute flags set in attr. */
+t_attr attr;
+{
+ t_attr flag;
+
+ /* Some compilers can't handle a switch on a long, and t_attr is now a long
+ * integer on some systems. foey! */
+ for( flag = MAX_ATTR; flag; flag >>= 1 )
+ if( flag & attr )
+ if( flag == A_PRECIOUS) Def_macro(".PRECIOUS", "y", M_EXPANDED);
+ else if( flag == A_SILENT) Def_macro(".SILENT", "y", M_EXPANDED);
+ else if( flag == A_IGNORE ) Def_macro(".IGNORE", "y", M_EXPANDED);
+ else if( flag == A_EPILOG ) Def_macro(".EPILOG", "y", M_EXPANDED);
+ else if( flag == A_PROLOG ) Def_macro(".PROLOG", "y", M_EXPANDED);
+ else if( flag == A_NOINFER ) Def_macro(".NOINFER", "y", M_EXPANDED);
+ else if( flag == A_SEQ ) Def_macro(".SEQUENTIAL","y", M_EXPANDED);
+ else if( flag == A_SHELL ) Def_macro(".USESHELL", "y", M_EXPANDED);
+ else if( flag == A_MKSARGS ) Def_macro(".MKSARGS", "y", M_EXPANDED);
+ else if( flag == A_SWAP ) Def_macro(".SWAP", "y", M_EXPANDED);
+
+ attr &= ~A_GLOB;
+ if( attr ) Warning( "Non global attribute(s) ignored" );
+}
+
+
+
+static void
+_stick_at_head( cp, pq )/*
+==========================
+ Add the prerequisite list to the head of the existing prerequisite
+ list */
+
+CELLPTR cp; /* cell for target node */
+CELLPTR pq; /* list of prerequisites to add */
+{
+ DB_ENTER( "_stick_at_head" );
+
+ if( pq->ce_link != NIL(CELL) ) _stick_at_head( cp, pq->ce_link );
+ Add_prerequisite( cp, pq, TRUE, FALSE );
+
+ DB_VOID_RETURN;
+}
+
+
+
+static t_attr
+_is_attribute( name )/*
+=======================
+ Check the passed name against the list of valid attributes and return the
+ attribute index if it is, else return 0, indicating the name is not a valid
+ attribute. The present attributes are defined in dmake.h as A_xxx #defines,
+ with the corresponding makefile specification: (note they must be named
+ exactly as defined below)
+
+ Valid attributes are: .IGNORE, .SETDIR=, .SILENT, .PRECIOUS, .LIBRARY,
+ .EPILOG, .PROLOG, .LIBRARYM, .SYMBOL, .UPDATEALL,
+ .USESHELL, .NOINFER, .PHONY, .SWAP, .SEQUENTIAL
+ .NOSTATE, .MKSARGS, .IGNOREGROUP, .GROUP, .FIRST
+ .EXECUTE, .ERRREMOVE
+
+ NOTE: The strcmp's are OK since at most three are ever executed for any
+ one attribute check, and that happens only when we can be fairly
+ certain we have an attribute. */
+char *name;
+{
+ t_attr attr = 0;
+
+ DB_ENTER( "_is_attribute" );
+
+ if( *name++ == '.' )
+ switch( *name )
+ {
+ case 'E':
+ if( !strcmp(name, "EPILOG") ) attr = A_EPILOG;
+ else if( !strcmp(name, "EXECUTE")) attr = A_EXECUTE;
+ else if( !strcmp(name, "ERRREMOVE")) attr = A_ERRREMOVE;
+ else attr = 0;
+ break;
+
+ /* A_FIRST implies A_IGNORE, handled in ST_INCLUDE */
+ case 'F':
+ attr = (strcmp(name, "FIRST")) ? 0 : A_FIRST;
+ break;
+
+ case 'G': attr = (strcmp(name, "GROUP")) ? 0 : A_GROUP; break;
+ case 'L': attr = (strcmp(name, "LIBRARY")) ? 0 : A_LIBRARY; break;
+ case 'M': attr = (strcmp(name, "MKSARGS")) ? 0 : A_MKSARGS; break;
+
+ case 'I':
+ if( !strcmp(name, "IGNORE") ) attr = A_IGNORE;
+ else if( !strcmp(name, "IGNOREGROUP")) attr = A_IGNOREGROUP;
+ else attr = 0;
+ break;
+
+ case 'N':
+ if( !strcmp(name, "NOINFER") ) attr = A_NOINFER;
+ else if( !strcmp(name, "NOSTATE")) attr = A_NOSTATE;
+ else attr = 0;
+ break;
+
+ case 'U':
+ if( !strcmp(name, "UPDATEALL") ) attr = A_UPDATEALL;
+ else if( !strcmp(name, "USESHELL")) attr = A_SHELL;
+ else attr = 0;
+ break;
+
+ case 'P':
+ if( !strcmp(name, "PRECIOUS") ) attr = A_PRECIOUS;
+ else if( !strcmp(name, "PROLOG") ) attr = A_PROLOG;
+ else if( !strcmp(name, "PHONY") ) attr = A_PHONY;
+ else attr = 0;
+ break;
+
+ case 'S':
+ if( !strncmp(name, "SETDIR=", 7) ) attr = A_SETDIR;
+ else if( !strcmp(name, "SILENT") ) attr = A_SILENT;
+ else if( !strcmp(name, "SYMBOL") ) attr = A_SYMBOL;
+ else if( !strcmp(name, "SEQUENTIAL")) attr = A_SEQ;
+ else if( !strcmp(name, "SWAP")) attr = A_SWAP;
+ else attr = 0;
+ break;
+ }
+
+ DB_RETURN( attr );
+}
+
+
+
+static int
+_is_special( tg )/*
+===================
+ This function returns TRUE if the name passed in represents a special
+ target, otherwise it returns false. A special target is one that has
+ a special meaning to dmake, and may require processing at the time that
+ it is parsed.
+
+ Current Special targets are:
+ .GROUPPROLOG .GROUPEPILOG .INCLUDE .IMPORT
+ .EXPORT .SOURCE .SUFFIXES .ERROR .EXIT
+ .INCLUDEDIRS .MAKEFILES .REMOVE .KEEP_STATE
+*/
+char *tg;
+{
+ DB_ENTER( "_is_special" );
+
+ if( *tg++ != '.' ) DB_RETURN( 0 );
+
+ switch( *tg )
+ {
+ case 'E':
+ if( !strcmp( tg, "ERROR" ) ) DB_RETURN( ST_REST );
+ else if( !strcmp( tg, "EXPORT" ) ) DB_RETURN( ST_EXPORT );
+ else if( !strcmp( tg, "EXIT" ) ) DB_RETURN( ST_EXIT );
+ break;
+
+ case 'G':
+ if( !strcmp( tg, "GROUPPROLOG" )) DB_RETURN( ST_REST );
+ else if( !strcmp( tg, "GROUPEPILOG" )) DB_RETURN( ST_REST );
+ break;
+
+ case 'I':
+ if( !strcmp( tg, "IMPORT" ) ) DB_RETURN( ST_IMPORT );
+ else if( !strcmp( tg, "INCLUDE" ) ) DB_RETURN( ST_INCLUDE );
+ else if( !strcmp( tg, "INCLUDEDIRS" )) DB_RETURN( ST_REST );
+ break;
+
+ case 'K':
+ if( !strcmp( tg, "KEEP_STATE" ) ) DB_RETURN( ST_KEEP );
+ break;
+
+ case 'M':
+ if( !strcmp( tg, "MAKEFILES" ) ) DB_RETURN( ST_REST );
+ break;
+
+ case 'R':
+ if( !strcmp( tg, "REMOVE" ) ) DB_RETURN( ST_REST );
+ break;
+
+ case 'S':
+ if( !strncmp( tg, "SOURCE", 6 ) ) DB_RETURN( ST_SOURCE );
+ else if( !strncmp(tg, "SUFFIXES", 8 )) DB_RETURN( ST_SOURCE );
+ break;
+ }
+
+ DB_RETURN( 0 );
+}
+
+
+
+static int
+_is_percent( np )/*
+===================
+ return TRUE if np points at a string containing a % sign */
+char *np;
+{
+ return( (strchr(np,'%') && (*np != '\'' && np[strlen(np)-1] != '\'')) ?
+ TRUE : FALSE );
+}
+
+
+static char *
+_is_magic( np )/*
+=================
+ return TRUE if np points at a string of the form
+ .<chars>.<chars> or .<chars>
+ where chars are only alpha characters.
+
+ NOTE: reject target if it begins with ./ or ../ */
+char *np;
+{
+ register char *n;
+
+ n = np;
+ if( *n != '.' ) return( NIL(char) );
+ if (strchr(DirBrkStr, *(n+1))!=NULL || *(n+1) == '.' )
+ return (NIL(char));
+
+ for( n++; isgraph(*n) && (*n != '.'); n++ );
+
+ if( *n != '\0' ) {
+ if( *n != '.' ) return( NIL(char) );
+ for( np = n++; isgraph( *n ) && (*n != '.'); n++ );
+ if( *n != '\0' ) return( NIL(char) );
+ }
+ else if( STOBOOL(Augmake) )
+ return( NIL(char) );
+
+ /* np points at the second . of .<chars>.<chars> string.
+ * if the special target is of the form .<chars> then np points at the
+ * first . in the token. */
+
+ return( np );
+}
+
+
+static int
+_add_root(tg)
+CELLPTR tg;
+{
+ int res = FALSE;
+
+ if(tg == Targets)
+ return(TRUE);
+
+ if( !Target && !(tg->ce_flag & (F_SPECIAL|F_PERCENT)) ) {
+ Add_prerequisite(Targets, tg, FALSE, TRUE);
+
+ tg->ce_flag |= F_TARGET;
+ tg->ce_attr |= A_FRINGE;
+ res = TRUE;
+ }
+
+ return(res);
+}
diff --git a/dmake/startup/mac/macros.mk b/dmake/startup/mac/macros.mk
new file mode 100644
index 000000000000..ca161a8baa5c
--- /dev/null
+++ b/dmake/startup/mac/macros.mk
@@ -0,0 +1,41 @@
+# Define MPW MAC specific macros.
+# Assumes CodeWarrior for Mac 5.0 C, change as needed.
+#
+
+A *:= .lib
+S *:= .s
+V *:= v
+TMPDIR *:= $(TempFolder)
+
+# import library definitions
+.IMPORT .IGNORE : CLibraries Libraries
+
+# Set arguments for the SHELL. Since we can't execute sub-processes,
+# these variables are not important, except for some makefiles that check
+# for some values to determine the platform.
+SHELL *:= "{MPW}MPW Shell"
+SHELLFLAGS *:=
+GROUPFLAGS *:=
+SHELLMETAS *:=
+
+# Define toolkit macros
+CC *:= MWCPPC
+AS *:= PPCAsm
+LD *:= MWLinkPPC
+AR *:=
+ARFLAGS *:=
+RM *:= delete
+RMFLAGS *:=
+MV *:= rename
+YTAB *:=
+LEXYY *:=
+
+LDLIBS *= "{SharedLibraries}StdCLib" "{SharedLibraries}InterfaceLib" \
+ "{PPCLibraries}StdCRuntime.o" "{PPCLibraries}PPCCRuntime.o" \
+ "{Libraries}MathLib.o" "{PPCLibraries}PPCToolLibs.o"
+
+# Disable the print command
+PRINT *=
+
+# Make certain to disable defining how to make executables.
+__.EXECS !:=
diff --git a/dmake/startup/msdos/borland/bcc30/macros.mk b/dmake/startup/msdos/borland/bcc30/macros.mk
new file mode 100644
index 000000000000..599ba52c0a61
--- /dev/null
+++ b/dmake/startup/msdos/borland/bcc30/macros.mk
@@ -0,0 +1,4 @@
+# MSDOS Borland-C customization.
+
+# Standard C-language command names and flags
+CC *:= bcc # C compiler
diff --git a/dmake/startup/msdos/borland/bcc40/macros.mk b/dmake/startup/msdos/borland/bcc40/macros.mk
new file mode 100644
index 000000000000..599ba52c0a61
--- /dev/null
+++ b/dmake/startup/msdos/borland/bcc40/macros.mk
@@ -0,0 +1,4 @@
+# MSDOS Borland-C customization.
+
+# Standard C-language command names and flags
+CC *:= bcc # C compiler
diff --git a/dmake/startup/msdos/borland/bcc45/macros.mk b/dmake/startup/msdos/borland/bcc45/macros.mk
new file mode 100644
index 000000000000..599ba52c0a61
--- /dev/null
+++ b/dmake/startup/msdos/borland/bcc45/macros.mk
@@ -0,0 +1,4 @@
+# MSDOS Borland-C customization.
+
+# Standard C-language command names and flags
+CC *:= bcc # C compiler
diff --git a/dmake/startup/msdos/borland/bcc50.32/macros.mk b/dmake/startup/msdos/borland/bcc50.32/macros.mk
new file mode 100644
index 000000000000..599ba52c0a61
--- /dev/null
+++ b/dmake/startup/msdos/borland/bcc50.32/macros.mk
@@ -0,0 +1,4 @@
+# MSDOS Borland-C customization.
+
+# Standard C-language command names and flags
+CC *:= bcc # C compiler
diff --git a/dmake/startup/msdos/borland/bcc50/macros.mk b/dmake/startup/msdos/borland/bcc50/macros.mk
new file mode 100644
index 000000000000..599ba52c0a61
--- /dev/null
+++ b/dmake/startup/msdos/borland/bcc50/macros.mk
@@ -0,0 +1,4 @@
+# MSDOS Borland-C customization.
+
+# Standard C-language command names and flags
+CC *:= bcc # C compiler
diff --git a/dmake/startup/msdos/borland/macros.mk b/dmake/startup/msdos/borland/macros.mk
new file mode 100644
index 000000000000..1e8915171ff1
--- /dev/null
+++ b/dmake/startup/msdos/borland/macros.mk
@@ -0,0 +1,33 @@
+# MSDOS Borland-C environment customization.
+
+.IF $(OSENVIRONMENT)
+ .INCLUDE .IGNORE .NOINFER : $(INCFILENAME:d)$(OSENVIRONMENT)$/macros.mk
+.ENDIF
+
+# Standard C-language command names and flags
+CPP *:= # C-preprocessor
+CFLAGS *= # C compiler flags
+"C++" *:= # C++ Compiler
+"C++FLAGS" *= # C++ Compiler flags
+
+AS *:= tasm # Assembler and flags
+ASFLAGS *=
+LD *= tlink # Loader and flags
+LDFLAGS *=
+LDLIBS *= # Default libraries
+AR *:= tlib # archiver
+ARFLAGS *= ????
+
+# Definition of Print command for this system.
+PRINT *= print
+
+# Language and Parser generation Tools and their flags
+YACC *:= yacc # standard yacc
+YFLAGS *=
+LEX *:= lex # standard lex
+LFLAGS *=
+
+# Other Compilers, Tools and their flags
+PC *:= tpc # pascal compiler
+RC *:= ??? # ratfor compiler
+FC *:= ??? # fortran compiler
diff --git a/dmake/startup/msdos/borland/tcc20/macros.mk b/dmake/startup/msdos/borland/tcc20/macros.mk
new file mode 100644
index 000000000000..7d922e44d03a
--- /dev/null
+++ b/dmake/startup/msdos/borland/tcc20/macros.mk
@@ -0,0 +1,4 @@
+# MSDOS Turbo-C customization.
+
+# Standard C-language command names and flags
+CC *:= tcc # C compiler
diff --git a/dmake/startup/msdos/macros.mk b/dmake/startup/msdos/macros.mk
new file mode 100644
index 000000000000..320865ea94de
--- /dev/null
+++ b/dmake/startup/msdos/macros.mk
@@ -0,0 +1,62 @@
+# Define additional MSDOS specific settings.
+#
+
+# Execution environment configuration.
+# Grab the current setting of COMSPEC.
+#
+.IMPORT .IGNORE : COMSPEC
+
+# First check if SHELL is defined to be something other than COMSPEC.
+# If it is, then assume that SHELL is a Korn compatible shell like MKS's
+.IF $(SHELL) == $(NULL)
+ .IF $(COMSPEC) == $(NULL)
+ SHELL *:= $(ROOTDIR)$/bin$/sh$E
+ .ELSE
+ SHELL *:= $(COMSPEC)
+ .END
+.END
+GROUPSHELL *:= $(SHELL)
+
+# Process release-specific refinements, if any.
+.INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)$(OSRELEASE)$/macros.mk
+
+# Applicable suffix definitions
+A *:= .lib # Libraries
+E *:= .exe # Executables
+F *:= .for # Fortran
+O *:= .obj # Objects
+P *:= .pas # Pascal
+S *:= .asm # Assembler sources
+V *:= # RCS suffix
+
+# Now set the remaining arguments depending on which SHELL we
+# are going to use. COMSPEC (assumed to be command.com) or
+# MKS Korn shell.
+.IF $(SHELL) == $(COMSPEC)
+ SHELLFLAGS *:= $(SWITCHAR)c
+ GROUPFLAGS *:= $(SHELLFLAGS)
+ SHELLMETAS *:= "<>|
+ GROUPSUFFIX *:= .bat
+ DIVFILE *= $(TMPFILE:s,/,\)
+ RM *= del
+ RMFLAGS *=
+ MV *= rename
+ __.DIVSEP-sh-yes *:= \\
+ __.DIVSEP-sh-no *:= \\
+.ELSE
+ SHELLFLAGS *:= -c
+ GROUPFLAGS *:=
+ SHELLMETAS *:= *";?<>|()&][$$\#`'
+ GROUPSUFFIX *:= .ksh
+ .MKSARGS *:= yes
+ RM *= $(ROOTDIR)$/bin$/rm
+ RMFLAGS *= -f
+ MV *= $(ROOTDIR)$/bin$/mv
+ DIVFILE *= $(TMPFILE:s,/,${__.DIVSEP-sh-${USESHELL}})
+ __.DIVSEP-sh-yes *:= \\\
+ __.DIVSEP-sh-no *:= \\
+.ENDIF
+
+
+# Does not respect case of filenames.
+.DIRCACHERESPCASE := no
diff --git a/dmake/startup/msdos/microsft/macros.mk b/dmake/startup/msdos/microsft/macros.mk
new file mode 100644
index 000000000000..3891f84fde21
--- /dev/null
+++ b/dmake/startup/msdos/microsft/macros.mk
@@ -0,0 +1,34 @@
+# MSDOS Microsoft-C environment customization.
+
+.IF $(OSENVIRONMENT)
+ .INCLUDE .IGNORE .NOINFER : $(INCFILENAME:d)$(OSENVIRONMENT)$/macros.mk
+.ENDIF
+
+# Standard C-language command names and flags
+CC *:= cl # C compiler
+CPP *:= # C-preprocessor
+CFLAGS *= # C compiler flags
+"C++" *:= # C++ Compiler
+"C++FLAGS" *= # C++ Compiler flags
+
+AS *:= masm # Assembler and flags
+ASFLAGS *=
+LD *= link # Loader and flags
+LDFLAGS *=
+LDLIBS *= # Default libraries
+AR *:= lib # archiver
+ARFLAGS *= ????
+
+# Definition of Print command for this system.
+PRINT *= print
+
+# Language and Parser generation Tools and their flags
+YACC *:= yacc # standard yacc
+YFLAGS *=
+LEX *:= lex # standard lex
+LFLAGS *=
+
+# Other Compilers, Tools and their flags
+PC *:= ??? # pascal compiler
+RC *:= ??? # ratfor compiler
+FC *:= ??? # fortran compiler
diff --git a/dmake/startup/msdos/recipes.mk b/dmake/startup/msdos/recipes.mk
new file mode 100644
index 000000000000..39a5965e844c
--- /dev/null
+++ b/dmake/startup/msdos/recipes.mk
@@ -0,0 +1,9 @@
+# Define additional MSDOS specific build recipes.
+#
+
+# Executables
+ %$E .SWAP : %$O ; $(CC) $(LDFLAGS) -o$@ $< $(LDLIBS)
+ %$O : %$S ; $(AS) $(ASFLAGS) $(<:s,/,\)
+
+# Process release-specific refinements, if any.
+.INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)$(OSRELEASE)$/recipes.mk
diff --git a/dmake/startup/msdos/zortech/macros.mk b/dmake/startup/msdos/zortech/macros.mk
new file mode 100644
index 000000000000..f9166150f13d
--- /dev/null
+++ b/dmake/startup/msdos/zortech/macros.mk
@@ -0,0 +1,30 @@
+# MSDOS Zortech-C environment customization.
+
+# Standard C-language command names and flags
+CC *:= ztc # C compiler
+CPP *:= # C-preprocessor
+CFLAGS *= # C compiler flags
+"C++" *:= # C++ Compiler
+"C++FLAGS" *= # C++ Compiler flags
+
+AS *:= masm # Assembler and flags
+ASFLAGS *=
+LD *= blink # Loader and flags
+LDFLAGS *=
+LDLIBS *= # Default libraries
+AR *:= ???? # archiver
+ARFLAGS *= ????
+
+# Definition of Print command for this system.
+PRINT *= print
+
+# Language and Parser generation Tools and their flags
+YACC *:= yacc # standard yacc
+YFLAGS *=
+LEX *:= lex # standard lex
+LFLAGS *=
+
+# Other Compilers, Tools and their flags
+PC *:= ??? # pascal compiler
+RC *:= ??? # ratfor compiler
+FC *:= ??? # fortran compiler
diff --git a/dmake/startup/os2/ibm/macros.mk b/dmake/startup/os2/ibm/macros.mk
new file mode 100644
index 000000000000..4b848d93cc4c
--- /dev/null
+++ b/dmake/startup/os2/ibm/macros.mk
@@ -0,0 +1,30 @@
+# OS/2 1.3 and 2.1 specific customization.
+
+# Standard C-language command names and flags
+CC *:= icc # C compiler
+CPP *:= # C-preprocessor
+CFLAGS *= # C compiler flags
+"C++" *:= # C++ Compiler
+"C++FLAGS" *= # C++ Compiler flags
+
+AS *:= masm # Assembler and flags
+ASFLAGS *=
+LD *= link386 # Loader and flags
+LDFLAGS *=
+LDLIBS *= # Default libraries
+AR *:= lib # archiver
+ARFLAGS *= ????
+
+# Definition of Print command for this system.
+PRINT *= print
+
+# Language and Parser generation Tools and their flags
+YACC *:= yacc # standard yacc
+YFLAGS *=
+LEX *:= lex # standard lex
+LFLAGS *=
+
+# Other Compilers, Tools and their flags
+PC *:= ??? # pascal compiler
+RC *:= ??? # ratfor compiler
+FC *:= ??? # fortran compiler
diff --git a/dmake/startup/os2/macros.mk b/dmake/startup/os2/macros.mk
new file mode 100644
index 000000000000..a35df6ee4b8c
--- /dev/null
+++ b/dmake/startup/os2/macros.mk
@@ -0,0 +1,60 @@
+# Define additional OS/2 specific macros.
+#
+
+# Process release-specific refinements, if any.
+.INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)$(OSRELEASE)$/macros.mk
+
+# Execution environment configuration.
+# Grab the current setting of COMSPEC.
+#
+.IMPORT .IGNORE : COMSPEC
+
+# First check if SHELL is defined to be something other than COMSPEC.
+# If it is assume that SHELL is a Korn compatible shell like MKS's
+.IF $(SHELL) == $(NULL)
+ .IF $(COMSPEC) == $(NULL)
+ SHELL *:= $(ROOTDIR)$/bin$/sh$E
+ .ELSE
+ SHELL *:= $(COMSPEC)
+ .END
+.END
+GROUPSHELL *:= $(SHELL)
+
+# Directory entries are case incensitive
+.DIRCACHERESPCASE *:= no
+
+# Applicable suffix definitions
+A *:= .lib # Libraries
+E *:= .exe # Executables
+F *:= .for # Fortran
+O *:= .obj # Objects
+P *:= .pas # Pascal
+S *:= .asm # Assembler sources
+V *:= # RCS suffix
+
+# Now set the remaining arguments depending on which SHELL we
+# are going to use. COMSPEC (assumed to be command.com) or
+# MKS Korn shell.
+.IF $(SHELL) == $(COMSPEC)
+ SHELLFLAGS *:= $(SWITCHAR)c
+ GROUPFLAGS *:= $(SHELLFLAGS)
+ SHELLMETAS *:= *"?<>
+ GROUPSUFFIX *:= .bat
+ DIRSEPSTR *:= \\\
+ DIVFILE *= $(TMPFILE:s,/,\)
+ RM *= del
+ RMFLAGS *=
+ MV *= rename
+.ELSE
+ SHELLFLAGS *:= -c
+ GROUPFLAGS *:=
+ SHELLMETAS *:= *"?<>|()&][$$\#`'
+ GROUPSUFFIX *:= .ksh
+ .MKSARGS *:= yes
+ RM *= $(ROOTDIR)$/bin$/rm
+ RMFLAGS *= -f
+ MV *= $(ROOTDIR)$/bin$/mv
+ DIVFILE *= $(TMPFILE:s,/,${__.DIVSEP-sh-${USESHELL}})
+ __.DIVSEP-sh-yes !:= \\\
+ __.DIVSEP-sh-no !:= \\
+.ENDIF
diff --git a/dmake/startup/qssl/macros.mk b/dmake/startup/qssl/macros.mk
new file mode 100644
index 000000000000..de89485e8541
--- /dev/null
+++ b/dmake/startup/qssl/macros.mk
@@ -0,0 +1,11 @@
+# QNX Specific macro definitions
+#
+
+# Primary suffixes in common use
+A *:= .lib # Libraries
+
+# Standard C-language command names and flags
+AS *:= # Don't have an assembler
+
+AR *:= wlib # archiver
+ARFLAGS *=
diff --git a/dmake/startup/qssl/qnx/macros.mk b/dmake/startup/qssl/qnx/macros.mk
new file mode 100644
index 000000000000..de89485e8541
--- /dev/null
+++ b/dmake/startup/qssl/qnx/macros.mk
@@ -0,0 +1,11 @@
+# QNX Specific macro definitions
+#
+
+# Primary suffixes in common use
+A *:= .lib # Libraries
+
+# Standard C-language command names and flags
+AS *:= # Don't have an assembler
+
+AR *:= wlib # archiver
+ARFLAGS *=
diff --git a/dmake/startup/qssl/qnx/recipes.mk b/dmake/startup/qssl/qnx/recipes.mk
new file mode 100644
index 000000000000..4458b43924a7
--- /dev/null
+++ b/dmake/startup/qssl/qnx/recipes.mk
@@ -0,0 +1,8 @@
+# Define additional QNX specific build recipes.
+#
+
+# Recipe to make archive files.
+# --Figure out what to do about the librarian--
+%$A .GROUP :
+ $(AR) $(ARFLAGS) $@ $?
+ $(RM) $(RMFLAGS) $?
diff --git a/dmake/startup/qssl/recipes.mk b/dmake/startup/qssl/recipes.mk
new file mode 100644
index 000000000000..4458b43924a7
--- /dev/null
+++ b/dmake/startup/qssl/recipes.mk
@@ -0,0 +1,8 @@
+# Define additional QNX specific build recipes.
+#
+
+# Recipe to make archive files.
+# --Figure out what to do about the librarian--
+%$A .GROUP :
+ $(AR) $(ARFLAGS) $@ $?
+ $(RM) $(RMFLAGS) $?
diff --git a/dmake/startup/startup.mk b/dmake/startup/startup.mk
new file mode 100644
index 000000000000..7e8b4aec9231
--- /dev/null
+++ b/dmake/startup/startup.mk
@@ -0,0 +1,209 @@
+# This is the root DMAKE startup file.
+#
+# Definitions common to all environments are given at the root.
+# Definitions parameterized at the root have their parameters specified
+# in sub-makefiles which are included based on the values of the three
+# make variables:
+#
+# OS - core operating system flavour
+# OSRELEASE - specific release of the operating system
+# OSENVIRONMENT - software construction environment in use
+#
+# See the file 'summary', found in this directory for a list of
+# environments supported by this release.
+
+# Disable warnings for macros given on the command line but redefined here.
+__.silent !:= $(.SILENT) # Preserve user's .SILENT flag
+.SILENT !:= yes
+
+# startup.mk configuration parameters, for each, set it to non-null if you wish
+# to enable the named facility.
+__.HAVE_RCS !:= yes # yes => RCS is installed.
+__.HAVE_SCCS !:= # yes => SCCS is installed.
+__.DEFAULTS !:= yes # yes => define default construction rules.
+__.EXECS !:= yes # yes => define how to build executables.
+
+# Grab key definitions from the environment
+.IMPORT .IGNORE : OS OSRELEASE OSENVIRONMENT TMPDIR SHELL
+
+# Default DMAKE configuration, if not overriden by environment
+.INCLUDE .NOINFER $(!null,$(OS) .IGNORE) : $(INCFILENAME:d)config.mk
+
+# Look for a local defaults configuration
+.INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)local.mk
+
+# Define the directory separator string.
+/ *= $(DIRSEPSTR)
+
+# Customize macro definitions based on setings of OS, OSRELEASE and
+# OSENVIRONMENT, this must come before the default macro definitions which
+# follow.
+.INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)$(OS)$/macros.mk
+
+# ----------------- Default Control Macro definitions -----------------------
+# Select appropriate defaults for basic macros
+ MAKE *= $(MAKECMD) -S $(MFLAGS)
+ TMPDIR *:= $/tmp
+ DIVFILE *= $(TMPFILE)
+ AUGMAKE *:= no
+
+# Recipe execution configuration
+ SHELL *:= $/bin$/sh
+ SHELLFLAGS *:= -ce
+ GROUPSHELL *:= $(SHELL)
+ GROUPFLAGS *:=
+ SHELLMETAS *:= |();&<>?*][$$:\\#`'"
+ GROUPSUFFIX *:=
+
+# Intermediate target removal configuration
+ RM *:= $/bin$/rm
+ RMFLAGS *= -f
+ RMTARGET *= $<
+
+# Default recipe that is used to remove intermediate targets.
+.REMOVE :; $(RM) $(RMFLAGS) $(RMTARGET)
+
+# Check and enable AUGMAKE extensions for SYSV compatibility
+.IF $(AUGMAKE)
+ "@B" != $(@:b)
+ "@D" != $(@:d)
+ "@F" != $(@:f)
+ "*B" != $(*:b)
+ "*D" != $(*:d)
+ "*F" != $(*:f)
+ "<B" != $(<:b)
+ "<D" != $(<:d)
+ "<F" != $(<:f)
+ "?B" != $(?:b)
+ "?F" != $(?:f)
+ "?D" != $(?:d)
+.ENDIF
+
+# Directory caching configuration.
+ .DIRCACHE *:= yes
+ .DIRCACHERESPCASE *:= yes
+
+# Define the special NULL Prerequisite
+NULLPRQ *:= __.NULLPRQ
+
+# ---------- Default Construction Macro and Rule definitions --------------
+# The construction rules may be customized further in subsequent recipes.mk
+# files.
+.IF $(__.DEFAULTS)
+ # Primary suffixes in common use
+ A *:= .a # Libraries
+ E *:= # Executables
+ F *:= .f # Fortran
+ O *:= .o # Objects
+ P *:= .p # Pascal
+ S *:= .s # Assembler sources
+ V *:= ,v # RCS suffix
+ YTAB *:= y.tab # name-stem for yacc output files.
+ LEXYY *:= lex.yy # lex output file
+
+ # Standard C-language command names and flags
+ CPP *:= $/lib$/cpp # C-preprocessor
+ CC *:= cc # C compiler
+ CFLAGS *= # C compiler flags
+ "C++" *:= CC # C++ Compiler
+ "C++FLAGS" *= # C++ Compiler flags
+
+ AS *:= as # Assembler and flags
+ ASFLAGS *=
+
+ LD *= $(CC) # Loader and flags
+ LDFLAGS *=
+ LDLIBS *= # Default libraries
+
+ AR *:= ar # archiver
+ ARFLAGS *= -rv
+
+ # Definition of Print command for this system.
+ PRINT *= lp
+
+ # Language and Parser generation Tools and their flags
+ YACC *:= yacc # standard yacc
+ YFLAGS *=
+ LEX *:= lex # standard lex
+ LFLAGS *=
+
+ # Other Compilers, Tools and their flags
+ PC *:= pc # pascal compiler
+ RC *:= f77 # ratfor compiler
+ FC *:= f77 # fortran compiler
+ MV *:= $/bin$/mv # File rename command
+
+ # Implicit generation rules for making inferences.
+ # lex and yacc rules
+ %.c : %.y %.Y
+ $(YACC) $(YFLAGS) $<
+ $(MV) $(YTAB).c $@
+
+ %.c : %.l %.L
+ $(LEX) $(LFLAGS) $<
+ $(MV) $(LEXYY).c $@
+
+ # Rules for making *$O
+ %$O : %.c ; $(CC) $(CFLAGS) -c $<
+ %$O : %$P ; $(PC) $(PFLAGS) -c $<
+ %$O : %$S ; $(AS) $(ASFLAGS) -o $@ $<
+ %$O : %.cl ; class -c $<
+ %$O :| %.e %.r %.F %$F
+ $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $<
+
+ # Defibe how to build simple executables
+ .IF $(__.EXECS)
+ %$E : %$O ; $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS)
+ .ENDIF
+
+ # Recipe to make archive files, defined only if we have
+ # an archiver defined.
+ .IF $(AR)
+ %$A .SWAP .GROUP :
+ $(AR) $(ARFLAGS) $@ $?
+ $(RM) $(RMFLAGS) $?
+ .ENDIF
+
+ # RCS support
+ .IF $(__.HAVE_RCS)
+ CO *:= co # check out for RCS
+ COFLAGS !+= -q
+
+ % : $$(@:d)RCS$$/$$(@:f)$V
+ -$(CO) $(COFLAGS) $(null,$(@:d) $@ $(<:d:s/RCS/)$@)
+ .NOINFER : $$(@:d)RCS$$/$$(@:f)$V
+
+ .IF $V
+ % : %$V
+ -$(CO) $(COFLAGS) $(null,$(@:d) $@ $(<:d:s/RCS/)$@)
+ .NOINFER : %$V
+ .ENDIF
+ .END
+
+ # SCCS support
+ .IF $(__.HAVE_SCCS)
+ GET *:= get
+ GFLAGS !+=
+
+ % : "$$(null,$$(@:d) s.$$@ $$(@:d)s.$$(@:f))"
+ -$(GET) $(GFLAGS) $@
+ .NOINFER : "$$(null,$$(@:d) s.$$@ $$(@:d)s.$$(@:f))"
+ .END
+
+ # Customize default recipe definitions for OS, OSRELEASE, etc. settings.
+ .INCLUDE .NOINFER .IGNORE: $(INCFILENAME:d)$(OS)$/recipes.mk
+.ENDIF
+
+
+# Finally, define the default construction strategy
+.ROOT .PHONY .NOSTATE .SEQUENTIAL :- .INIT .TARGETS .DONE;
+.INIT .DONE .PHONY: $(NULLPRQ);
+
+# Define the NULL Prerequisite as having no recipe.
+$(NULLPRQ) .PHONY :;
+
+# Reset warnings back to previous setting.
+.SILENT !:= $(__.silent)
+
+# Check for a Local project file, gets parsed before user makefile.
+.INCLUDE .IGNORE .NOINFER: "project.mk"
diff --git a/dmake/startup/summary b/dmake/startup/summary
new file mode 100644
index 000000000000..4ae18860da41
--- /dev/null
+++ b/dmake/startup/summary
@@ -0,0 +1,3 @@
+The following is a summary of the supported dmake environments. When you
+issue the build command 'dmake tag' where tag is the target environment it
+will build one of these by default.
diff --git a/dmake/startup/template.mk b/dmake/startup/template.mk
new file mode 100644
index 000000000000..58544ee35848
--- /dev/null
+++ b/dmake/startup/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= xxOSxx
+ OSRELEASE *:= xxOSRELEASExx
+ OSENVIRONMENT *:= xxOSENVIRONMENTxx
diff --git a/dmake/startup/templates/mac/template.mk b/dmake/startup/templates/mac/template.mk
new file mode 100644
index 000000000000..0cf10289c826
--- /dev/null
+++ b/dmake/startup/templates/mac/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= mac
+ OSRELEASE *:=
+ OSENVIRONMENT *:=
diff --git a/dmake/startup/templates/msdos/borland/bcc30/template.mk b/dmake/startup/templates/msdos/borland/bcc30/template.mk
new file mode 100644
index 000000000000..df574e09c7aa
--- /dev/null
+++ b/dmake/startup/templates/msdos/borland/bcc30/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= msdos
+ OSRELEASE *:= borland
+ OSENVIRONMENT *:= bcc30
diff --git a/dmake/startup/templates/msdos/borland/bcc40/template.mk b/dmake/startup/templates/msdos/borland/bcc40/template.mk
new file mode 100644
index 000000000000..30a27692f3ed
--- /dev/null
+++ b/dmake/startup/templates/msdos/borland/bcc40/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= msdos
+ OSRELEASE *:= borland
+ OSENVIRONMENT *:= bcc40
diff --git a/dmake/startup/templates/msdos/borland/bcc45/template.mk b/dmake/startup/templates/msdos/borland/bcc45/template.mk
new file mode 100644
index 000000000000..83b5e009033d
--- /dev/null
+++ b/dmake/startup/templates/msdos/borland/bcc45/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= msdos
+ OSRELEASE *:= borland
+ OSENVIRONMENT *:= bcc45
diff --git a/dmake/startup/templates/msdos/borland/bcc50/template.mk b/dmake/startup/templates/msdos/borland/bcc50/template.mk
new file mode 100644
index 000000000000..51b575677985
--- /dev/null
+++ b/dmake/startup/templates/msdos/borland/bcc50/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= msdos
+ OSRELEASE *:= borland
+ OSENVIRONMENT *:= bcc50
diff --git a/dmake/startup/templates/msdos/borland/tcc20/template.mk b/dmake/startup/templates/msdos/borland/tcc20/template.mk
new file mode 100644
index 000000000000..3cac6b22a240
--- /dev/null
+++ b/dmake/startup/templates/msdos/borland/tcc20/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= msdos
+ OSRELEASE *:= borland
+ OSENVIRONMENT *:= tcc20
diff --git a/dmake/startup/templates/msdos/microsft/msc51/template.mk b/dmake/startup/templates/msdos/microsft/msc51/template.mk
new file mode 100644
index 000000000000..7174197d6284
--- /dev/null
+++ b/dmake/startup/templates/msdos/microsft/msc51/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= msdos
+ OSRELEASE *:= microsft
+ OSENVIRONMENT *:= msc51
diff --git a/dmake/startup/templates/msdos/microsft/msc60/template.mk b/dmake/startup/templates/msdos/microsft/msc60/template.mk
new file mode 100644
index 000000000000..a147c694c5f7
--- /dev/null
+++ b/dmake/startup/templates/msdos/microsft/msc60/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= msdos
+ OSRELEASE *:= microsft
+ OSENVIRONMENT *:= msc60
diff --git a/dmake/startup/templates/os2/ibm/icc/template.mk b/dmake/startup/templates/os2/ibm/icc/template.mk
new file mode 100644
index 000000000000..c9c5adbf21ae
--- /dev/null
+++ b/dmake/startup/templates/os2/ibm/icc/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= os2
+ OSRELEASE *:= ibm
+ OSENVIRONMENT *:= icc
diff --git a/dmake/startup/templates/qssl/template.mk b/dmake/startup/templates/qssl/template.mk
new file mode 100644
index 000000000000..e7e9837ae671
--- /dev/null
+++ b/dmake/startup/templates/qssl/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= qssl
+ OSRELEASE *:=
+ OSENVIRONMENT *:=
diff --git a/dmake/startup/templates/tos/template.mk b/dmake/startup/templates/tos/template.mk
new file mode 100644
index 000000000000..91ce656f14b0
--- /dev/null
+++ b/dmake/startup/templates/tos/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= tos
+ OSRELEASE *:=
+ OSENVIRONMENT *:=
diff --git a/dmake/startup/templates/unix/386ix/template.mk b/dmake/startup/templates/unix/386ix/template.mk
new file mode 100644
index 000000000000..e59d37c7ca72
--- /dev/null
+++ b/dmake/startup/templates/unix/386ix/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= 386ix
+ OSENVIRONMENT *:=
diff --git a/dmake/startup/templates/unix/bsd43/template.mk b/dmake/startup/templates/unix/bsd43/template.mk
new file mode 100644
index 000000000000..14a7cab8ed4b
--- /dev/null
+++ b/dmake/startup/templates/unix/bsd43/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= bsd43
+ OSENVIRONMENT *:=
diff --git a/dmake/startup/templates/unix/bsd43/uw/template.mk b/dmake/startup/templates/unix/bsd43/uw/template.mk
new file mode 100644
index 000000000000..6afe91c1fc7a
--- /dev/null
+++ b/dmake/startup/templates/unix/bsd43/uw/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= bsd43
+ OSENVIRONMENT *:= uw
diff --git a/dmake/startup/templates/unix/bsd43/vf/template.mk b/dmake/startup/templates/unix/bsd43/vf/template.mk
new file mode 100644
index 000000000000..395cd4718fa0
--- /dev/null
+++ b/dmake/startup/templates/unix/bsd43/vf/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= bsd43
+ OSENVIRONMENT *:= vf
diff --git a/dmake/startup/templates/unix/coherent/ver40/template.mk b/dmake/startup/templates/unix/coherent/ver40/template.mk
new file mode 100644
index 000000000000..ef23550cf651
--- /dev/null
+++ b/dmake/startup/templates/unix/coherent/ver40/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= coherent
+ OSENVIRONMENT *:= ver40
diff --git a/dmake/startup/templates/unix/coherent/ver42/template.mk b/dmake/startup/templates/unix/coherent/ver42/template.mk
new file mode 100644
index 000000000000..e5dd9f99ffac
--- /dev/null
+++ b/dmake/startup/templates/unix/coherent/ver42/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= coherent
+ OSENVIRONMENT *:= ver42
diff --git a/dmake/startup/templates/unix/linux/gnu/template.mk b/dmake/startup/templates/unix/linux/gnu/template.mk
new file mode 100644
index 000000000000..a0bcef64097b
--- /dev/null
+++ b/dmake/startup/templates/unix/linux/gnu/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= linux
+ OSENVIRONMENT *:= gnu
diff --git a/dmake/startup/templates/unix/solaris/gnu/template.mk b/dmake/startup/templates/unix/solaris/gnu/template.mk
new file mode 100644
index 000000000000..3f9282027c5c
--- /dev/null
+++ b/dmake/startup/templates/unix/solaris/gnu/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= solaris
+ OSENVIRONMENT *:= gnu
diff --git a/dmake/startup/templates/unix/solaris/template.mk b/dmake/startup/templates/unix/solaris/template.mk
new file mode 100644
index 000000000000..233917a6ba92
--- /dev/null
+++ b/dmake/startup/templates/unix/solaris/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= solaris
+ OSENVIRONMENT *:=
diff --git a/dmake/startup/templates/unix/sysvr1/template.mk b/dmake/startup/templates/unix/sysvr1/template.mk
new file mode 100644
index 000000000000..4eb40febb3a1
--- /dev/null
+++ b/dmake/startup/templates/unix/sysvr1/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= sysvr1
+ OSENVIRONMENT *:=
diff --git a/dmake/startup/templates/unix/sysvr3/pwd/template.mk b/dmake/startup/templates/unix/sysvr3/pwd/template.mk
new file mode 100644
index 000000000000..fa6b4aa6bd1b
--- /dev/null
+++ b/dmake/startup/templates/unix/sysvr3/pwd/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= sysvr3
+ OSENVIRONMENT *:= pwd
diff --git a/dmake/startup/templates/unix/sysvr3/template.mk b/dmake/startup/templates/unix/sysvr3/template.mk
new file mode 100644
index 000000000000..3cb518671142
--- /dev/null
+++ b/dmake/startup/templates/unix/sysvr3/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= sysvr3
+ OSENVIRONMENT *:=
diff --git a/dmake/startup/templates/unix/sysvr4/template.mk b/dmake/startup/templates/unix/sysvr4/template.mk
new file mode 100644
index 000000000000..553878268e59
--- /dev/null
+++ b/dmake/startup/templates/unix/sysvr4/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= sysvr4
+ OSENVIRONMENT *:=
diff --git a/dmake/startup/templates/unix/xenix/pwd/template.mk b/dmake/startup/templates/unix/xenix/pwd/template.mk
new file mode 100644
index 000000000000..abd4066c347b
--- /dev/null
+++ b/dmake/startup/templates/unix/xenix/pwd/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= xenix
+ OSENVIRONMENT *:= pwd
diff --git a/dmake/startup/templates/unix/xenix/template.mk b/dmake/startup/templates/unix/xenix/template.mk
new file mode 100644
index 000000000000..7ab223fbdb9f
--- /dev/null
+++ b/dmake/startup/templates/unix/xenix/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= xenix
+ OSENVIRONMENT *:=
diff --git a/dmake/startup/templates/win95/borland/bcc50/template.mk b/dmake/startup/templates/win95/borland/bcc50/template.mk
new file mode 100644
index 000000000000..b5095c40ce2a
--- /dev/null
+++ b/dmake/startup/templates/win95/borland/bcc50/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= win95
+ OSRELEASE *:= borland
+ OSENVIRONMENT *:= bcc50
diff --git a/dmake/startup/templates/win95/microsft/vpp40/template.mk b/dmake/startup/templates/win95/microsft/vpp40/template.mk
new file mode 100644
index 000000000000..d4e6c9eb9f40
--- /dev/null
+++ b/dmake/startup/templates/win95/microsft/vpp40/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= win95
+ OSRELEASE *:= microsft
+ OSENVIRONMENT *:= vpp40
diff --git a/dmake/startup/templates/winnt/borland/bcc50/template.mk b/dmake/startup/templates/winnt/borland/bcc50/template.mk
new file mode 100644
index 000000000000..b94ac034e0a1
--- /dev/null
+++ b/dmake/startup/templates/winnt/borland/bcc50/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= winnt
+ OSRELEASE *:= borland
+ OSENVIRONMENT *:= bcc50
diff --git a/dmake/startup/templates/winnt/microsft/vpp40/template.mk b/dmake/startup/templates/winnt/microsft/vpp40/template.mk
new file mode 100644
index 000000000000..e53922df68c3
--- /dev/null
+++ b/dmake/startup/templates/winnt/microsft/vpp40/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= winnt
+ OSRELEASE *:= microsft
+ OSENVIRONMENT *:= vpp40
diff --git a/dmake/startup/tos/macros.mk b/dmake/startup/tos/macros.mk
new file mode 100644
index 000000000000..1023dfc9acd1
--- /dev/null
+++ b/dmake/startup/tos/macros.mk
@@ -0,0 +1,24 @@
+# Define Atari TOS specific macros.
+#
+
+# Process environment-specific refinements, if any.
+.IF $(OSENVIRONMENT)
+ .INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)$(OSENVIRONMENT)$/macros.mk
+.ENDIF
+
+# Set default to GCC Compiler.
+CPP *:= /gnu/lib/cpp
+CC *:= gcc
+"C++" *:= g++
+AS *:= gas
+YACC *:= bison
+LEX *:= flex
+RM *:= /bin/rm
+
+# Common flag settings
+ARFLAGS *= -rvs
+
+# Other appropriate macro settings.
+A *:= .olb
+SHELLFLAGS *:=
+GROUPSUFFIX *:= .bat
diff --git a/dmake/startup/unix/386ix/macros.mk b/dmake/startup/unix/386ix/macros.mk
new file mode 100644
index 000000000000..a359b302f546
--- /dev/null
+++ b/dmake/startup/unix/386ix/macros.mk
@@ -0,0 +1,6 @@
+# We hang off the standard sysvr3'isms
+#
+__.incdir !:= $(INCFILENAME:d:d:d:d)/sysvr3
+
+# Process environment-specific refinements, if any.
+.INCLUDE .SETDIR=$(__.incdir) .NOINFER .IGNORE : macros.mk
diff --git a/dmake/startup/unix/bsd43/macros.mk b/dmake/startup/unix/bsd43/macros.mk
new file mode 100644
index 000000000000..be4ae5fe45e9
--- /dev/null
+++ b/dmake/startup/unix/bsd43/macros.mk
@@ -0,0 +1,11 @@
+# Define additional Berkely UNIX specific macros.
+#
+
+# Process environment-specific refinements, if any.
+.IF $(OSENVIRONMENT)
+ .INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)$(OSENVIRONMENT)$/macros.mk
+.ENDIF
+
+# Set defaults for local OS release
+RANLIB *:= ranlib
+PRINT *:= lpr
diff --git a/dmake/startup/unix/bsd43/recipes.mk b/dmake/startup/unix/bsd43/recipes.mk
new file mode 100644
index 000000000000..557ac7c8c17b
--- /dev/null
+++ b/dmake/startup/unix/bsd43/recipes.mk
@@ -0,0 +1,13 @@
+# Define additional Berkeley UNIX specific build rules and recipes.
+#
+
+# Recipe to make archive files.
+%$A .GROUP :
+ $(AR) $(ARFLAGS) $@ $?
+ $(RM) $(RMFLAGS) $?
+ $(RANLIB) $@
+
+# Process environment-specific refinements, if any.
+.IF $(OSENVIRONMENT)
+ .INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)$(OSENVIRONMENT)$/recipes.mk
+.ENDIF
diff --git a/dmake/startup/unix/coherent/macros.mk b/dmake/startup/unix/coherent/macros.mk
new file mode 100644
index 000000000000..e0201ebd14ba
--- /dev/null
+++ b/dmake/startup/unix/coherent/macros.mk
@@ -0,0 +1,6 @@
+# We hang off the standard BSD'isms
+#
+__.incdir !:= $(INCFILENAME:d:d:d:d)/bsd43
+
+# Process environment-specific refinements, if any.
+.INCLUDE .SETDIR=$(__.incdir) .NOINFER .IGNORE : macros.mk
diff --git a/dmake/startup/unix/coherent/recipes.mk b/dmake/startup/unix/coherent/recipes.mk
new file mode 100644
index 000000000000..5966640d3621
--- /dev/null
+++ b/dmake/startup/unix/coherent/recipes.mk
@@ -0,0 +1,6 @@
+# Use the same file as
+#
+__.incdir !:= $(INCFILENAME:d:d:d:d)/bsd43
+
+# Process environment-specific refinements, if any.
+.INCLUDE .SETDIR=$(__.incdir) .NOINFER .IGNORE : recipes.mk
diff --git a/dmake/startup/unix/linux/gnu/macros.mk b/dmake/startup/unix/linux/gnu/macros.mk
new file mode 100644
index 000000000000..3d9c437d9e70
--- /dev/null
+++ b/dmake/startup/unix/linux/gnu/macros.mk
@@ -0,0 +1,6 @@
+# We hang off the standard sysvr3'isms
+#
+__.incdir !:= $(INCFILENAME:d:d:d:d:d:d)/sysvr3/gnu
+
+# Process environment-specific refinements, if any.
+.INCLUDE .SETDIR=$(__.incdir) .NOINFER .IGNORE : macros.mk
diff --git a/dmake/startup/unix/linux/macros.mk b/dmake/startup/unix/linux/macros.mk
new file mode 100644
index 000000000000..228dafff2992
--- /dev/null
+++ b/dmake/startup/unix/linux/macros.mk
@@ -0,0 +1,10 @@
+# Define additional Linux specific macros.
+#
+
+# Process environment-specific refinements, if any.
+.IF $(OSENVIRONMENT)
+ .INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)$(OSENVIRONMENT)$/macros.mk
+.ENDIF
+
+# Make OS-release-specific settings
+PRINT *:= lpr
diff --git a/dmake/startup/unix/macosx/gnu/macros.mk b/dmake/startup/unix/macosx/gnu/macros.mk
new file mode 100644
index 000000000000..3d9c437d9e70
--- /dev/null
+++ b/dmake/startup/unix/macosx/gnu/macros.mk
@@ -0,0 +1,6 @@
+# We hang off the standard sysvr3'isms
+#
+__.incdir !:= $(INCFILENAME:d:d:d:d:d:d)/sysvr3/gnu
+
+# Process environment-specific refinements, if any.
+.INCLUDE .SETDIR=$(__.incdir) .NOINFER .IGNORE : macros.mk
diff --git a/dmake/startup/unix/macosx/macros.mk b/dmake/startup/unix/macosx/macros.mk
new file mode 100644
index 000000000000..b29e917ec8e1
--- /dev/null
+++ b/dmake/startup/unix/macosx/macros.mk
@@ -0,0 +1,10 @@
+# Define additional Mac OS X specific macros.
+#
+
+# Process environment-specific refinements, if any.
+.IF $(OSENVIRONMENT)
+ .INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)$(OSENVIRONMENT)$/macros.mk
+.ENDIF
+
+# Make OS-release-specific settings
+PRINT *:= lpr
diff --git a/dmake/startup/unix/macros.mk b/dmake/startup/unix/macros.mk
new file mode 100644
index 000000000000..362b81d2c2f6
--- /dev/null
+++ b/dmake/startup/unix/macros.mk
@@ -0,0 +1,5 @@
+# Define additional UNIX specific macros.
+#
+
+# Process release-specific refinements, if any.
+.INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)$(OSRELEASE)$/macros.mk
diff --git a/dmake/startup/unix/recipes.mk b/dmake/startup/unix/recipes.mk
new file mode 100644
index 000000000000..1650430f3ed8
--- /dev/null
+++ b/dmake/startup/unix/recipes.mk
@@ -0,0 +1,15 @@
+# Define additional UNIX specific build recipes.
+#
+
+# Define additional build targets.
+%$E : %.sh; cp $< $@; chmod 0777 $@
+
+# This rule tells how to make a non-suffixed executable from its single
+# file source.
+% : %$O; $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS)
+
+# This rule tells how to make a.out from it's immediate list of prerequisites.
+%.out :; $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+# Process release-specific refinements, if any.
+.INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)$(OSRELEASE)$/recipes.mk
diff --git a/dmake/startup/unix/solaris/macros.mk b/dmake/startup/unix/solaris/macros.mk
new file mode 100644
index 000000000000..a359b302f546
--- /dev/null
+++ b/dmake/startup/unix/solaris/macros.mk
@@ -0,0 +1,6 @@
+# We hang off the standard sysvr3'isms
+#
+__.incdir !:= $(INCFILENAME:d:d:d:d)/sysvr3
+
+# Process environment-specific refinements, if any.
+.INCLUDE .SETDIR=$(__.incdir) .NOINFER .IGNORE : macros.mk
diff --git a/dmake/startup/unix/sysvr1/macros.mk b/dmake/startup/unix/sysvr1/macros.mk
new file mode 100644
index 000000000000..a359b302f546
--- /dev/null
+++ b/dmake/startup/unix/sysvr1/macros.mk
@@ -0,0 +1,6 @@
+# We hang off the standard sysvr3'isms
+#
+__.incdir !:= $(INCFILENAME:d:d:d:d)/sysvr3
+
+# Process environment-specific refinements, if any.
+.INCLUDE .SETDIR=$(__.incdir) .NOINFER .IGNORE : macros.mk
diff --git a/dmake/startup/unix/sysvr3/gnu/macros.mk b/dmake/startup/unix/sysvr3/gnu/macros.mk
new file mode 100644
index 000000000000..13141971fe40
--- /dev/null
+++ b/dmake/startup/unix/sysvr3/gnu/macros.mk
@@ -0,0 +1,12 @@
+# System V R3 GCC compiler specific macro definitions...
+#
+
+# Common tool renamings
+CC *:= gcc
+"C++" *:= g++
+AS *:= gas
+YACC *:= bison
+LEX *:= flex
+
+# Common flag settings
+ARFLAGS *= -rvs
diff --git a/dmake/startup/unix/sysvr3/macros.mk b/dmake/startup/unix/sysvr3/macros.mk
new file mode 100644
index 000000000000..2ccd730acfc0
--- /dev/null
+++ b/dmake/startup/unix/sysvr3/macros.mk
@@ -0,0 +1,7 @@
+# Define additional UNIX specific macros.
+#
+
+# Process environment-specific refinements, if any.
+.IF $(OSENVIRONMENT)
+ .INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)$(OSENVIRONMENT)$/macros.mk
+.ENDIF
diff --git a/dmake/startup/unix/sysvr4/macros.mk b/dmake/startup/unix/sysvr4/macros.mk
new file mode 100644
index 000000000000..a359b302f546
--- /dev/null
+++ b/dmake/startup/unix/sysvr4/macros.mk
@@ -0,0 +1,6 @@
+# We hang off the standard sysvr3'isms
+#
+__.incdir !:= $(INCFILENAME:d:d:d:d)/sysvr3
+
+# Process environment-specific refinements, if any.
+.INCLUDE .SETDIR=$(__.incdir) .NOINFER .IGNORE : macros.mk
diff --git a/dmake/startup/unix/xenix/macros.mk b/dmake/startup/unix/xenix/macros.mk
new file mode 100644
index 000000000000..a359b302f546
--- /dev/null
+++ b/dmake/startup/unix/xenix/macros.mk
@@ -0,0 +1,6 @@
+# We hang off the standard sysvr3'isms
+#
+__.incdir !:= $(INCFILENAME:d:d:d:d)/sysvr3
+
+# Process environment-specific refinements, if any.
+.INCLUDE .SETDIR=$(__.incdir) .NOINFER .IGNORE : macros.mk
diff --git a/dmake/startup/win95/borland/macros.mk b/dmake/startup/win95/borland/macros.mk
new file mode 100644
index 000000000000..2017f02d3f1f
--- /dev/null
+++ b/dmake/startup/win95/borland/macros.mk
@@ -0,0 +1,34 @@
+# MSDOS Borland-C environment customization.
+
+.IF $(OSENVIRONMENT)
+ .INCLUDE .IGNORE .NOINFER : $(INCFILENAME:d)$(OSENVIRONMENT)$/macros.mk
+.ENDIF
+
+# Standard C-language command names and flags
+CPP *:= # C-preprocessor
+CC *:= bcc32
+CFLAGS *= # C compiler flags
+"C++" *:= # C++ Compiler
+"C++FLAGS" *= # C++ Compiler flags
+
+AS *:= tasm # Assembler and flags
+ASFLAGS *=
+LD *= tlink32 # Loader and flags
+LDFLAGS *=
+LDLIBS *= # Default libraries
+AR *:= tlib # archiver
+ARFLAGS *= ????
+
+# Definition of Print command for this system.
+PRINT *= print
+
+# Language and Parser generation Tools and their flags
+YACC *:= yacc # standard yacc
+YFLAGS *=
+LEX *:= lex # standard lex
+LFLAGS *=
+
+# Other Compilers, Tools and their flags
+PC *:= tpc # pascal compiler
+RC *:= ??? # ratfor compiler
+FC *:= ??? # fortran compiler
diff --git a/dmake/startup/win95/macros.mk b/dmake/startup/win95/macros.mk
new file mode 100644
index 000000000000..72707c23bbe3
--- /dev/null
+++ b/dmake/startup/win95/macros.mk
@@ -0,0 +1,64 @@
+# Define additional MSDOS specific settings.
+#
+
+# Execution environment configuration.
+# Grab the current setting of COMSPEC.
+#
+.IMPORT .IGNORE : COMSPEC
+
+# First check if SHELL is defined to be something other than COMSPEC.
+# If it is, then assume that SHELL is a Korn compatible shell like MKS's
+.IF $(SHELL) == $(NULL)
+ .IF $(COMSPEC) == $(NULL)
+ SHELL *:= $(ROOTDIR)$/bin$/sh$E
+ .ELSE
+ SHELL *:= $(COMSPEC)
+ .END
+.END
+GROUPSHELL *:= $(SHELL)
+
+# Process release-specific refinements, if any.
+.INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)$(OSRELEASE)$/macros.mk
+
+# Applicable suffix definitions
+A *:= .lib # Libraries
+E *:= .exe # Executables
+F *:= .for # Fortran
+O *:= .obj # Objects
+P *:= .pas # Pascal
+S *:= .asm # Assembler sources
+V *:= # RCS suffix
+
+# Now set the remaining arguments depending on which SHELL we
+# are going to use. COMSPEC (assumed to be command.com) or
+# MKS Korn shell.
+.IF $(SHELL) == $(COMSPEC)
+ SHELLFLAGS *:= $(SWITCHAR)c
+ GROUPFLAGS *:= $(SHELLFLAGS)
+ SHELLMETAS *:= "<>|
+ GROUPSUFFIX *:= .bat
+ DIVFILE *= $(TMPFILE:s,/,\)
+ RM *= del
+ RMFLAGS *=
+ MV *= rename
+ __.DIVSEP-sh-yes *:= \\
+ __.DIVSEP-sh-no *:= \\
+.ELSE
+ SHELL !:= $(SHELL:s,/,\,)
+ COMMAND *= $(CMNDNAME:s,/,\,) $(CMNDARGS)
+ SHELLFLAGS *:= -c
+ GROUPFLAGS *:=
+ SHELLMETAS *:= *";?<>|()&][$$\#`'
+ GROUPSUFFIX *:= .ksh
+ .MKSARGS *:= yes
+ RM *= $(ROOTDIR)$/bin$/rm
+ RMFLAGS *= -f
+ MV *= $(ROOTDIR)$/bin$/mv
+ DIVFILE *= $(TMPFILE:s,/,${__.DIVSEP-sh-${USESHELL}})
+ __.DIVSEP-sh-yes *:= \\\
+ __.DIVSEP-sh-no *:= \\
+.ENDIF
+
+
+# Does not respect case of filenames.
+.DIRCACHERESPCASE := no
diff --git a/dmake/startup/win95/microsft/macros.mk b/dmake/startup/win95/microsft/macros.mk
new file mode 100644
index 000000000000..f10b1fdfa69d
--- /dev/null
+++ b/dmake/startup/win95/microsft/macros.mk
@@ -0,0 +1,38 @@
+# MSDOS Microsoft-C environment customization.
+
+.IF $(OSENVIRONMENT)
+ .INCLUDE .IGNORE .NOINFER : $(INCFILENAME:d)$(OSENVIRONMENT)$/macros.mk
+.ENDIF
+
+# Standard C-language command names and flags
+CC *:= cl # C compiler
+CPP *:= # C-preprocessor
+CFLAGS *= # C compiler flags
+"C++" *:= # C++ Compiler
+"C++FLAGS" *= # C++ Compiler flags
+
+AS *:= masm # Assembler and flags
+ASFLAGS *=
+LD *= link # Loader and flags
+LDFLAGS *=
+LDLIBS *= # Default libraries
+AR *:= lib # archiver
+ARFLAGS *= ????
+
+# Definition of Print command for this system.
+PRINT *= print
+
+# Language and Parser generation Tools and their flags
+YACC *:= yacc # standard yacc
+YFLAGS *=
+LEX *:= lex # standard lex
+LFLAGS *=
+
+# Other Compilers, Tools and their flags
+PC *:= ??? # pascal compiler
+RC *:= ??? # ratfor compiler
+FC *:= ??? # fortran compiler
+
+
+# Directory cache configuration.
+.DIRCACHE *:= no
diff --git a/dmake/startup/win95/recipes.mk b/dmake/startup/win95/recipes.mk
new file mode 100644
index 000000000000..5a98f22b1e05
--- /dev/null
+++ b/dmake/startup/win95/recipes.mk
@@ -0,0 +1,9 @@
+# Define additional MSDOS specific build recipes.
+#
+
+# Executables
+ %$E : %$O ; $(CC) $(LDFLAGS) -o$@ $< $(LDLIBS)
+ %$O : %$S ; $(AS) $(ASFLAGS) $(<:s,/,\)
+
+# Process release-specific refinements, if any.
+.INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)$(OSRELEASE)$/recipes.mk
diff --git a/dmake/startup/winnt/borland/macros.mk b/dmake/startup/winnt/borland/macros.mk
new file mode 100644
index 000000000000..2017f02d3f1f
--- /dev/null
+++ b/dmake/startup/winnt/borland/macros.mk
@@ -0,0 +1,34 @@
+# MSDOS Borland-C environment customization.
+
+.IF $(OSENVIRONMENT)
+ .INCLUDE .IGNORE .NOINFER : $(INCFILENAME:d)$(OSENVIRONMENT)$/macros.mk
+.ENDIF
+
+# Standard C-language command names and flags
+CPP *:= # C-preprocessor
+CC *:= bcc32
+CFLAGS *= # C compiler flags
+"C++" *:= # C++ Compiler
+"C++FLAGS" *= # C++ Compiler flags
+
+AS *:= tasm # Assembler and flags
+ASFLAGS *=
+LD *= tlink32 # Loader and flags
+LDFLAGS *=
+LDLIBS *= # Default libraries
+AR *:= tlib # archiver
+ARFLAGS *= ????
+
+# Definition of Print command for this system.
+PRINT *= print
+
+# Language and Parser generation Tools and their flags
+YACC *:= yacc # standard yacc
+YFLAGS *=
+LEX *:= lex # standard lex
+LFLAGS *=
+
+# Other Compilers, Tools and their flags
+PC *:= tpc # pascal compiler
+RC *:= ??? # ratfor compiler
+FC *:= ??? # fortran compiler
diff --git a/dmake/startup/winnt/macros.mk b/dmake/startup/winnt/macros.mk
new file mode 100644
index 000000000000..63fa7983d503
--- /dev/null
+++ b/dmake/startup/winnt/macros.mk
@@ -0,0 +1,64 @@
+# Define additional MSDOS specific settings.
+#
+
+# Execution environment configuration.
+# Grab the current setting of COMSPEC.
+#
+.IMPORT .IGNORE : COMSPEC
+
+# First check if SHELL is defined to be something other than COMSPEC.
+# If it is, then assume that SHELL is a Korn compatible shell like MKS's
+.IF $(SHELL) == $(NULL)
+ .IF $(COMSPEC) == $(NULL)
+ SHELL *:= $(ROOTDIR)$/bin$/sh$E
+ .ELSE
+ SHELL *:= $(COMSPEC)
+ .END
+.END
+GROUPSHELL *:= $(SHELL)
+
+# Process release-specific refinements, if any.
+.INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)$(OSRELEASE)$/macros.mk
+
+# Applicable suffix definitions
+A *:= .lib # Libraries
+E *:= .exe # Executables
+F *:= .for # Fortran
+O *:= .obj # Objects
+P *:= .pas # Pascal
+S *:= .asm # Assembler sources
+V *:= # RCS suffix
+
+# Now set the remaining arguments depending on which SHELL we
+# are going to use. COMSPEC (assumed to be command.com) or
+# MKS Korn shell.
+.IF $(SHELL) == $(COMSPEC)
+ SHELLFLAGS *:= $(SWITCHAR)c
+ GROUPFLAGS *:= $(SHELLFLAGS)
+ SHELLMETAS *:= "<>|
+ GROUPSUFFIX *:= .cmd
+ DIVFILE *= $(TMPFILE:s,/,\)
+ RM *= del
+ RMFLAGS *=
+ MV *= rename
+ __.DIVSEP-sh-yes *:= \\
+ __.DIVSEP-sh-no *:= \\
+.ELSE
+ SHELL !:= $(SHELL:s,/,\,)
+ COMMAND *= $(CMNDNAME:s,/,\,) $(CMNDARGS)
+ SHELLFLAGS *:= -c
+ GROUPFLAGS *:=
+ SHELLMETAS *:= *";?<>|()&][$$\#`'
+ GROUPSUFFIX *:= .ksh
+ .MKSARGS *:= yes
+ RM *= $(ROOTDIR)$/bin$/rm
+ RMFLAGS *= -f
+ MV *= $(ROOTDIR)$/bin$/mv
+ DIVFILE *= $(TMPFILE:s,/,${__.DIVSEP-sh-${USESHELL}})
+ __.DIVSEP-sh-yes *:= \\\
+ __.DIVSEP-sh-no *:= \\
+.ENDIF
+
+
+# Does not respect case of filenames.
+.DIRCACHERESPCASE := no
diff --git a/dmake/startup/winnt/microsft/macros.mk b/dmake/startup/winnt/microsft/macros.mk
new file mode 100644
index 000000000000..eed3fbdeeedb
--- /dev/null
+++ b/dmake/startup/winnt/microsft/macros.mk
@@ -0,0 +1,37 @@
+# MSDOS Microsoft-C environment customization.
+
+.IF $(OSENVIRONMENT)
+ .INCLUDE .IGNORE .NOINFER : $(INCFILENAME:d)$(OSENVIRONMENT)$/macros.mk
+.ENDIF
+
+# Standard C-language command names and flags
+CC *:= cl # C compiler
+CPP *:= # C-preprocessor
+CFLAGS *= # C compiler flags
+"C++" *:= # C++ Compiler
+"C++FLAGS" *= # C++ Compiler flags
+
+AS *:= masm # Assembler and flags
+ASFLAGS *=
+LD *= link # Loader and flags
+LDFLAGS *=
+LDLIBS *= # Default libraries
+AR *:= lib # archiver
+ARFLAGS *= ????
+
+# Definition of Print command for this system.
+PRINT *= print
+
+# Language and Parser generation Tools and their flags
+YACC *:= yacc # standard yacc
+YFLAGS *=
+LEX *:= lex # standard lex
+LFLAGS *=
+
+# Other Compilers, Tools and their flags
+PC *:= ??? # pascal compiler
+RC *:= ??? # ratfor compiler
+FC *:= ??? # fortran compiler
+
+# Directory cache configuration.
+.DIRCACHE *:= no
diff --git a/dmake/startup/winnt/recipes.mk b/dmake/startup/winnt/recipes.mk
new file mode 100644
index 000000000000..5a98f22b1e05
--- /dev/null
+++ b/dmake/startup/winnt/recipes.mk
@@ -0,0 +1,9 @@
+# Define additional MSDOS specific build recipes.
+#
+
+# Executables
+ %$E : %$O ; $(CC) $(LDFLAGS) -o$@ $< $(LDLIBS)
+ %$O : %$S ; $(AS) $(ASFLAGS) $(<:s,/,\)
+
+# Process release-specific refinements, if any.
+.INCLUDE .NOINFER .IGNORE : $(INCFILENAME:d)$(OSRELEASE)$/recipes.mk
diff --git a/dmake/stat.c b/dmake/stat.c
new file mode 100644
index 000000000000..aee8a18e1c23
--- /dev/null
+++ b/dmake/stat.c
@@ -0,0 +1,263 @@
+/* RCS $Id: stat.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Bind a target name to a file.
+--
+-- DESCRIPTION
+-- This file contains the code to go and stat a target. The stat rules
+-- follow a predefined order defined in the comment for Stat_target.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+
+static int _check_dir_list ANSI((CELLPTR, CELLPTR, int, int));
+
+#ifdef DBUG
+ /* Just a little ditty for debugging this thing */
+ static time_t
+ _do_stat( name, lib, sym, force )
+ char *name;
+ char *lib;
+ char **sym;
+ int force;
+ {
+ time_t res;
+ DB_ENTER( "_do_stat" );
+
+ res = Do_stat(name, lib, sym, force);
+ DB_PRINT( "stat", ("Statted [%s,%s,%d,%ld]", name, lib, sym, res) );
+
+ DB_RETURN( res );
+ }
+#define DO_STAT(A,B,C,D) _do_stat(A,B,C,D)
+#else
+#define DO_STAT(A,B,C,D) Do_stat(A,B,C,D)
+#endif
+
+static char *_first; /* local storage of first attempted path */
+
+PUBLIC void
+Stat_target( cp, setfname, force )/*
+====================================
+ Stat a target. When doing so follow the following rules, suppose
+ that cp->CE_NAME points at a target called fred.o:
+
+ 0. If A_SYMBOL attribute set look into the library
+ then do the steps 1 thru 4 on the resulting name.
+ 1. Try path's obtained by prepending any dirs found as
+ prerequisites for .SOURCE.o.
+ 2. If not found, do same as 2 but use .SOURCE
+ 3. If not found and .LIBRARYM attribute for the target is
+ set then look for it in the corresponding library.
+ 4. If found in step 0 thru 3, then ce_fname points at
+ file name associate with target, else ce_fname points
+ at a file name built by the first .SOURCE* dir that
+ applied. */
+
+CELLPTR cp;
+int setfname;
+int force;
+{
+ register HASHPTR hp;
+ static HASHPTR srchp = NIL(HASH);
+ char *name;
+ char *tmp;
+ int res = 0;
+
+ DB_ENTER( "Stat_target" );
+
+ name = cp->CE_NAME;
+ if( srchp == NIL(HASH) ) srchp = Get_name(".SOURCE",Defs,FALSE);
+
+ /* Look for a symbol of the form lib((symbol)) the name of the symbol
+ * as entered in the hash table is (symbol) so pull out symbol and try
+ * to find it's module. If successful DO_STAT will return the module
+ * as well as the archive member name (pointed at by tmp). We then
+ * replace the symbol name with the archive member name so that we
+ * have the proper name for any future refrences. */
+
+ if( cp->ce_attr & A_SYMBOL ) {
+ DB_PRINT( "stat", ("Binding lib symbol [%s]", name) );
+
+ cp->ce_time = DO_STAT( name, cp->ce_lib, &tmp, force );
+
+ if( cp->ce_time != (time_t) 0L ) {
+ /* stat the new member name below note tmp must point at a string
+ * returned by MALLOC... ie. the Do_stat code should use DmStrDup */
+
+ if( Verbose & V_MAKE )
+ printf( "%s: Mapped ((%s)) to %s(%s)\n", Pname,
+ name, cp->ce_lib, tmp );
+
+ FREE( name );
+ name = cp->CE_NAME = tmp;
+ cp->ce_attr &= ~(A_FFNAME | A_SYMBOL);
+ }
+ else
+ { DB_VOID_RETURN; }
+ }
+
+ _first = NIL(char);
+ tmp = DmStrJoin( ".SOURCE", Get_suffix(name), -1, FALSE);
+
+ /* Check .SOURCE.xxx target */
+ if( (hp = Get_name(tmp, Defs, FALSE)) != NIL(HASH) )
+ res = _check_dir_list( cp, hp->CP_OWNR, setfname, force );
+
+ /* Check just .SOURCE */
+ if( !res && (srchp != NIL(HASH)) )
+ res = _check_dir_list( cp, srchp->CP_OWNR, setfname, force );
+
+ /* If libmember and we haven't found it check the library */
+ if( !res && (cp->ce_attr & A_LIBRARYM) ) {
+ cp->ce_time = DO_STAT(name, cp->ce_lib, NIL(char *), force);
+
+ if( !cp->ce_time && Tmd && *Tmd && cp->ce_lib ) {
+ char *tmplib;
+ tmplib=DmStrDup(Build_path(Tmd,cp->ce_lib));
+
+ if ((cp->ce_time = DO_STAT(name, tmplib, NIL(char *),force)) != (time_t)0L){
+ cp->ce_lib=DmStrDup(tmplib);
+ }
+ }
+
+ if( Verbose & V_MAKE )
+ printf( "%s: Checking library '%s' for member [%s], time %ld\n",
+ Pname, cp->ce_lib, name, cp->ce_time );
+ }
+
+ FREE( tmp );
+
+ if( setfname == 1 || (setfname == -1 && cp->ce_time != (time_t)0L) ) {
+ int setlib = (cp->ce_lib == cp->ce_fname);
+
+ if( (cp->ce_attr & A_FFNAME) && (cp->ce_fname != NIL(char)) )
+ FREE( cp->ce_fname );
+
+ if( _first != NIL(char) ) {
+ cp->ce_fname = _first;
+ cp->ce_attr |= A_FFNAME;
+ }
+ else {
+ cp->ce_fname = cp->CE_NAME;
+ cp->ce_attr &= ~A_FFNAME;
+ }
+
+ if ( setlib ) cp->ce_lib = cp->ce_fname;
+ }
+ else if( _first )
+ FREE( _first );
+
+ /* set it as stated only if successful, this way, we shall try again
+ * later. */
+ if( cp->ce_time != (time_t)0L ) {
+ cp->ce_flag |= F_STAT;
+
+ /* If it is a whatif this changed scenario then return the current
+ * time, but do so only if the stat was successful. */
+ if ( (cp->ce_attr & A_WHATIF) && !(cp->ce_flag & F_MADE) ) {
+ cp->ce_time = Do_time();
+ }
+ }
+
+ DB_VOID_RETURN;
+}
+
+
+static int
+_check_dir_list( cp, sp, setfname, force )/*
+============================================
+ Check the list of dir's given by the prerequisite list of sp, for a
+ file pointed at by cp. Returns 0 if path not bound, else returns
+ 1 and replaces old name for cell with new cell name. */
+
+CELLPTR cp;
+CELLPTR sp;
+int setfname;
+int force;
+{
+ /* FIXME: BCC 5.0 BUG??? If lp is assigned to a register variable then
+ * BCC 5.0 corrupts a field of the member structure when DO_STAT
+ * calls the native win95 stat system call. Blech!!!
+ *
+ * Making this a static variable forces it out of a register and
+ * seems to avoid the problem. */
+ static LINKPTR lp;
+ char *dir;
+ char *path;
+ char *name;
+ int res = 0;
+ int fset = 0;
+
+ DB_ENTER( "_check_dir_list" );
+ DB_PRINT( "mem", ("%s:-> mem %ld", cp->CE_NAME, (long) coreleft()) );
+
+ if( sp->ce_prq != NIL(LINK) ) /* check prerequisites if any */
+ {
+ /* Use the real name instead of basename, this prevents silly
+ * loops in inference code, and is consistent with man page */
+ name = cp->CE_NAME;
+
+ /* Here we loop through each directory on the list, and try to stat
+ * the target. We always save the first pathname we try to stat in
+ * _first. If we subsequently get a match we then replace the value of
+ * _first by the matched path name. */
+
+ for( lp=sp->CE_PRQ; lp != NIL(LINK) && !res; lp=lp->cl_next ) {
+ int nodup = 0;
+ dir = lp->cl_prq->CE_NAME;
+
+ if( strchr( dir, '$' ) ) dir = Expand(dir);
+ if( strcmp( dir, ".NULL" ) == 0 ) {
+ nodup = 1;
+ path = cp->CE_NAME;
+ } else {
+ path = DmStrDup(Build_path(dir,name));
+ }
+
+ res = ((cp->ce_time=DO_STAT(path,NIL(char),NIL(char *),force))!=(time_t)0L);
+
+ /* Have to use DmStrDup to set _first since Build_path, builds it's
+ * path names inside a static buffer. */
+ if( setfname )
+ if( (_first == NIL(char) && !fset) || res ) {
+ if( _first != NIL(char) ) FREE( _first );
+ if (nodup)
+ _first = NIL(char);
+ else {
+ _first = path;
+ path = NIL(char);
+ }
+ fset = 1;
+ }
+
+ DB_PRINT( "stat", ("_first [%s], path [%s]", _first, path) );
+ if( dir != lp->cl_prq->CE_NAME ) FREE(dir);
+ if( path && path != cp->CE_NAME ) FREE(path);
+ }
+ }
+
+ DB_PRINT( "mem", ("%s:-< mem %ld", cp->CE_NAME, (long) coreleft()) );
+ DB_RETURN( res );
+}
+
+
+
+
diff --git a/dmake/state.c b/dmake/state.c
new file mode 100644
index 000000000000..7b5a2fe79ab8
--- /dev/null
+++ b/dmake/state.c
@@ -0,0 +1,229 @@
+/* RCS $Id: state.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- .KEEP_STATE state file management
+--
+-- DESCRIPTION
+-- Three routines to interface to the .KEEP_STATE state file.
+--
+-- Read_state() - reads the state file if any.
+-- Write_state() - writes the state file.
+--
+-- Check_state(cp,how) - checks an entry returns 0 or 1
+-- and updates the entry.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+typedef struct se {
+ char *st_name; /* name of cell */
+ uint32 st_nkey; /* name hash key */
+ int st_count; /* how count for how */
+ uint32 st_dkey; /* directory hash key */
+ uint32 st_key; /* hash key */
+ struct se *st_next;
+} KSTATE, *KSTATEPTR;
+
+static KSTATEPTR _st_head = NIL(KSTATE);
+static KSTATEPTR _st_tail = NIL(KSTATE);
+static int _st_upd = FALSE;
+static char *_st_file = NIL(char);
+
+static int _my_fgets ANSI((char *, int, FILE *));
+
+PUBLIC void
+Read_state()
+{
+ char *buf;
+ char sizeb[20];
+ int size;
+ FILE *fp;
+ KSTATEPTR sp;
+
+ if( (fp = Search_file(".KEEP_STATE", &_st_file)) != NIL(FILE) ) {
+ if( _my_fgets( sizeb, 20, fp ) ) {
+ size = atol(sizeb);
+ buf = MALLOC(size+2, char);
+
+ while( _my_fgets(buf, size, fp) ) {
+ TALLOC(sp, 1, KSTATE);
+ sp->st_name = DmStrDup(buf);
+ (void) Hash(buf, &sp->st_nkey);
+
+ if( _my_fgets(buf, size, fp) ) sp->st_count = atoi(buf);
+ if( _my_fgets(buf, size, fp) ) sp->st_dkey = (uint32) atol(buf);
+
+ if( _my_fgets(buf, size, fp) )
+ sp->st_key = (uint32) atol(buf);
+ else {
+ FREE(sp);
+ break;
+ }
+
+ if( _st_head == NIL(KSTATE) )
+ _st_head = sp;
+ else
+ _st_tail->st_next = sp;
+
+ _st_tail = sp;
+ }
+
+ FREE(buf);
+ }
+
+ Closefile();
+ }
+}
+
+
+PUBLIC void
+Write_state()
+{
+ static int in_write = 0;
+ register KSTATEPTR sp;
+ FILE *fp;
+
+ if( !_st_upd || !_st_file || (_st_file && !*_st_file) ||
+ Trace || in_write ) return;
+
+ in_write++;
+ if( (fp = Openfile(_st_file, TRUE, TRUE)) != NIL(FILE) ) {
+ int maxlen = 0;
+ int tmplen;
+
+ for( sp = _st_head; sp; sp=sp->st_next )
+ if( (tmplen = strlen(sp->st_name)+2) > maxlen )
+ maxlen = tmplen;
+
+ /* A nice arbitrary minimum size */
+ if( maxlen < 20 ) maxlen = 20;
+ fprintf( fp, "%d\n", maxlen );
+
+ for( sp = _st_head; sp; sp=sp->st_next ) {
+ uint16 hv;
+ uint32 hk;
+
+ if( Search_table(Defs, sp->st_name, &hv, &hk) ) {
+ fprintf( fp, "%s\n", sp->st_name );
+ fprintf( fp, "%d\n", sp->st_count );
+ fprintf( fp, "%lu\n", sp->st_dkey );
+ fprintf( fp, "%lu\n", sp->st_key );
+ }
+ }
+
+ Closefile();
+ }
+ else
+ Fatal("Cannot open STATE file %s", _st_file);
+
+ in_write = 0;
+}
+
+
+PUBLIC int
+Check_state( cp, recipes, maxrcp )
+CELLPTR cp;
+STRINGPTR *recipes;
+int maxrcp;
+{
+ KSTATEPTR st;
+ STRINGPTR sp;
+ int i;
+ uint32 thkey;
+ uint32 hkey;
+ uint32 nkey;
+ uint32 dkey;
+ int update = FALSE;
+
+ if( !_st_file || (_st_file && !*_st_file) || Trace )
+ return(FALSE);
+
+ if( strcmp(cp->CE_NAME,".REMOVE") == 0
+ || (cp->ce_attr & (A_PHONY|A_NOSTATE)) )
+ return(FALSE);
+
+ (void) Hash( cp->CE_NAME, &nkey ); thkey = nkey + (uint32) cp->ce_count;
+ (void) Hash( Pwd, &dkey ); thkey += dkey;
+
+ Suppress_temp_file = TRUE;
+ for( i=0 ; i<maxrcp; i++ )
+ for(sp=recipes[i]; sp != NIL(STRING); sp=sp->st_next ) {
+ CELLPTR svct = Current_target;
+ char *cmnd;
+ t_attr silent = (Glob_attr & A_SILENT);
+
+ Current_target = cp;
+ Glob_attr |= A_SILENT;
+ cmnd = Expand(sp->st_string);
+ Glob_attr = (Glob_attr & ~A_SILENT)|silent;
+ Current_target = svct;
+
+ (void) Hash(cmnd, &hkey); thkey += hkey;
+ FREE(cmnd);
+ }
+ Suppress_temp_file = FALSE;
+
+ for( st=_st_head; st != NIL(KSTATE); st=st->st_next ) {
+ if( st->st_nkey == nkey
+ && st->st_dkey == dkey
+ && st->st_count == cp->ce_count
+ && !strcmp(cp->CE_NAME, st->st_name) )
+ break;
+ }
+
+ if( st == NIL(KSTATE) ) {
+ KSTATEPTR nst;
+
+ TALLOC(nst, 1, KSTATE);
+ nst->st_name = cp->CE_NAME;
+ nst->st_nkey = nkey;
+ nst->st_dkey = dkey;
+ nst->st_key = thkey;
+ nst->st_count = cp->ce_count;
+
+ if( _st_head == NIL(KSTATE) )
+ _st_head = nst;
+ else
+ _st_tail->st_next = nst;
+
+ _st_tail = nst;
+ _st_upd = TRUE;
+ }
+ else if( st->st_key != thkey ) {
+ st->st_key = thkey;
+ _st_upd = update = TRUE;
+ }
+
+ return(st != NIL(KSTATE) && update);
+}
+
+
+static int
+_my_fgets(buf, size, fp)
+char *buf;
+int size;
+FILE *fp;
+{
+ char *p;
+
+ if( fgets(buf, size, fp) == NULL ) return(0);
+
+ if( (p=strrchr(buf,'\n')) != NIL(char) ) *p='\0';
+ return(1);
+}
diff --git a/dmake/stdmacs.h b/dmake/stdmacs.h
new file mode 100644
index 000000000000..a2b6aa3dfa9b
--- /dev/null
+++ b/dmake/stdmacs.h
@@ -0,0 +1,56 @@
+/* RCS $Id: stdmacs.h,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- General use macros.
+--
+-- DESCRIPTION
+-- ANSI macro relies on the fact that it can be replaced by (), or by
+-- its value, where the value is one value due to the preprocessors
+-- handling of arguments that are surrounded by ()'s as a single
+-- argument.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef MACROS_h
+#define MACROS_h
+
+/* AIX and Mac MPW define __STDC__ as special, but defined(__STDC__) is false,
+ * and it has no value. */
+#ifndef __STDC__
+#define __STDC__ 0
+#endif
+
+#if __STDC__ || defined(__TURBOC__) || defined(__IBMC__)
+#define ANSI(x) x
+#else
+#define ANSI(x) ()
+#endif
+
+#define NIL(p) ((p*)NULL)
+
+#if !defined(atarist) && !defined(__STDDEF_H)
+#define offsetof(type,id) ((size_t)&((type*)NULL)->id)
+#endif
+
+#define FALSE 0
+#define TRUE 1
+
+#define PUBLIC
+
+#endif
+
diff --git a/dmake/struct.h b/dmake/struct.h
new file mode 100644
index 000000000000..01ac57f661ed
--- /dev/null
+++ b/dmake/struct.h
@@ -0,0 +1,256 @@
+/* RCS $Id: struct.h,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
+--
+-- SYNOPSIS
+-- Structure definitions
+--
+-- DESCRIPTION
+-- dmake main data structure definitions. See each of the individual
+-- struct declarations for more detailed information on the defined
+-- fields and their use.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _STRUCT_INCLUDED_
+#define _STRUCT_INCLUDED_
+
+typedef uint32 t_attr;
+
+/* The following struct is the cell used in the hash table.
+ * NOTE: It contains the actual hash value. This allows the hash table
+ * insertion to compare hash values and to do a string compare only
+ * for entries that have matching hash_key values. This elliminates
+ * 99.9999% of all extraneous string compare operations when searching
+ * a hash table chain for matching entries. */
+
+typedef struct hcell {
+ struct hcell *ht_next; /* next entry in the hash table */
+ struct hcell *ht_link; /* for temporary lists */
+ char *ht_name; /* name of this cell */
+ char *ht_value; /* cell value if any */
+ uint32 ht_hash; /* actual hash_key of cell */
+ int ht_flag; /* flags belonging to hash entry */
+
+ /* NOTE: some macros have corresponding variables defined
+ * that control program behaviour. For these macros a
+ * bit of ht_flag indicates the variable value will be set, and the
+ * type of the value that will be set.
+ *
+ * The struct below contains a mask for bit variables, and a
+ * pointer to the global STATIC location for that variable.
+ * String and char variables point to the same place as ht_value
+ * and must be updated when ht_value changes, bit variables must
+ * have their value recomputed. See Def_macro code for more
+ * details.
+ *
+ * NOTE: Macro variables and Targets are always distinct. Thus
+ * the value union contains pointers back at cells that own
+ * a particular name entry. A conflict in this can never
+ * arise, ie pointers at cells will never be used as
+ * values for a macro variable, since the cell and macro
+ * name spaces are completely distinct. */
+
+ struct {
+ int mv_mask; /* bit mask for bit variable */
+ union {
+ char** mv_svar;/* ptr to string valued glob var */
+ char* mv_cvar;/* ptr to char valued glob var */
+ t_attr* mv_bvar;/* ptr to bit valued glob var */
+ int* mv_ivar;/* ptr to int valued glob var */
+
+ struct {
+ struct tcell* ht_owner;/* ptr to CELL owning name */
+ struct tcell* ht_root; /* root ptr for explode */
+ } ht;
+ } val;
+ } var; /* variable's static equivalent */
+} HASH, *HASHPTR;
+
+#define MV_MASK var.mv_mask
+#define MV_SVAR var.val.mv_svar
+#define MV_CVAR var.val.mv_cvar
+#define MV_BVAR var.val.mv_bvar
+#define MV_IVAR var.val.mv_ivar
+#define CP_OWNR var.val.ht.ht_owner
+#define CP_ROOT var.val.ht.ht_root
+
+
+
+/* This struct holds the list of temporary files that have been created.
+ * It gets unlinked when Quit is called due to an execution error */
+typedef struct flst {
+ char *fl_name; /* file name */
+ FILE *fl_file; /* the open file */
+ struct flst *fl_next; /* pointer to next file */
+} FILELIST, *FILELISTPTR;
+
+
+/* The next struct is used to link together prerequisite lists */
+typedef struct lcell {
+ struct tcell *cl_prq; /* link to a prerequisite */
+ struct lcell *cl_next; /* next cell on dependency list */
+ int cl_flag; /* flags for link cell */
+} LINK, *LINKPTR;
+
+
+/* This is the structure of a target cell in the dag which represents the
+ * graph of dependencies. Each possible target is represented as a cell.
+ *
+ * Each cell contains a pointer to the hash table entry for this cell.
+ * The hash table entry records the name of the cell. */
+
+typedef struct tcell {
+ struct hcell *ce_name; /* name of this cell */
+ struct hcell *ce_pushed; /* local pushed macro definitions */
+
+ struct lcell ce_all; /* link for grouping UPDATEALL cells*/
+ struct tcell *ce_set; /* set rep. valid if ce_all != NULL */
+ struct tcell *ce_setdir; /* SETDIR ROOT pointer for this cell*/
+ struct tcell *ce_link; /* link for temporary list making */
+ struct tcell *ce_parent; /* used by inner loop, not a static */
+
+ struct lcell *ce_prq; /* list of prerequisites for cell */
+ struct lcell *ce_prqorg; /* list of original prerequisites */
+ struct lcell *ce_indprq; /* indirect prerequisites for % cell*/
+
+ struct str *ce_recipe; /* recipe for making this cell */
+ FILELISTPTR ce_files; /* list of temporary files for cell */
+ struct str *ce_cond; /* conditional macro assignments */
+
+ char *ce_per; /* value of % in %-meta expansion */
+ char *ce_fname; /* file name associated with target */
+ char *ce_lib; /* archive name, if A_LIBRARYM */
+ char *ce_dir; /* value for .SETDIR attribute */
+
+ int ce_count; /* value for :: recipe set */
+ int ce_index; /* value of count for next :: child */
+ int ce_flag; /* all kinds of goodies */
+ t_attr ce_attr; /* attributes for this target */
+ time_t ce_time; /* time stamp value of target if any*/
+} CELL, *CELLPTR;
+
+#define CE_NAME ce_name->ht_name
+#define CE_RECIPE ce_recipe
+#define CE_PRQ ce_prq
+#define CeMeToo(C) &((C)->ce_all)
+#define CeNotMe(C) (C)->ce_all.cl_next
+
+
+/* This struct represents that used by Get_token to return and control
+ * access to a token list inside a particular string. This gives the
+ * ability to access non overlapping tokens simultaneously from
+ * multiple strings. */
+
+typedef struct {
+ char *tk_str; /* the string to search for tokens */
+ char tk_cchar; /* current char under *str */
+ int tk_quote; /* if we are scanning a quoted str */
+} TKSTR, *TKSTRPTR;
+
+
+
+/* Below is the struct used to represent a string. It points at possibly
+ * another string, since the set of rules for making a target is a collection
+ * of strings. */
+
+
+typedef struct str {
+ char *st_string; /* the string value */
+ struct str *st_next; /* pointer to the next string */
+ t_attr st_attr; /* attr for rule operations */
+} STRING, *STRINGPTR;
+
+
+
+/* These structs are used in processing of the % rules, and in building
+ * the NFA machine that is used to match an arbitrary target string to
+ * one of the % rules that is represented by each DFA */
+
+typedef int16 statecnt; /* limits the max number of dfa states */
+
+
+/* Each state of the DFA contains four pieces of information. */
+typedef struct st {
+ struct st *no_match; /* state to go to if no match */
+ struct st *match; /* state to go to if we do match */
+ char symbol; /* symbol on which we transit */
+ char action; /* action to perform if match */
+} STATE, *STATEPTR;
+
+
+/* Each DFA machine looks like this. It must have two pointers that represent
+ * the value of % in the matched string, and it contains a pointer into the
+ * current state, as well as the array of all states. */
+typedef struct {
+ char *pstart; /* start of % string match */
+ char *pend; /* end of % string match */
+ STATEPTR c_state; /* current DFA state */
+ CELLPTR node; /* % target represented by this DFA */
+ STATEPTR states; /* table of states for the DFA */
+} DFA, *DFAPTR;
+
+
+/* An NFA is a collection of DFA's. For each DFA we must know it's current
+ * state and where the next NFA is. */
+typedef struct nfa_machine {
+ DFAPTR dfa; /* The DFA for this eps transition */
+ char status; /* DFA state */
+ struct nfa_machine *next; /* the next DFA in NFA */
+} NFA, *NFAPTR;
+
+
+
+/* The next struct is used to link together DFA nodes for inference. */
+
+typedef struct dfal {
+ struct tcell *dl_meta; /* link to %-meta cell */
+ struct dfal *dl_next; /* next cell on matched DFA list*/
+ struct dfal *dl_prev; /* prev cell on matched DFA list*/
+ struct dfal *dl_member; /* used during subset calc */
+ char dl_delete; /* used during subset calc */
+ char *dl_per; /* value of % for matched DFA */
+ statecnt dl_state; /* matched state of the DFA */
+ int dl_prep; /* repetion count for the cell */
+} DFALINK, *DFALINKPTR;
+
+
+/* This struct is used to store the stack of DFA sets during inference */
+typedef struct dfst {
+ DFALINKPTR df_set; /* pointer to the set */
+ struct dfst *df_next; /* next element in the stack */
+} DFASET, *DFASETPTR;
+
+
+/* We need sets of items during inference, here is the item, we form sets
+ * by linking them together. */
+
+typedef struct ic {
+ CELLPTR ic_meta; /* Edge we used to make this cell*/
+ DFALINKPTR ic_dfa; /* Dfa that we matched against */
+ CELLPTR ic_setdirroot; /* setdir root pointer for cell */
+ DFASET ic_dfastack; /* set of dfas we're working with*/
+ int ic_dmax; /* max depth of cycles in graph */
+ char *ic_name; /* name of the cell to insert */
+ char *ic_dir; /* dir to CD to prior to recurse */
+ struct ic *ic_next; /* next pointer to link */
+ struct ic *ic_link; /* link all ICELL'S together */
+ struct ic *ic_parent; /* pointer to post-requisite */
+ char ic_flag; /* flag, used for NOINFER only */
+ char ic_exists; /* TRUE if prerequisite exists */
+} ICELL, *ICELLPTR;
+
+#endif
diff --git a/dmake/sysintf.c b/dmake/sysintf.c
new file mode 100644
index 000000000000..15ddb5d96976
--- /dev/null
+++ b/dmake/sysintf.c
@@ -0,0 +1,753 @@
+/* RCS $Id: sysintf.c,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $
+--
+-- SYNOPSIS
+-- System independent interface
+--
+-- DESCRIPTION
+-- These are the routines constituting the system interface.
+-- The system is taken to be essentially POSIX conformant.
+-- The original code was extensively revised by T J Thompson at MKS,
+-- and the library cacheing was added by Eric Gisin at MKS. I then
+-- revised the code yet again, to improve the lib cacheing, and to
+-- make it more portable.
+--
+-- The following is a list of routines that are required by this file
+-- in order to work. These routines are provided as functions by the
+-- standard C lib of the target system or as #defines in system/sysintf.h
+-- or via appropriate C code in the system/ directory for the given
+-- system.
+--
+-- The first group must be provided by a file in the system/ directory
+-- the second group is ideally provided by the C lib. However, there
+-- are instances where the C lib implementation of the specified routine
+-- does not exist, or is incorrect. In these instances the routine
+-- must be provided by the the user in the system/ directory of dmake.
+-- (For example, the bsd/ dir contains code for putenv(), and tempnam())
+--
+-- DMAKE SPECIFIC:
+-- seek_arch()
+-- touch_arch()
+-- void_lcache()
+-- runargv()
+-- DMSTAT()
+-- Remove_prq()
+--
+-- C-LIB SPECIFIC: (should be present in your C-lib)
+-- utime()
+-- time()
+-- getenv()
+-- putenv()
+-- getcwd()
+-- signal()
+-- chdir()
+-- tempnam()
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+#include "sysintf.h"
+
+/*
+** Tries to stat the file name. Returns 0 if the file
+** does not exist. Note that if lib is not null it tries to stat
+** the name found inside lib.
+**
+** If member is NOT nil then look for the library object which defines the
+** symbol given by name. If found DmStrDup the name and return make the
+** pointer pointed at by sym point at it. Not handled for now!
+*/
+static time_t
+really_dostat(name, buf)
+char *name;
+struct stat *buf;
+{
+ return( ( DMSTAT(name,buf)==-1
+ || (STOBOOL(Augmake) && (buf->st_mode & S_IFDIR)))
+ ? (time_t)0L
+ : (time_t) buf->st_mtime
+ );
+}
+
+
+PUBLIC time_t
+Do_stat(name, lib, member, force)
+char *name;
+char *lib;
+char **member;
+int force;
+{
+ struct stat buf;
+ time_t seek_arch();
+
+ if( member != NIL(char *) )
+ Fatal("Library symbol names not supported");
+
+ buf.st_mtime = (time_t)0L;
+ if( lib != NIL(char) )
+ return( seek_arch(Basename(name), lib) );
+ else if( STOBOOL(UseDirCache) )
+ return(CacheStat(name,force));
+ else if( strlen(Basename(name)) > NameMax )
+ return((time_t)0L);
+ else
+ return(really_dostat(name,&buf));
+}
+
+
+/* Touch existing file to force modify time to present.
+ */
+PUBLIC int
+Do_touch(name, lib, member)
+char *name;
+char *lib;
+char **member;
+{
+ if( member != NIL(char *) )
+ Fatal("Library symbol names not supported");
+
+ if (lib != NIL(char))
+ return( touch_arch(Basename(name), lib) );
+ else if( strlen(Basename(name)) > NameMax )
+ return(-1);
+ else
+ return( utime(name, NIL(time_t)) );
+}
+
+
+
+PUBLIC void
+Void_lib_cache( lib_name, member_name )/*
+=========================================
+ Void the library cache for lib lib_name, and member member_name. */
+char *lib_name;
+char *member_name;
+{
+ VOID_LCACHE( lib_name, member_name );
+}
+
+
+
+/*
+** return the current time
+*/
+PUBLIC time_t
+Do_time()
+{
+ extern time_t time();
+ return (time((time_t*)0));
+}
+
+
+
+/*
+** Execute the string passed in as a command and return
+** the return code. The command line arguments are
+** assumed to be separated by spaces or tabs. The first
+** such argument is assumed to be the command.
+**
+** If group is true then this is a group of commands to be fed to the
+** the shell as a single unit. In this case cmd is of the form
+** "file" indicating the file that should be read by the shell
+** in order to execute the command group.
+*/
+PUBLIC int
+Do_cmnd(cmd, group, do_it, target, ignore, shell, last)
+char *cmd;
+int group;
+int do_it;
+CELLPTR target;
+int ignore;
+int shell;
+int last;
+{
+ int i;
+
+ if( !do_it ) {
+ if( last && !Doing_bang ) {
+ Update_time_stamp( target );
+ }
+ return(0);
+ }
+
+ if ( target->ce_attr & A_ERROR ) {
+ if ( last ) {
+ Update_time_stamp( target );
+ }
+ return(0);
+ }
+
+ if( Max_proc == 1 ) Wait_for_completion = TRUE;
+
+ if( (i = runargv(target, ignore, group, last, shell, cmd)) == -1 )
+ Quit();
+
+ /* NOTE: runargv must return either 0 or 1, 0 ==> command executed, and
+ * we waited for it to return, 1 ==> command started and is running
+ * concurrently with make process. */
+ return(i);
+}
+
+
+#define MINARGV 64
+/* Take a command and pack it into an argument vector to be executed. */
+PUBLIC char **
+Pack_argv( group, shell, cmd )
+int group;
+int shell;
+char *cmd;
+{
+ static char **av = NIL(char *);
+ static int avs = 0;
+ int i = 0;
+
+ if( av == NIL(char *) ) {
+ TALLOC(av, MINARGV, char*);
+ avs = MINARGV;
+ }
+ av[0] = NIL(char);
+
+ if (*cmd) {
+ Packed_shell = shell||group||(*DmStrPbrk(cmd, Shell_metas)!='\0');
+
+ if( Packed_shell ){
+ char* sh = group ? GShell : Shell;
+
+ if( sh != NIL(char) ) {
+ av[i++] = sh;
+ if( (av[i] = (group?GShell_flags:Shell_flags)) != NIL(char) ) i++;
+
+ av[i++] = cmd;
+ av[i] = NIL(char);
+ }
+ else
+ Fatal("%sSHELL macro not defined", group?"GROUP":"");
+ }
+ else {
+ do {
+ while( iswhite(*cmd) ) ++cmd;
+ if( *cmd ) av[i++] = cmd;
+
+ while( *cmd != '\0' && !iswhite(*cmd) ) ++cmd;
+ if( *cmd ) *cmd++ = '\0';
+
+ if( i == avs ) {
+ avs += MINARGV;
+ av = (char **) realloc( av, avs*sizeof(char *) );
+ }
+ } while( *cmd );
+
+ av[i] = NIL(char);
+ }
+ }
+
+ return(av);
+}
+
+
+/*
+** Return the value of ename from the environment
+** if ename is not defined in the environment then
+** NIL(char) should be returned
+*/
+PUBLIC char *
+Read_env_string(ename)
+char *ename;
+{
+#if !defined(_MSC_VER) || _MSC_VER < 600
+ extern char *getenv();
+#endif
+ return( getenv(ename) );
+}
+
+
+
+/*
+** Set the value of the environment string ename to value.
+** Returns 0 if success, non-zero if failure
+*/
+PUBLIC int
+Write_env_string(ename, value)
+char *ename;
+char *value;
+{
+ extern int putenv();
+ char* p;
+ char* envstr = DmStrAdd(ename, value, FALSE);
+
+ p = envstr+strlen(ename); /* Don't change this code, DmStrAdd does not */
+ *p++ = '='; /* add the space if *value is 0, it does */
+ if( !*value ) *p = '\0'; /* allocate enough memory for one though. */
+
+ return( putenv(envstr) );
+}
+
+
+
+PUBLIC void
+ReadEnvironment()
+{
+ extern char **Rule_tab;
+#if !defined(_MSC_VER)
+#if defined(__BORLANDC__) && __BORLANDC__ >= 0x500
+ extern char ** _RTLENTRY _EXPDATA environ;
+#else
+ extern char **environ;
+#endif
+#endif
+ char **rsave;
+
+#if !defined(__ZTC__) && !defined(_MPW)
+# define make_env()
+# define free_env()
+#else
+ void make_env();
+ void free_env();
+#endif
+
+ make_env();
+
+ rsave = Rule_tab;
+ Rule_tab = environ;
+ Readenv = TRUE;
+
+ Parse( NIL(FILE) );
+
+ Readenv = FALSE;
+ Rule_tab = rsave;
+
+ free_env();
+}
+
+
+
+/*
+** All we have to catch is SIG_INT
+*/
+PUBLIC void
+Catch_signals(fn)
+void (*fn)();
+{
+ if( (void (*)()) signal(SIGINT, SIG_IGN) != (void (*)())SIG_IGN )
+ signal( SIGINT, fn );
+ if( (void (*)()) signal(SIGQUIT, SIG_IGN) != (void (*)())SIG_IGN )
+ signal( SIGQUIT, fn );
+}
+
+
+
+/*
+** Clear any previously set signals
+*/
+PUBLIC void
+Clear_signals()
+{
+ if( (void (*)())signal(SIGINT, SIG_IGN) != (void (*)())SIG_IGN )
+ signal( SIGINT, SIG_DFL );
+ if( (void (*)())signal(SIGQUIT, SIG_IGN) != (void (*)())SIG_IGN )
+ signal( SIGQUIT, SIG_DFL );
+}
+
+
+
+/*
+** Set program name
+*/
+PUBLIC void
+Prolog(argc, argv)
+int argc;
+char* argv[];
+{
+ Pname = (argc == 0) ? DEF_MAKE_PNAME : argv[0];
+ Root = Def_cell( ".ROOT" );
+ Targets = Def_cell( ".TARGETS" );
+ Add_prerequisite(Root, Targets, FALSE, FALSE);
+
+ Targets->ce_flag = Root->ce_flag = F_RULES|F_TARGET|F_STAT;
+ Targets->ce_attr = Root->ce_attr = A_NOSTATE|A_PHONY;
+
+ Root->ce_flag |= F_MAGIC;
+ Root->ce_attr |= A_SEQ;
+
+ tzset();
+}
+
+
+
+/*
+** Do any clean up for exit.
+*/
+PUBLIC void
+Epilog(ret_code)
+int ret_code;
+{
+ Write_state();
+ Unlink_temp_files(Root);
+ Hook_std_writes(NIL(char)); /* For MSDOS tee (-F option) */
+ exit( ret_code );
+}
+
+
+
+/*
+** Use the built-in functions of the operating system to get the current
+** working directory.
+*/
+PUBLIC char *
+Get_current_dir()
+{
+ static char buf[PATH_MAX+2];
+ return(getcwd(buf, sizeof(buf)));
+}
+
+
+
+/*
+** change working directory
+*/
+PUBLIC int
+Set_dir(path)
+char* path;
+{
+ return( chdir(path) );
+}
+
+
+
+/*
+** return switch char
+*/
+PUBLIC char
+Get_switch_char()
+{
+ return( getswitchar() );
+}
+
+
+
+/*
+** Generate a temporary file name and open the file for writing.
+** If a name cannot be generated or the file cannot be opened
+** return -1, else return the fileno of the open file.
+** and update the source file pointer to point at the new file name.
+** Note that the new name should be freed when the file is removed.
+*/
+PUBLIC FILE*
+Get_temp(path, suff, op)
+char **path;
+char *suff;
+int op;
+{
+ extern char *tempnam();
+
+ *path = DmStrJoin( tempnam(NIL(char), "mk"), suff, -1, TRUE );
+ Def_macro( "TMPFILE", *path, M_MULTI|M_EXPANDED );
+
+ return( op?fopen(*path, "w"):NIL(FILE) );
+}
+
+
+/*
+** Open a new temporary file and set it up for writing.
+*/
+PUBLIC FILE *
+Start_temp( suffix, cp, fname )
+char *suffix;
+CELLPTR cp;
+char **fname;
+{
+ FILE *fp;
+ char *tmpname;
+ char *name;
+
+ name = (cp != NIL(CELL))?cp->CE_NAME:"makefile text";
+
+ if( (fp = Get_temp(&tmpname, suffix, TRUE)) == NIL(FILE) )
+ Open_temp_error( tmpname, name );
+
+ Link_temp( cp, fp, tmpname );
+ *fname = tmpname;
+
+ return( fp );
+}
+
+
+/*
+** Issue an error on failing to open a temporary file
+*/
+PUBLIC void
+Open_temp_error( tmpname, name )
+char *tmpname;
+char *name;
+{
+ Fatal("Cannot open temp file `%s' while processing `%s'", tmpname, name );
+}
+
+
+/*
+** Link a temp file onto the list of files.
+*/
+PUBLIC void
+Link_temp( cp, fp, fname )
+CELLPTR cp;
+FILE *fp;
+char *fname;
+{
+ FILELISTPTR new;
+
+ if( cp == NIL(CELL) ) cp = Root;
+
+ TALLOC( new, 1, FILELIST );
+
+ new->fl_next = cp->ce_files;
+ new->fl_name = fname;
+ new->fl_file = fp; /* indicates temp file is open */
+
+ cp->ce_files = new;
+}
+
+
+/*
+** Close a previously used temporary file.
+*/
+PUBLIC void
+Close_temp(cp, file)
+CELLPTR cp;
+FILE *file;
+{
+ FILELISTPTR fl;
+ if( cp == NIL(CELL) ) cp = Root;
+
+ for( fl=cp->ce_files; fl && fl->fl_file != file; fl=fl->fl_next );
+ if( fl ) {
+ fl->fl_file = NIL(FILE);
+ fclose(file);
+ }
+}
+
+
+/*
+** Clean-up, and close all temporary files associated with a target.
+*/
+PUBLIC void
+Unlink_temp_files( cp )/*
+==========================
+ Unlink the tempfiles if any exist. Make sure you close the files first
+ though. This ensures that under DOS there is no disk space lost. */
+CELLPTR cp;
+{
+ FILELISTPTR cur, next;
+
+ if( cp == NIL(CELL) || cp->ce_files == NIL(FILELIST) ) return;
+
+ for( cur=cp->ce_files; cur != NIL(FILELIST); cur=next ) {
+ next = cur->fl_next;
+
+ if( cur->fl_file ) fclose( cur->fl_file );
+
+ if( Verbose & V_LEAVE_TMP )
+ fprintf( stderr, "%s: Left temp file [%s]\n", Pname, cur->fl_name );
+ else
+ (void) Remove_file( cur->fl_name );
+
+ FREE(cur->fl_name);
+ FREE(cur);
+ }
+
+ cp->ce_files = NIL(FILELIST);
+}
+
+
+PUBLIC void
+Handle_result(status, ignore, abort_flg, target)
+int status;
+int ignore;
+int abort_flg;
+CELLPTR target;
+{
+ status = ((status&0xff)==0 ? status>>8
+ : (status & 0xff)==SIGTERM ? -1
+ : (status & 0x7f)+128);
+
+ if( status )
+ if( !abort_flg ) {
+ char buf[512];
+
+ sprintf(buf, "%s: Error code %d, while making '%s'",
+ Pname, status, target->ce_fname );
+
+ if( ignore || Continue ) {
+ if (!(Glob_attr & A_SILENT)) {
+ strcat(buf, " (Ignored" );
+
+ if ( Continue ) {
+ strcat(buf,",Continuing");
+ target->ce_attr |= A_ERROR;
+ }
+ strcat(buf,")");
+ if (Verbose)
+ fprintf(stderr, "%s\n", buf);
+ }
+
+ if( target->ce_attr & A_ERRREMOVE
+ && Remove_file( target->ce_fname ) == 0
+ && !(Glob_attr & A_SILENT))
+ fprintf(stderr,"%s: '%s' removed.\n", Pname, target->ce_fname);
+ }
+ else {
+ fprintf(stderr, "%s\n",buf);
+
+ if(!(target->ce_attr & A_PRECIOUS)||(target->ce_attr & A_ERRREMOVE))
+ if( Remove_file( target->ce_fname ) == 0 )
+ fprintf(stderr,"%s: '%s' removed.\n", Pname,
+ target->ce_fname);
+
+ Quit();
+ }
+ }
+ else if(!(target->ce_attr & A_PRECIOUS)||(target->ce_attr & A_ERRREMOVE))
+ Remove_file( target->ce_fname );
+}
+
+
+PUBLIC void
+Update_time_stamp( cp )
+CELLPTR cp;
+{
+ HASHPTR hp;
+ LINKPTR dp;
+ CELLPTR tcp;
+ time_t phonytime = (time_t)0L;
+ int phony = ((cp->ce_attr&A_PHONY) != 0);
+
+ /* Compute phony time as either the current time, or the most recent time
+ * from the list of prerequisites if there are any. */
+ if ( cp->ce_prq != NIL(LINK) ) {
+ for(dp=cp->ce_prq; dp; dp=dp->cl_next)
+ if ( dp->cl_prq->ce_time > phonytime )
+ phonytime = dp->cl_prq->ce_time;
+ }
+ else
+ phonytime = Do_time();
+
+ for(dp=CeMeToo(cp); dp; dp=dp->cl_next) {
+ tcp=dp->cl_prq;
+
+ if( tcp->ce_attr & A_LIBRARY )
+ Void_lib_cache( tcp->ce_fname, NIL(char) );
+ else if( !Touch && (tcp->ce_attr & A_LIBRARYM) )
+ Void_lib_cache( tcp->ce_lib, tcp->ce_fname );
+
+ if( phony ) {
+ tcp->ce_time = phonytime;
+ }
+ else if (Trace) {
+ tcp->ce_time = Do_time();
+ }
+ else {
+ Stat_target(tcp, -1, TRUE);
+
+ if( tcp->ce_time == (time_t) 0L )
+ tcp->ce_time = Do_time();
+ }
+
+ if( Trace ) {
+ tcp->ce_flag |= F_STAT; /* pretend we stated ok */
+ }
+
+ if( Verbose & V_MAKE )
+ printf( "%s: <<<< Set [%s] time stamp to %lu\n",
+ Pname, tcp->CE_NAME, tcp->ce_time );
+
+ Unlink_temp_files( tcp );
+ tcp->ce_flag |= F_MADE;
+ tcp->ce_attr |= A_UPDATED;
+ }
+
+ /* Scan the list of prerequisites and if we find one that is
+ * marked as being removable, (ie. an inferred intermediate node
+ * then remove it. We remove a prerequisite by running the recipe
+ * associated with the special target .REMOVE, with $< set to
+ * the list of prerequisites to remove. */
+
+ /* Make sure we don't try to remove prerequisites for the .REMOVE
+ * target. */
+ if( strcmp(cp->CE_NAME,".REMOVE") != 0 &&
+ (hp = Get_name(".REMOVE", Defs, FALSE)) != NIL(HASH) ) {
+ register LINKPTR dp;
+ int flag = FALSE;
+ int rem;
+ t_attr attr;
+
+ tcp = hp->CP_OWNR;
+
+ tcp->ce_flag |= F_TARGET;
+ Clear_prerequisites( tcp );
+
+ for(dp=cp->ce_prq; dp != NIL(LINK); dp=dp->cl_next) {
+ register CELLPTR prq = dp->cl_prq;
+
+ attr = Glob_attr | prq->ce_attr;
+ rem = (prq->ce_flag & F_REMOVE) &&
+ (prq->ce_flag & F_MADE ) &&
+ !(prq->ce_attr & A_PHONY) &&
+ !(attr & A_PRECIOUS);
+
+ if(rem) {
+ LINKPTR tdp;
+
+ for(tdp=CeMeToo(prq); tdp; tdp=tdp->cl_next) {
+ CELLPTR tmpcell=tdp->cl_prq;
+
+ (Add_prerequisite(tcp,tmpcell,FALSE,FALSE))->cl_flag|=F_TARGET;
+ tmpcell->ce_flag &= ~F_REMOVE;
+ }
+ flag = TRUE;
+ }
+ }
+
+ if( flag ) {
+ int sv_force = Force;
+
+ Force = FALSE;
+ Remove_prq( tcp );
+ Force = sv_force;
+
+ for(dp=tcp->ce_prq; dp != NIL(LINK); dp=dp->cl_next) {
+ register CELLPTR prq = dp->cl_prq;
+
+ prq->ce_flag &= ~(F_MADE|F_VISITED|F_STAT);
+ prq->ce_flag |= F_REMOVE;
+ prq->ce_time = (time_t)0L;
+ }
+ }
+ }
+}
+
+
+PUBLIC int
+Remove_file( name )
+char *name;
+{
+ struct stat buf;
+
+ if( stat(name, &buf) != 0 )
+ return 1;
+ if( (buf.st_mode & S_IFMT) == S_IFDIR )
+ return 1;
+ return(unlink(name));
+}
diff --git a/dmake/tos/config.mk b/dmake/tos/config.mk
new file mode 100644
index 000000000000..65076200175a
--- /dev/null
+++ b/dmake/tos/config.mk
@@ -0,0 +1,49 @@
+# This is an OS specific configuration file
+# It assumes that OBJDIR, TARGET and DEBUG are previously defined.
+# It defines CFLAGS, LDARGS, CPPFLAGS, STARTUPFILE, LDOBJS
+# PRINTER, PRINTFLAGS
+# It augments SRC, OBJDIR, TARGET, CFLAGS, LDLIBS
+#
+PRINTER = hw
+PRINTFLAGS = -P$(PRINTER)
+STARTUPFILE = $(OS)/startup.mk
+CPPFLAGS = $(CFLAGS)
+LDOBJS = $(CSTARTUP) $(OBJDIR)/{$(<:f)}
+LDARGS = $(LDFLAGS) -o $@ $(OBJDIR)/*$O
+LDFLAGS += -s
+LD = $(CC)
+
+# Debug flags
+DB_CFLAGS = -g -DDBUG
+DB_LDFLAGS = -g
+DB_LDLIBS =
+
+# NO Debug flags
+NDB_CFLAGS = -O
+NDB_LDFLAGS =
+NDB_LDLIBS =
+
+# Local configuration modifications for CFLAGS.
+CFLAGS += -I$(OS)
+
+# Sources that must be defined for each different version
+OS_SRC += ruletab.c
+DOS_SRC = rmprq.c runargv.c dirbrk.c rmprq.c
+UNIX_SRC = arlib.c
+BSD_SRC = putenv.c tempnam.c
+
+.SETDIR=$(OS) : $(OS_SRC)
+.SETDIR=msdos : $(DOS_SRC)
+.SETDIR=unix : $(UNIX_SRC)
+.SETDIR=unix/bsd43 : $(BSD_SRC)
+
+SRC += $(OS_SRC) $(DOS_SRC) $(UNIX_SRC) $(BSD_SRC)
+
+# Set source dirs so that we can find files named in this
+# config file.
+.SOURCE.h : $(OS)
+
+# See if we modify anything in the lower levels.
+.IF $(OSRELEASE) != $(NULL)
+ .INCLUDE .IGNORE : $(OS)$(DIRSEPSTR)$(OSRELEASE)$(DIRSEPSTR)config.mk
+.END
diff --git a/dmake/tos/make.sh b/dmake/tos/make.sh
new file mode 100644
index 000000000000..8ecb7db9c8e3
--- /dev/null
+++ b/dmake/tos/make.sh
@@ -0,0 +1,57 @@
+mkdir objects
+gcc -c -I. -Itos -O infer.c
+mv infer.o objects
+gcc -c -I. -Itos -O make.c
+mv make.o objects
+gcc -c -I. -Itos -O stat.c
+mv stat.o objects
+gcc -c -I. -Itos -O expand.c
+mv expand.o objects
+gcc -c -I. -Itos -O dmstring.c
+mv dmstring.o objects
+gcc -c -I. -Itos -O hash.c
+mv hash.o objects
+gcc -c -I. -Itos -O dag.c
+mv dag.o objects
+gcc -c -I. -Itos -O dmake.c
+mv dmake.o objects
+gcc -c -I. -Itos -O path.c
+mv path.o objects
+gcc -c -I. -Itos -O imacs.c
+mv imacs.o objects
+gcc -c -I. -Itos -O sysintf.c
+mv sysintf.o objects
+gcc -c -I. -Itos -O parse.c
+mv parse.o objects
+gcc -c -I. -Itos -O getinp.c
+mv getinp.o objects
+gcc -c -I. -Itos -O quit.c
+mv quit.o objects
+gcc -c -I. -Itos -O state.c
+mv state.o objects
+gcc -c -I. -Itos -O dmdump.c
+mv dmdump.o objects
+gcc -c -I. -Itos -O macparse.c
+mv macparse.o objects
+gcc -c -I. -Itos -O rulparse.c
+mv rulparse.o objects
+gcc -c -I. -Itos -O percent.c
+mv percent.o objects
+gcc -c -I. -Itos -O function.c
+mv function.o objects
+gcc -c -I. -Itos -O tos/ruletab.c
+mv ruletab.o objects
+gcc -c -I. -Itos -O msdos/rmprq.c
+mv rmprq.o objects
+gcc -c -I. -Itos -O msdos/runargv.c
+mv runargv.o objects
+gcc -c -I. -Itos -O msdos/dirbrk.c
+mv dirbrk.o objects
+gcc -c -I. -Itos -O unix/arlib.c
+mv arlib.o objects
+gcc -c -I. -Itos -O unix/bsd43/putenv.c
+mv putenv.o objects
+gcc -c -I. -Itos -O unix/bsd43/tempnam.c
+mv tempnam.o objects
+gcc -s -o dmake objects/*.o
+cp tos/template.mk startup/config.mk
diff --git a/dmake/tos/public.h b/dmake/tos/public.h
new file mode 100644
index 000000000000..8302f0b29d56
--- /dev/null
+++ b/dmake/tos/public.h
@@ -0,0 +1,163 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+void Clean_up_processes ANSI(());
+int Wait_for_child ANSI((int, int));
+int If_root_path ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+
+#endif
diff --git a/dmake/tos/putenv.c b/dmake/tos/putenv.c
new file mode 100644
index 000000000000..06e914d1fa0f
--- /dev/null
+++ b/dmake/tos/putenv.c
@@ -0,0 +1,78 @@
+/* RCS $Id: putenv.c,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- My own putenv for BSD like systems.
+--
+-- DESCRIPTION
+-- This originally came from MKS, but I rewrote it to fix a bug with
+-- replacing existing strings, probably never happened but the code
+-- was wrong nonetheless.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <stdio.h>
+#include <string.h>
+
+int
+putenv( str )/*
+===============
+ Take a string of the form NAME=value and stick it into the environment.
+ We do this by allocating a new set of pointers if we have to add a new
+ string and by replacing an existing pointer if the value replaces the value
+ of an existing string. */
+char *str;
+{
+ extern char **environ; /* The current environment. */
+ static char **ourenv = NULL; /* A new environment */
+ register char **p;
+ register char *q;
+ int size;
+
+ /* First search the current environment and see if we can replace a
+ * string. */
+ for( p=environ; *p; p++ ) {
+ register char *s = str;
+
+ for( q = *p; *q && *s && *s == *q; q++, s++ )
+ if( *s == '=' ) {
+ *p = str;
+ return(0); /* replaced it so go away */
+ }
+ }
+
+ /* Ok, can't replace a string so need to grow the environment. */
+ size = p - environ + 2; /* size of new environment */
+ /* size of old is size-1 */
+
+ /* It's the first time, so allocate a new environment since we don't know
+ * where the old one is comming from. */
+ if( ourenv == NULL ) {
+ if( (ourenv = (char **) malloc( sizeof(char *)*size )) == NULL )
+ return(1);
+
+ memcpy( (char *)ourenv, (char *)environ, (size-2)*sizeof(char *) );
+ }
+ else if( (ourenv = (char **)realloc( ourenv, size*sizeof(char *))) == NULL )
+ return(1);
+
+ ourenv[--size] = NULL;
+ ourenv[--size] = str;
+
+ environ = ourenv;
+ return(0);
+}
diff --git a/dmake/tos/ruletab.c b/dmake/tos/ruletab.c
new file mode 100644
index 000000000000..4e70c19621d4
--- /dev/null
+++ b/dmake/tos/ruletab.c
@@ -0,0 +1,42 @@
+/* RCS $Id: ruletab.c,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- Default initial configuration of dmake.
+--
+-- DESCRIPTION
+-- Define here the initial set of rules that are defined before
+-- dmake performs any processing.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* These are control macros for dmake that MUST be defined at some point
+ * if they are NOT dmake will not work! These are default definitions. They
+ * may be overridden inside the .STARTUP makefile, they are here
+ * strictly so that dmake can parse the STARTUP makefile */
+
+static char *_rules[] = {
+ "MAXPROCESSLIMIT := 1",
+ "MAXPROCESS := 1",
+ "MAXLINELENGTH := 8190",
+ ".IMPORT .IGNORE: ROOTDIR",
+ ".MAKEFILES : makefile.mk Makefile makefile",
+ ".SOURCE : .NULL",
+#include "startup.h"
+ 0 };
+
+char **Rule_tab = _rules; /* for sundry reasons in Get_environment() */
diff --git a/dmake/tos/startup.h b/dmake/tos/startup.h
new file mode 100644
index 000000000000..216f463ded56
--- /dev/null
+++ b/dmake/tos/startup.h
@@ -0,0 +1,27 @@
+/* RCS $Id: startup.h,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- Definition of MAKESTARTUP
+--
+-- DESCRIPTION
+-- Default MAKESTARTUP value defining where dmake locates the
+-- startup file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+"MAKESTARTUP := $(ROOTDIR)/etc/startup/startup.mk",
diff --git a/dmake/tos/sysintf.h b/dmake/tos/sysintf.h
new file mode 100644
index 000000000000..6ac5dce2c4b2
--- /dev/null
+++ b/dmake/tos/sysintf.h
@@ -0,0 +1,46 @@
+/* RCS $Id: sysintf.h,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- Interfaces for sysintf.c
+--
+-- DESCRIPTION
+-- Abstractions of functions in sysintf.c
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#define DMSTAT stat
+#define VOID_LCACHE(l,m) (void) void_lcache(l,m)
+#define Hook_std_writes(A)
+#define GETPID getpid()
+#define DMSTRLWR(A,B)
+
+/* for directory cache */
+#define CacheStat(A,B) really_dostat(A,&buf)
+
+/*
+** standard C items
+*/
+
+/*
+** DOS interface standard items
+*/
+#define getswitchar() '-'
+
+/*
+** make parameters
+*/
diff --git a/dmake/tos/template.mk b/dmake/tos/template.mk
new file mode 100644
index 000000000000..91ce656f14b0
--- /dev/null
+++ b/dmake/tos/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= tos
+ OSRELEASE *:=
+ OSENVIRONMENT *:=
diff --git a/dmake/tos/tempnam.c b/dmake/tos/tempnam.c
new file mode 100644
index 000000000000..8c0e3077d65a
--- /dev/null
+++ b/dmake/tos/tempnam.c
@@ -0,0 +1,104 @@
+/* RCS $Id: tempnam.c,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- tempnam
+--
+-- DESCRIPTION
+-- temp file name generation routines.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+
+/*LINTLIBRARY*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define max(A,B) (((A)<(B))?(B):(A))
+
+extern char *mktemp();
+extern int access();
+
+static char *cpdir();
+static char *seed="AAA";
+
+/* BSD stdio.h doesn't define P_tmpdir, so let's do it here */
+#ifndef P_tmpdir
+static char *P_tmpdir = "/tmp";
+#endif
+
+char *
+tempnam(dir, prefix)
+char *dir; /* use this directory please (if non-NULL) */
+char *prefix; /* use this (if non-NULL) as filename prefix */
+{
+ register char *p, *q, *tmpdir;
+ int tl=0, dl=0, pl;
+
+ pl = strlen(P_tmpdir);
+
+ if( (tmpdir = getenv("TMPDIR")) != NULL ) tl = strlen(tmpdir);
+ if( dir != NULL ) dl = strlen(dir);
+
+ if( (p = malloc((unsigned)(max(max(dl,tl),pl)+16))) == NULL )
+ return(NULL);
+
+ *p = '\0';
+
+ if( (tl == 0) || (access( cpdir(p, tmpdir), 3) != 0) )
+ if( (dl == 0) || (access( cpdir(p, dir), 3) != 0) )
+ if( access( cpdir(p, P_tmpdir), 3) != 0 )
+ if( access( cpdir(p, "/tmp"), 3) != 0 )
+ return(NULL);
+
+ (void) strcat(p, "/");
+ if(prefix)
+ {
+ *(p+strlen(p)+5) = '\0';
+ (void)strncat(p, prefix, 5);
+ }
+
+ (void)strcat(p, seed);
+ (void)strcat(p, "XXXXXX");
+
+ q = seed;
+ while(*q == 'Z') *q++ = 'A';
+ ++*q;
+
+ if(*mktemp(p) == '\0') return(NULL);
+ return(p);
+}
+
+
+
+static char *
+cpdir(buf, str)
+char *buf;
+char *str;
+{
+ char *p;
+
+ if(str != NULL)
+ {
+ (void) strcpy(buf, str);
+ p = buf - 1 + strlen(buf);
+ if(*p == '/') *p = '\0';
+ }
+
+ return(buf);
+}
diff --git a/dmake/unix/386ix/ar.h b/dmake/unix/386ix/ar.h
new file mode 100644
index 000000000000..4c38e8944e99
--- /dev/null
+++ b/dmake/unix/386ix/ar.h
@@ -0,0 +1,27 @@
+/* RCS $Id: ar.h,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- ar header
+--
+-- DESCRIPTION
+-- Make sure that PORTAR is defined.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#define PORTAR 1
+#include "/usr/include/ar.h"
diff --git a/dmake/unix/386ix/config.mk b/dmake/unix/386ix/config.mk
new file mode 100644
index 000000000000..4c1eac92b94d
--- /dev/null
+++ b/dmake/unix/386ix/config.mk
@@ -0,0 +1,27 @@
+# This is the 386IX UNIX configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+# The following are required sources
+OSDSRC :=
+.IF $(OSDSRC)
+ SRC += $(OSDSRC)
+ .SETDIR=$(osrdir) : $(OSDSRC)
+.END
+
+.SOURCE.h : $(osrdir)
+
+# Local configuration modifications for CFLAGS, there's local SysV includes
+# too.
+CFLAGS += -I$(osrdir)
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
diff --git a/dmake/unix/386ix/make.sh b/dmake/unix/386ix/make.sh
new file mode 100644
index 000000000000..68e0109bb576
--- /dev/null
+++ b/dmake/unix/386ix/make.sh
@@ -0,0 +1,60 @@
+mkdir objects
+cc -c -I. -Iunix -Iunix/386ix -O infer.c
+mv infer.o objects
+cc -c -I. -Iunix -Iunix/386ix -O make.c
+mv make.o objects
+cc -c -I. -Iunix -Iunix/386ix -O stat.c
+mv stat.o objects
+cc -c -I. -Iunix -Iunix/386ix -O expand.c
+mv expand.o objects
+cc -c -I. -Iunix -Iunix/386ix -O dmstring.c
+mv dmstring.o objects
+cc -c -I. -Iunix -Iunix/386ix -O hash.c
+mv hash.o objects
+cc -c -I. -Iunix -Iunix/386ix -O dag.c
+mv dag.o objects
+cc -c -I. -Iunix -Iunix/386ix -O dmake.c
+mv dmake.o objects
+cc -c -I. -Iunix -Iunix/386ix -O path.c
+mv path.o objects
+cc -c -I. -Iunix -Iunix/386ix -O imacs.c
+mv imacs.o objects
+cc -c -I. -Iunix -Iunix/386ix -O sysintf.c
+mv sysintf.o objects
+cc -c -I. -Iunix -Iunix/386ix -O parse.c
+mv parse.o objects
+cc -c -I. -Iunix -Iunix/386ix -O getinp.c
+mv getinp.o objects
+cc -c -I. -Iunix -Iunix/386ix -O quit.c
+mv quit.o objects
+cc -c -I. -Iunix -Iunix/386ix -O state.c
+mv state.o objects
+cc -c -I. -Iunix -Iunix/386ix -O dmdump.c
+mv dmdump.o objects
+cc -c -I. -Iunix -Iunix/386ix -O macparse.c
+mv macparse.o objects
+cc -c -I. -Iunix -Iunix/386ix -O rulparse.c
+mv rulparse.o objects
+cc -c -I. -Iunix -Iunix/386ix -O percent.c
+mv percent.o objects
+cc -c -I. -Iunix -Iunix/386ix -O function.c
+mv function.o objects
+cc -c -I. -Iunix -Iunix/386ix -O unix/arlib.c
+mv arlib.o objects
+cc -c -I. -Iunix -Iunix/386ix -O unix/dirbrk.c
+mv dirbrk.o objects
+cc -c -I. -Iunix -Iunix/386ix -O unix/rmprq.c
+mv rmprq.o objects
+cc -c -I. -Iunix -Iunix/386ix -O unix/ruletab.c
+mv ruletab.o objects
+cc -c -I. -Iunix -Iunix/386ix -O unix/runargv.c
+mv runargv.o objects
+cc -c -I. -Iunix -Iunix/386ix -O unix/dcache.c
+mv dcache.o objects
+cc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o objects/dcache.o
+cp unix/386ix/template.mk startup/config.mk
diff --git a/dmake/unix/386ix/public.h b/dmake/unix/386ix/public.h
new file mode 100644
index 000000000000..eced883f353d
--- /dev/null
+++ b/dmake/unix/386ix/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/386ix/stdlib.h b/dmake/unix/386ix/stdlib.h
new file mode 100644
index 000000000000..1ec47228432b
--- /dev/null
+++ b/dmake/unix/386ix/stdlib.h
@@ -0,0 +1,44 @@
+/* RCS $Id: stdlib.h,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- stdlib interface
+--
+-- DESCRIPTION
+-- Specially needed pieces of interface to the standard C lib.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _STDLIB_INCLUDED_
+#define _STDLIB_INCLUDED_
+
+extern /*GOTO*/ _exit();
+extern /*GOTO*/ exit();
+extern /*GOTO*/ abort();
+extern int system();
+extern char *getenv();
+extern char *calloc();
+extern char *malloc();
+extern char *realloc();
+extern free();
+extern int errno;
+
+#ifndef EIO
+# include <errno.h>
+#endif
+
+#endif /* _STDLIB_INCLUDED_ */
diff --git a/dmake/unix/386ix/template.mk b/dmake/unix/386ix/template.mk
new file mode 100644
index 000000000000..e59d37c7ca72
--- /dev/null
+++ b/dmake/unix/386ix/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= 386ix
+ OSENVIRONMENT *:=
diff --git a/dmake/unix/386ix/time.h b/dmake/unix/386ix/time.h
new file mode 100644
index 000000000000..aff117b02ade
--- /dev/null
+++ b/dmake/unix/386ix/time.h
@@ -0,0 +1,35 @@
+/* RCS $Id: time.h,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- time_t
+--
+-- DESCRIPTION
+-- Properly define time_t.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/*
+** Berkeley get this wrong!
+*/
+#ifndef TIME_h
+#define TIME_h
+
+typedef long time_t; /* this is the thing we use */
+
+#endif TIME_h
+
diff --git a/dmake/unix/arlib.c b/dmake/unix/arlib.c
new file mode 100644
index 000000000000..22a2168cfed1
--- /dev/null
+++ b/dmake/unix/arlib.c
@@ -0,0 +1,609 @@
+/* RCS $Id: arlib.c,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- Unix archive manipulation code.
+--
+-- DESCRIPTION
+-- Originally this code was provided by Eric Gisin of MKS. I took
+-- his code and completely rewrote it adding cacheing of lib members
+-- and other various optimizations. I kept the overal functional
+-- idea of the library routines as they are similar to those in GNU
+-- make and felt it advantageous to maintain a similar interface.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* Sun unix on 386i's has a broken ar.h that does not assume PORTAR format
+ * by default, so we fix it here. */
+#if defined(i386) || defined(__DGUX__)
+#define PORTAR 1
+#endif
+
+#if !defined (COHERENT) && !defined(__COHERENT__)
+#include <ar.h>
+#else
+#include <arcoff.h>
+#endif /* COHERENT, __COHERENT__ */
+#include "extern.h"
+#include "sysintf.h"
+
+/* By defining the defines below it is possible to configure the library
+ * code for library cacheing/non-cacheing, ASCII archive headers, and a full
+ * decode of the ar_hdr fields in the scan_ar function. */
+
+#ifndef ASCARCH
+#define ASCARCH 1 /* ASCII time stored in archive */
+#endif
+
+#ifndef LC
+#define LC 1 /* Turn on library cacheing */
+#endif
+
+#ifndef CHECKELF
+#define CHECKELF 1 /* Enable Elf long member names */
+#endif
+
+#ifndef DECODE_ALL_AR_FIELDS
+#define DECODE_ALL_AR_FIELDS 0 /* decode only fields make needs*/
+#endif
+
+#ifndef AR_TRUNCATE_MEMBER_NAMES
+#define AR_TRUNCATE_MEMBER_NAMES 0 /* truncate member names for */
+#endif /* comparison. */
+
+#if LC
+# define FOUND_MEMBER FALSE
+#else
+# define FOUND_MEMBER TRUE
+# define _cache_member(a, b, c)
+# define _check_cache(a, b, c, d) FALSE
+#endif
+
+#define MAXFNAME 255 /* Max length of member name */
+#define MAXMNAME 8 /* Max module name < MAXFNAME */
+
+
+/* This struct is used to pass the library and member inrmation about the
+ * routines that perform the library seeking/cacheing */
+struct ar_args {
+ char *lib;
+ char *member;
+ time_t time;
+};
+
+
+typedef struct AR {
+ char ar_name[MAXFNAME+1]; /* File name */
+ long ar_size; /* Size in bytes */
+ time_t ar_time; /* Modification time */
+
+#ifdef DOS
+ char ar_modname[MAXMNAME+1]; /* DOS module name */
+#endif
+
+#if DECODE_ALL_AR_FIELDS
+ uint16 ar_mode; /* File mode */
+ uint16 ar_uid; /* File owner */
+ uint16 ar_gid; /* File group owner */
+#endif
+} AR, *ARPTR;
+
+
+static int ar_scan ANSI((FILE *,
+ int (*) ANSI((FILE *, struct AR *,struct ar_args *)),
+ struct ar_args *));
+static int ar_touch ANSI(( FILE *, time_t ));
+static int time_function ANSI(( FILE *, struct AR *, struct ar_args * ));
+static int touch_function ANSI(( FILE *, struct AR *, struct ar_args * ));
+static int ar_name_equal ANSI((char *, char *));
+
+#if LC
+static int _cache_member ANSI((char *, char *, time_t));
+static int _check_cache ANSI((char *, char *, time_t *, int));
+#endif
+
+/* decoded archive header */
+static AR _ar;
+static off_t arhdroffset; /* member seek offset */
+
+
+PUBLIC time_t
+seek_arch(name, lib)/*
+======================
+ Look for module 'name' inside 'lib'. If compiled with cacheing then first
+ check to see if the specified lib is cached. If so then return that time
+ stamp instead of looking into the library. */
+char *name;
+char *lib;
+{
+ FILE *f;
+ int rv;
+ time_t mtime;
+ struct ar_args args;
+
+ /* Check the cache first (if there is a cache) */
+ if( _check_cache(name, lib, &mtime, FALSE) ) return( mtime );
+
+ /* Open the lib file and perform the scan of the members, looking
+ * for our particular member. If cacheing is enabled it will be
+ * taken care of automatically during the scan. */
+
+ args.lib = lib;
+ args.member = name;
+ args.time = (time_t)0L;
+
+ if( (f = fopen(lib, "r")) == NIL(FILE) ) return( (time_t)0L );
+ rv = ar_scan(f, time_function, &args );
+ fclose( f );
+
+ if( rv < 0 ) Fatal("(%s): Invalid library format", lib);
+
+ return( args.time );
+}
+
+
+int
+touch_arch(name, lib)/*
+=======================
+ Look for module 'name' inside 'lib'. If compiled with cacheing then first
+ check to see if the specified lib is cached. If so then set that time
+ stamp and write it into the library. Returns 0 on success, non-zero
+ on failure. */
+char *name;
+char *lib;
+{
+ FILE *f;
+ int rv;
+ struct ar_args args;
+
+ /* Open the lib file and perform the scan of the members, looking
+ * for our particular member. If cacheing is enabled it will be
+ * taken care of automatically during the scan. */
+
+ args.lib = lib;
+ args.member = name;
+ args.time = (time_t)0L;
+
+ if( (f = fopen(lib, "r+")) == NIL(FILE) ) return( (time_t)1L );
+ rv = ar_scan(f, touch_function, &args );
+ fclose( f );
+
+ if( rv < 0 ) Fatal("(%s): Invalid library format", lib);
+
+ return( 0 );
+}
+
+
+
+static int
+time_function(f, arp, argp)/*
+=============================
+ get library member's time, if it matches than return it in argp, if
+ cacheing is enabled than cache the library members also. */
+FILE *f; /* library file */
+struct AR *arp; /* library member header */
+struct ar_args *argp;
+{
+ int rv = _cache_member( arp->ar_name, argp->lib, arp->ar_time );
+
+ if( ar_name_equal (argp->member, arp->ar_name)) {
+ argp->time = arp->ar_time;
+
+ if( arp->ar_time == 0 && !(Glob_attr & A_SILENT) )
+ Warning( "(%s): Can't extract library member timestamp; using EPOCH",
+ argp->member);
+
+ return( rv ); /* 1 => no cacheing, 0 => cacheing */
+ }
+
+ return( FALSE ); /* continue scan */
+}
+
+
+
+static int
+touch_function(f, arp, argp)/*
+==============================
+ Update library member's time stamp, and write new time value into cache
+ if required. */
+FILE *f; /* library file */
+struct AR *arp; /* library member header */
+struct ar_args *argp;
+{
+ extern time_t time ANSI(( time_t * ));
+ time_t now = time((time_t*) NULL); /* Current time. */
+
+ if( ar_name_equal(argp->member, arp->ar_name) ) {
+ _check_cache( argp->member, argp->lib, &now, TRUE );
+ ar_touch(f, now );
+
+ return( TRUE );
+ }
+
+ return( FALSE ); /* continue scan */
+}
+
+
+static int
+ar_name_equal (char * name1, char * name2)
+{
+ int equal;
+
+#if AR_TRUNCATE_MEMBER_NAMES
+ struct ar_hdr hdr;
+
+ equal = !strncmp (name1, name2, sizeof (hdr.ar_name)-1);
+#else
+ equal = !strcmp (name1, name2);
+#endif
+
+ return equal;
+}
+
+
+static int
+ar_scan(f, function, arg)/*
+===========================
+ Scan the opened archive, and call the given function for each member found.
+ The function will be called with the file positioned at the beginning of
+ the member and it can read up to arp->ar_size bytes of the archive member.
+ If the function returns 1, we stop and return 1. We return 0 at the end
+ of the archive, or -1 if the archive has invalid format. This interface
+ is more general than required by "make", but it can be used by other
+ utilities. */
+register FILE *f;
+int (*function) ANSI((FILE *, struct AR *, struct ar_args *));
+struct ar_args *arg;
+{
+ extern long atol ();
+ register char *p;
+ struct ar_hdr arhdr; /* archive member header */
+ long nsize; /* size of member name */
+ long arind=0; /* archive index offset */
+ int process;
+#if defined(_AIX)
+ struct fl_hdr flhdr; /* archive file header */
+ char magic[SAIAMAG]; /* size of magic string */
+#else
+#if ASCARCH
+ char magic[SARMAG];
+#else
+ unsigned short word;
+#endif
+#endif
+
+ fseek( f, 0L, 0 ); /* Start at the beginning of the archive file */
+
+#if ASCARCH
+#if defined(_AIX)
+ fread( (char *)&flhdr, sizeof(flhdr), 1, f );
+ if( strncmp(flhdr.fl_magic,AIAMAG, SAIAMAG) != 0 ) return(-1);
+ fseek(f, atol(flhdr.fl_fstmoff), 0 ); /* postition to first member */
+#else
+ fread( magic, sizeof(magic), 1, f );
+ if( strncmp(magic, ARMAG, SARMAG) != 0 ) return( -1 );
+#endif
+#else
+ fread( (char*)&word, sizeof(word), 1, f );
+ if( word != ARMAG ) return( -1 );
+#endif
+
+ /* scan the library, calling `function' for each member
+ */
+ while( 1 ) {
+ arhdroffset = ftell(f);
+#if defined(_AIX)
+ if( fread((char*)&arhdr,sizeof(arhdr)-sizeof(arhdr._ar_name),1,f)!=1)
+ break;
+ nsize = atoi(arhdr.ar_namlen);
+ fseek(f, arhdroffset+(unsigned long)(((struct ar_hdr *)0)->_ar_name.ar_name), 0);
+ if( fread((char*)_ar.ar_name,nsize,1,f)!=1)
+ break;
+ _ar.ar_name[nsize]='\0';
+#else
+ if( fread((char*) &arhdr, sizeof(arhdr), 1, f) != 1 ) break;
+ strncpy(_ar.ar_name, arhdr.ar_name, nsize = sizeof(arhdr.ar_name));
+#endif
+
+ for( p = &_ar.ar_name[nsize];
+ --p >= _ar.ar_name && *p == ' ';);
+
+ p[1] = '\0';
+ if( *p == '/' ) *p = 0; /* SysV has trailing '/' */
+
+ /* check to see if this is an archive index using SsysV Index scheme.
+ * see ar(4) man page for more info */
+#if CHECKELF
+ if( _ar.ar_name[0] == '/' && _ar.ar_name[1] == '\0' ) {
+ arind = arhdroffset+sizeof(arhdr);
+ process = 0;
+ }
+ else
+#endif
+ process = 1;
+
+#if !defined(_AIX)
+#if ASCARCH
+ if( strncmp(arhdr.ar_fmag, ARFMAG, sizeof(arhdr.ar_fmag)) != 0 )
+ return( -1 );
+ _ar.ar_time = atol(arhdr.ar_date);
+ _ar.ar_size = atol(arhdr.ar_size);
+#else
+ _ar.ar_time = arhdr.ar_date;
+ _ar.ar_size = arhdr.ar_size;
+#endif
+#if CHECKELF
+ /* check for names of the form /xxxx where xxxx is an offset into the
+ * name table pointed at by arind. */
+ if(arind && _ar.ar_name[0] == '/') {
+ long offset = atol(_ar.ar_name+1);
+ long here = ftell(f);
+ int c;
+
+ fseek(f, arind+offset, 0);
+ p = _ar.ar_name;
+ while((c=fgetc(f)) != EOF) {
+ *p++ = c;
+ if(c == '/') {
+ p[-1] = '\0';
+ break;
+ }
+ }
+
+ if (c==EOF) return(-1); /* 'c' should never be EOF */
+ fseek(f, here, 0);
+ }
+#endif
+#else
+#if ASCARCH
+ _ar.ar_time = atol(arhdr.ar_date);
+ _ar.ar_size = atol(arhdr.ar_nxtmem);
+#else
+ _ar.ar_time = arhdr.ar_date;
+ _ar.ar_size = arhdr.ar_nxtmem;
+#endif
+#endif
+
+
+#if DECODE_ALL_AR_FIELDS
+#if ASCARCH
+ _ar.ar_mode = atoi(arhdr.ar_mode);
+ _ar.ar_uid = atoi(arhdr.ar_uid);
+ _ar.ar_gid = atoi(arhdr.ar_gid);
+#else
+ _ar.ar_mode = arhdr.ar_mode;
+ _ar.ar_uid = arhdr.ar_uid;
+ _ar.ar_gid = arhdr.ar_gid;
+#endif
+#endif
+ if( process && (*function)(f, &_ar, arg) ) return( 1 );
+
+#if defined(_AIX)
+ if( _ar.ar_size == 0L ) break;
+ fseek( f, (long) _ar.ar_size, 0 );
+#else
+ fseek( f, arhdroffset + sizeof(arhdr) + (_ar.ar_size+1 & ~1L), 0 );
+#endif
+ }
+
+#if !defined(_AIX)
+ if( !feof(f) ) return( -1 );
+#endif
+ return 0;
+}
+
+
+
+static int
+ar_touch( f, now )/*
+====================
+ touch module header timestamp. */
+FILE *f;
+time_t now;
+{
+ struct ar_hdr arhdr; /* external archive header */
+
+ fseek(f, arhdroffset + (unsigned long)(((struct ar_hdr *)0)->ar_date), 0);
+
+#if ASCARCH
+ fprintf(f, "%lu", now);
+#else
+ fwrite((char *)now, sizeof(now), 1, f);
+#endif
+
+ return( ferror(f) ? 0 : 1 );
+}
+
+
+#if LC
+typedef struct mem {
+ time_t m_time; /* modify time of member*/
+ struct mem *m_next; /* next member in lib */
+ char m_valid; /* valid cache entry */
+ char m_name[1]; /* lib member name */
+} MEM, *MEMPTR;
+
+typedef struct lib {
+ struct lib *lb_next; /* next library in list */
+ struct mem *lb_members; /* list of lib members */
+ char lb_valid; /* valid cache entry */
+ char *lb_name; /* library name */
+} LIB, *LIBPTR;
+
+static LIBPTR _cache = NIL(LIB);
+static MEMPTR _find_member ANSI(( LIBPTR, char * ));
+
+static int
+_check_cache( name, lib, pmtime, touch )/*
+==========================================
+ Check to see if we have cached member in lib, if so return time in pmtime
+ and return TRUE, otherwise return FALSE, if touch is TRUE then touch
+ the archive member instead. */
+char *name;
+char *lib;
+time_t *pmtime;
+int touch;
+{
+ register MEMPTR mp;
+ register LIBPTR lp;
+
+ for( lp=_cache; lp != NIL(LIB) && lp->lb_name != lib; lp=lp->lb_next );
+ if( lp == NIL(LIB) ) return( FALSE );
+
+ mp = _find_member( lp, name );
+ if( mp == NIL(MEM) || !mp->m_valid ) return( FALSE );
+
+ if( touch == TRUE )
+ {
+ mp->m_time = *pmtime;
+ mp->m_valid = 1;
+ }
+ else
+ *pmtime = mp->m_time;
+
+ lp->lb_valid = 1;
+ lp->lb_members = mp;
+
+ return( TRUE );
+}
+
+
+
+static int
+_cache_member( name, lib, mtime )/*
+===================================
+ Cache name in lib along with it's time */
+char *name;
+char *lib;
+time_t mtime;
+{
+ register MEMPTR mp;
+ register LIBPTR lp;
+
+ for( lp=_cache;
+ lp != NIL(LIB) && lp->lb_name != NIL(char) && lp->lb_name != lib;
+ lp=lp->lb_next);
+
+ if( lp == NIL(LIB) )
+ {
+ lp = (LIBPTR) malloc(sizeof(LIB));
+ if( lp == NIL(LIB) ) No_ram();
+
+ lp->lb_name = lib;
+ lp->lb_members = NIL(MEM);
+ lp->lb_next = _cache;
+ lp->lb_valid = 0;
+ _cache = lp;
+ }
+
+ /* On UNIX ar does not allow multiple copies of the same .o file to live
+ * in the same AR file. If this is not TRUE then use the commented out
+ * version to set the value of mp. */
+
+ /*mp = _find_member(lp, name);*/
+ mp = NIL(MEM);
+
+ if( mp == NIL(MEM) )
+ {
+ mp = (MEMPTR) malloc(sizeof(char)*offsetof(MEM,m_name[strlen(name)+1]));
+ if( mp == NIL(MEM) ) No_ram();
+
+ strcpy( mp->m_name, name );
+ mp->m_time = mtime;
+
+ if( lp->lb_members == NIL(MEM) ) {
+ mp->m_next = mp;
+ lp->lb_members = mp;
+ }
+ else {
+ mp->m_next = lp->lb_members->m_next;
+ lp->lb_members->m_next = mp;
+ lp->lb_members = mp;
+ }
+ }
+ else
+ mp->m_time = mtime;
+
+ mp->m_valid = 1;
+
+ return( lp->lb_valid );
+}
+
+
+static MEMPTR
+_find_member( lp, name )
+LIBPTR lp;
+char *name;
+{
+ register MEMPTR mp = lp->lb_members;
+
+ if( mp == NIL(MEM) ) return(mp);
+
+ do {
+ if( !strcmp(mp->m_name, name ) ) return( mp );
+ mp = mp->m_next;
+ }
+ while( mp != lp->lb_members );
+
+ return( NIL(MEM) );
+}
+#endif
+
+
+
+void
+void_lcache( lib, member )/*
+============================
+ Void the library cache for lib. If member is NIL(char) then nuke all
+ of the members, if member is NOT NIL(char) then invalidate only that
+ member. */
+char *lib;
+char *member;
+{
+#if LC
+ register LIBPTR lp;
+ register MEMPTR mp;
+ register MEMPTR tmp;
+
+ for( lp=_cache; lp != NIL(LIB) && lp->lb_name != lib; lp=lp->lb_next );
+ if( lp == NIL(LIB) ) return;
+
+ if( member == NIL(char) ) {
+ mp = lp->lb_members;
+ do {
+ tmp = mp->m_next;
+ (void) free( mp );
+ mp = tmp;
+ } while( mp != lp->lb_members );
+
+ lp->lb_valid = 0;
+ lp->lb_members = NIL(MEM);
+ lp->lb_name = NIL(char);
+ }
+ else {
+ mp=lp->lb_members;
+ do {
+ if( strcmp( member, mp->m_name) == 0 ) {
+ lp->lb_members = mp->m_next;
+ mp->m_valid = 0;
+ }
+
+ mp=mp->m_next;
+ } while( mp != lp->lb_members );
+ }
+#endif
+}
diff --git a/dmake/unix/bsd43/config.mk b/dmake/unix/bsd43/config.mk
new file mode 100644
index 000000000000..e99937342e68
--- /dev/null
+++ b/dmake/unix/bsd43/config.mk
@@ -0,0 +1,27 @@
+# This is the BSD 4.3 UNIX configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+# The following sources are required for BSD4.3
+OSDSRC := putenv.c tempnam.c utime.c setvbuf.c
+.IF $(OSDSRC)
+ SRC += $(OSDSRC)
+ .SETDIR=$(osrdir) : $(OSDSRC)
+.END
+
+.SOURCE.h : $(osrdir)
+
+# Local configuration modifications for CFLAGS, there's local BSD includes
+# too.
+CFLAGS += -I$(osrdir)
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
diff --git a/dmake/unix/bsd43/dirent.h b/dmake/unix/bsd43/dirent.h
new file mode 100644
index 000000000000..82f910ed3a7d
--- /dev/null
+++ b/dmake/unix/bsd43/dirent.h
@@ -0,0 +1,28 @@
+/* RCS $Id: dirent.h,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- dirent
+--
+-- DESCRIPTION
+-- Deal with sysV'ish dirent.h on BSD4.3 systems, which have the stuff
+-- in sys/dir.h
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <sys/dir.h>
+#define dirent direct
diff --git a/dmake/unix/bsd43/limits.h b/dmake/unix/bsd43/limits.h
new file mode 100644
index 000000000000..a08805d00d66
--- /dev/null
+++ b/dmake/unix/bsd43/limits.h
@@ -0,0 +1,32 @@
+/* RCS $Id: limits.h,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- limits
+--
+-- DESCRIPTION
+-- Compensate for systems that don't have a limits.h header file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <sys/types.h>
+#include <sys/dirent.h>
+#include <sys/param.h>
+
+#define NAME_MAX MAXNAMLEN
+#define PATH_MAX MAXPATHLEN
+#define CHILD_MAX 20
diff --git a/dmake/unix/bsd43/make.sh b/dmake/unix/bsd43/make.sh
new file mode 100644
index 000000000000..e45d01952f46
--- /dev/null
+++ b/dmake/unix/bsd43/make.sh
@@ -0,0 +1,69 @@
+mkdir objects
+cc -c -I. -Iunix -Iunix/bsd43 -O infer.c
+mv infer.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O make.c
+mv make.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O stat.c
+mv stat.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O expand.c
+mv expand.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O dmstring.c
+mv dmstring.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O hash.c
+mv hash.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O dag.c
+mv dag.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O dmake.c
+mv dmake.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O path.c
+mv path.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O imacs.c
+mv imacs.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O sysintf.c
+mv sysintf.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O parse.c
+mv parse.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O getinp.c
+mv getinp.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O quit.c
+mv quit.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O state.c
+mv state.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O dmdump.c
+mv dmdump.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O macparse.c
+mv macparse.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O rulparse.c
+mv rulparse.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O percent.c
+mv percent.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O function.c
+mv function.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O unix/arlib.c
+mv arlib.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O unix/dirbrk.c
+mv dirbrk.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O unix/rmprq.c
+mv rmprq.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O unix/ruletab.c
+mv ruletab.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O unix/runargv.c
+mv runargv.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O unix/dcache.c
+mv dcache.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O unix/bsd43/putenv.c
+mv putenv.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O unix/bsd43/tempnam.c
+mv tempnam.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O unix/bsd43/utime.c
+mv utime.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -O unix/bsd43/setvbuf.c
+mv setvbuf.o objects
+cc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o \
+objects/dcache.o objects/putenv.o objects/tempnam.o objects/utime.o objects/setvbuf.o
+cp unix/bsd43/template.mk startup/config.mk
diff --git a/dmake/unix/bsd43/public.h b/dmake/unix/bsd43/public.h
new file mode 100644
index 000000000000..eced883f353d
--- /dev/null
+++ b/dmake/unix/bsd43/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/bsd43/putenv.c b/dmake/unix/bsd43/putenv.c
new file mode 100644
index 000000000000..d0ed998158e0
--- /dev/null
+++ b/dmake/unix/bsd43/putenv.c
@@ -0,0 +1,78 @@
+/* RCS $Id: putenv.c,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- My own putenv for BSD like systems.
+--
+-- DESCRIPTION
+-- This originally came from MKS, but I rewrote it to fix a bug with
+-- replacing existing strings, probably never happened but the code
+-- was wrong nonetheless.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <stdio.h>
+#include <string.h>
+
+int
+putenv( str )/*
+===============
+ Take a string of the form NAME=value and stick it into the environment.
+ We do this by allocating a new set of pointers if we have to add a new
+ string and by replacing an existing pointer if the value replaces the value
+ of an existing string. */
+char *str;
+{
+ extern char **environ; /* The current environment. */
+ static char **ourenv = NULL; /* A new environment */
+ register char **p;
+ register char *q;
+ int size;
+
+ /* First search the current environment and see if we can replace a
+ * string. */
+ for( p=environ; *p; p++ ) {
+ register char *s = str;
+
+ for( q = *p; *q && *s && *s == *q; q++, s++ )
+ if( *s == '=' ) {
+ *p = str;
+ return(0); /* replaced it so go away */
+ }
+ }
+
+ /* Ok, can't replace a string so need to grow the environment. */
+ size = p - environ + 2; /* size of new environment */
+ /* size of old is size-1 */
+
+ /* It's the first time, so allocate a new environment since we don't know
+ * where the old one is comming from. */
+ if( ourenv == NULL ) {
+ if( (ourenv = (char **) malloc( sizeof(char *)*size )) == NULL )
+ return(1);
+
+ memcpy( (char *)ourenv, (char *)environ, (size-2)*sizeof(char *) );
+ }
+ else if( (ourenv = (char **)realloc( ourenv, size*sizeof(char *))) == NULL )
+ return(1);
+
+ ourenv[--size] = NULL;
+ ourenv[--size] = str;
+
+ environ = ourenv;
+ return(0);
+}
diff --git a/dmake/unix/bsd43/setvbuf.c b/dmake/unix/bsd43/setvbuf.c
new file mode 100644
index 000000000000..ce5d193fbe89
--- /dev/null
+++ b/dmake/unix/bsd43/setvbuf.c
@@ -0,0 +1,40 @@
+/* RCS $Id: setvbuf.c,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- Setvbuf for BSD
+--
+-- DESCRIPTION
+-- A sysv call, standard BSD doesn't have this.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <stdio.h>
+
+setvbuf(fp, bp, type, len_unused)
+FILE* fp;
+char* bp;
+int type;
+int len_unused;
+{
+ switch (type) {
+ case _IOLBF: setlinebuf(fp); return;
+ case _IONBF: setbuf(fp, NULL); return;
+ default: setbuf(fp, bp); return;
+ }
+}
+
diff --git a/dmake/unix/bsd43/stdlib.h b/dmake/unix/bsd43/stdlib.h
new file mode 100644
index 000000000000..82ab9627cd65
--- /dev/null
+++ b/dmake/unix/bsd43/stdlib.h
@@ -0,0 +1,44 @@
+/* RCS $Id: stdlib.h,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- stdlib interface
+--
+-- DESCRIPTION
+-- Specially needed pieces of interface to the standard C lib.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _STDLIB_INCLUDED_
+#define _STDLIB_INCLUDED_
+
+extern /*GOTO*/ _exit();
+extern /*GOTO*/ exit();
+extern /*GOTO*/ abort();
+extern int system();
+extern char *getenv();
+extern char *calloc();
+extern char *malloc();
+extern char *realloc();
+extern free();
+extern int errno;
+
+#ifndef EIO
+# include <errno.h>
+#endif
+
+#endif /* _STDLIB_INCLUDED_ */
diff --git a/dmake/unix/bsd43/string.h b/dmake/unix/bsd43/string.h
new file mode 100644
index 000000000000..862c17960a0b
--- /dev/null
+++ b/dmake/unix/bsd43/string.h
@@ -0,0 +1,43 @@
+/* RCS $Id: string.h,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- string function headers
+--
+-- DESCRIPTION
+-- Supply correct definitions for certain string functions.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+#ifndef STRING_h
+#define STRING_h
+
+/*
+** BSD does this wrong
+*/
+#include <strings.h>
+
+#include "stdmacs.h"
+extern char* strpbrk ANSI((char* src, char* any));
+
+#ifndef DBUG
+#define strchr(str,c) index(str,c)
+#define strrchr(str,c) rindex(str,c)
+#else
+char *strchr ANSI((char*, char));
+char *strrchr ANSI((char*, char));
+#endif
+#endif
diff --git a/dmake/unix/bsd43/template.mk b/dmake/unix/bsd43/template.mk
new file mode 100644
index 000000000000..14a7cab8ed4b
--- /dev/null
+++ b/dmake/unix/bsd43/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= bsd43
+ OSENVIRONMENT *:=
diff --git a/dmake/unix/bsd43/tempnam.c b/dmake/unix/bsd43/tempnam.c
new file mode 100644
index 000000000000..12512ec9cb8b
--- /dev/null
+++ b/dmake/unix/bsd43/tempnam.c
@@ -0,0 +1,103 @@
+/* RCS $Id: tempnam.c,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- tempnam
+--
+-- DESCRIPTION
+-- temp file name generation routines.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/*LINTLIBRARY*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define max(A,B) (((A)<(B))?(B):(A))
+
+extern char *mktemp();
+extern int access();
+
+static char *cpdir();
+static char seed[4]="AAA";
+
+/* BSD stdio.h doesn't define P_tmpdir, so let's do it here */
+#ifndef P_tmpdir
+static char *P_tmpdir = "/tmp";
+#endif
+
+char *
+tempnam(dir, prefix)
+char *dir; /* use this directory please (if non-NULL) */
+char *prefix; /* use this (if non-NULL) as filename prefix */
+{
+ register char *p, *q, *tmpdir;
+ int tl=0, dl=0, pl;
+
+ pl = strlen(P_tmpdir);
+
+ if( (tmpdir = getenv("TMPDIR")) != NULL ) tl = strlen(tmpdir);
+ if( dir != NULL ) dl = strlen(dir);
+
+ if( (p = malloc((unsigned)(max(max(dl,tl),pl)+16))) == NULL )
+ return(NULL);
+
+ *p = '\0';
+
+ if( (tl == 0) || (access( cpdir(p, tmpdir), 3) != 0) )
+ if( (dl == 0) || (access( cpdir(p, dir), 3) != 0) )
+ if( access( cpdir(p, P_tmpdir), 3) != 0 )
+ if( access( cpdir(p, "/tmp"), 3) != 0 )
+ return(NULL);
+
+ (void) strcat(p, "/");
+ if(prefix)
+ {
+ *(p+strlen(p)+5) = '\0';
+ (void)strncat(p, prefix, 5);
+ }
+
+ (void)strcat(p, seed);
+ (void)strcat(p, "XXXXXX");
+
+ q = seed;
+ while(*q == 'Z') *q++ = 'A';
+ ++*q;
+
+ if(*mktemp(p) == '\0') return(NULL);
+ return(p);
+}
+
+
+
+static char *
+cpdir(buf, str)
+char *buf;
+char *str;
+{
+ char *p;
+
+ if(str != NULL)
+ {
+ (void) strcpy(buf, str);
+ p = buf - 1 + strlen(buf);
+ if(*p == '/') *p = '\0';
+ }
+
+ return(buf);
+}
diff --git a/dmake/unix/bsd43/utime.c b/dmake/unix/bsd43/utime.c
new file mode 100644
index 000000000000..9d26700d8006
--- /dev/null
+++ b/dmake/unix/bsd43/utime.c
@@ -0,0 +1,70 @@
+/* RCS $Id: utime.c,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- utime
+--
+-- DESCRIPTION
+-- Provide our own utime function.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+
+int
+utime(name, timep)
+char* name;
+time_t timep[2];
+{
+ struct timeval tv[2], *tvp;
+ struct stat buf;
+ int fil;
+ char data;
+
+ if (timep!=0)
+ {
+ tvp = tv, tv[0].tv_sec = timep[0], tv[1].tv_sec = timep[1];
+ if (utimes(name, tvp)==0)
+ return (0);
+ }
+
+ if (stat(name, &buf) != 0)
+ return (-1);
+ if (buf.st_size != 0) {
+ if ((fil = open(name, O_RDWR, 0666)) < 0)
+ return (-1);
+ if (read(fil, &data, 1) < 1) {
+ close(fil);
+ return (-1);
+ }
+ lseek(fil, 0L, 0);
+ if (write(fil, &data, 1) < 1) {
+ close(fil);
+ return (-1);
+ }
+ close(fil);
+ return (0);
+ } else if ((fil = creat(name, 0666)) < 0) {
+ return (-1);
+ } else {
+ close(fil);
+ return (0);
+ }
+}
diff --git a/dmake/unix/bsd43/uw/config.mk b/dmake/unix/bsd43/uw/config.mk
new file mode 100644
index 000000000000..1f94136f6d6e
--- /dev/null
+++ b/dmake/unix/bsd43/uw/config.mk
@@ -0,0 +1,17 @@
+# This is the BSD 4.3 University of Waterloo (uw) UNIX configuration file
+# for DMAKE
+# It simply modifies the values of LDLIBS to include libuw.a
+# so that vfprintf can be found.
+#
+
+LDLIBS += -luw
+osredir := $(OS)$(DIRSEPSTR)$(OSRELEASE)$(DIRSEPSTR)$(OSENVIRONMENT)
+CFLAGS += -I$(osredir)
+
+# install script for UW's /usr/software hierarchy...
+install:
+ mkdir ../bin; strip ./dmake; mv ./dmake ../bin
+ chmod a+rx ../bin/dmake ../bin
+ mkdir ../lib; chmod a+rx ../lib
+ cp $(STARTUPFILE) ../lib
+ chmod a+r ../lib/startup.mk
diff --git a/dmake/unix/bsd43/uw/make.sh b/dmake/unix/bsd43/uw/make.sh
new file mode 100644
index 000000000000..f23ecbb8ec44
--- /dev/null
+++ b/dmake/unix/bsd43/uw/make.sh
@@ -0,0 +1,69 @@
+mkdir objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O infer.c
+mv infer.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O make.c
+mv make.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O stat.c
+mv stat.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O expand.c
+mv expand.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O dmstring.c
+mv dmstring.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O hash.c
+mv hash.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O dag.c
+mv dag.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O dmake.c
+mv dmake.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O path.c
+mv path.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O imacs.c
+mv imacs.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O sysintf.c
+mv sysintf.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O parse.c
+mv parse.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O getinp.c
+mv getinp.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O quit.c
+mv quit.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O state.c
+mv state.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O dmdump.c
+mv dmdump.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O macparse.c
+mv macparse.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O rulparse.c
+mv rulparse.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O percent.c
+mv percent.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O function.c
+mv function.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O unix/arlib.c
+mv arlib.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O unix/dirbrk.c
+mv dirbrk.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O unix/rmprq.c
+mv rmprq.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O unix/ruletab.c
+mv ruletab.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O unix/runargv.c
+mv runargv.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O unix/dcache.c
+mv dcache.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O unix/bsd43/putenv.c
+mv putenv.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O unix/bsd43/tempnam.c
+mv tempnam.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O unix/bsd43/utime.c
+mv utime.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/uw -O unix/bsd43/setvbuf.c
+mv setvbuf.o objects
+cc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o \
+objects/dcache.o objects/putenv.o objects/tempnam.o objects/utime.o objects/setvbuf.o -luw
+cp unix/bsd43/uw/template.mk startup/config.mk
diff --git a/dmake/unix/bsd43/uw/public.h b/dmake/unix/bsd43/uw/public.h
new file mode 100644
index 000000000000..da4cc6c0b7c4
--- /dev/null
+++ b/dmake/unix/bsd43/uw/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/bsd43/uw/template.mk b/dmake/unix/bsd43/uw/template.mk
new file mode 100644
index 000000000000..6afe91c1fc7a
--- /dev/null
+++ b/dmake/unix/bsd43/uw/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= bsd43
+ OSENVIRONMENT *:= uw
diff --git a/dmake/unix/bsd43/vf/config.mk b/dmake/unix/bsd43/vf/config.mk
new file mode 100644
index 000000000000..bf4e64808d6c
--- /dev/null
+++ b/dmake/unix/bsd43/vf/config.mk
@@ -0,0 +1,11 @@
+# This config file adds vfprintf.c and memcpy.c for those systems that
+# do not have it.
+#
+
+osredir := $(OS)$(DIRSEPSTR)$(OSRELEASE)$(DIRSEPSTR)$(OSENVIRONMENT)
+CFLAGS += -I$(osredir)
+
+# The following sources are required for BSD4.3
+OSDESRC := memcpy.c vfprintf.c
+SRC += $(OSDESRC)
+.SETDIR=$(osredir) : $(OSDESRC)
diff --git a/dmake/unix/bsd43/vf/ctype.h b/dmake/unix/bsd43/vf/ctype.h
new file mode 100644
index 000000000000..f229a9ab3967
--- /dev/null
+++ b/dmake/unix/bsd43/vf/ctype.h
@@ -0,0 +1,51 @@
+/* RCS $Id: ctype.h,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- ctype
+--
+-- DESCRIPTION
+-- ctype.h 4.2 85/09/04
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#define _U 01
+#define _L 02
+#define _N 04
+#define _S 010
+#define _P 020
+#define _C 040
+#define _X 0100
+#define _B 0200
+
+extern char _ctype_[];
+
+#define isalpha(c) ((_ctype_+1)[c]&(_U|_L))
+#define isupper(c) ((_ctype_+1)[c]&_U)
+#define islower(c) ((_ctype_+1)[c]&_L)
+#define isdigit(c) ((_ctype_+1)[c]&_N)
+#define isxdigit(c) ((_ctype_+1)[c]&(_N|_X))
+#define isspace(c) ((_ctype_+1)[c]&_S)
+#define ispunct(c) ((_ctype_+1)[c]&_P)
+#define isalnum(c) ((_ctype_+1)[c]&(_U|_L|_N))
+#define isprint(c) ((_ctype_+1)[c]&(_P|_U|_L|_N|_B))
+#define isgraph(c) ((_ctype_+1)[c]&(_P|_U|_L|_N))
+#define iscntrl(c) ((_ctype_+1)[c]&_C)
+#define isascii(c) ((unsigned)(c)<=0177)
+#define toupper(c) ((c)-'a'+'A')
+#define tolower(c) ((c)-'A'+'a')
+#define toascii(c) ((c)&0177)
diff --git a/dmake/unix/bsd43/vf/make.sh b/dmake/unix/bsd43/vf/make.sh
new file mode 100644
index 000000000000..231b683a80e6
--- /dev/null
+++ b/dmake/unix/bsd43/vf/make.sh
@@ -0,0 +1,73 @@
+mkdir objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O infer.c
+mv infer.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O make.c
+mv make.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O stat.c
+mv stat.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O expand.c
+mv expand.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O dmstring.c
+mv dmstring.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O hash.c
+mv hash.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O dag.c
+mv dag.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O dmake.c
+mv dmake.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O path.c
+mv path.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O imacs.c
+mv imacs.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O sysintf.c
+mv sysintf.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O parse.c
+mv parse.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O getinp.c
+mv getinp.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O quit.c
+mv quit.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O state.c
+mv state.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O dmdump.c
+mv dmdump.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O macparse.c
+mv macparse.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O rulparse.c
+mv rulparse.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O percent.c
+mv percent.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O function.c
+mv function.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O unix/arlib.c
+mv arlib.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O unix/dirbrk.c
+mv dirbrk.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O unix/rmprq.c
+mv rmprq.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O unix/ruletab.c
+mv ruletab.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O unix/runargv.c
+mv runargv.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O unix/dcache.c
+mv dcache.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O unix/bsd43/putenv.c
+mv putenv.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O unix/bsd43/tempnam.c
+mv tempnam.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O unix/bsd43/utime.c
+mv utime.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O unix/bsd43/setvbuf.c
+mv setvbuf.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O unix/bsd43/vf/memcpy.c
+mv memcpy.o objects
+cc -c -I. -Iunix -Iunix/bsd43 -Iunix/bsd43/vf -O unix/bsd43/vf/vfprintf.c
+mv vfprintf.o objects
+cc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o \
+objects/dcache.o objects/putenv.o objects/tempnam.o objects/utime.o objects/setvbuf.o objects/memcpy.o objects/vfprintf.o
+cp unix/bsd43/vf/template.mk startup/config.mk
diff --git a/dmake/unix/bsd43/vf/memcpy.c b/dmake/unix/bsd43/vf/memcpy.c
new file mode 100644
index 000000000000..4ae47722e851
--- /dev/null
+++ b/dmake/unix/bsd43/vf/memcpy.c
@@ -0,0 +1,36 @@
+/* RCS $Id: memcpy.c,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- memcpy
+--
+-- DESCRIPTION
+-- BSD didn't have this in the library many moons ago.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+char *
+memcpy(t, f, n)
+register char *t, *f;
+register n;
+{
+ register char *p = t;
+
+ while( --n >= 0 ) *t++ = *f++;
+
+ return (p);
+}
diff --git a/dmake/unix/bsd43/vf/public.h b/dmake/unix/bsd43/vf/public.h
new file mode 100644
index 000000000000..da4cc6c0b7c4
--- /dev/null
+++ b/dmake/unix/bsd43/vf/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/bsd43/vf/template.mk b/dmake/unix/bsd43/vf/template.mk
new file mode 100644
index 000000000000..395cd4718fa0
--- /dev/null
+++ b/dmake/unix/bsd43/vf/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= bsd43
+ OSENVIRONMENT *:= vf
diff --git a/dmake/unix/bsd43/vf/vfprintf.c b/dmake/unix/bsd43/vf/vfprintf.c
new file mode 100644
index 000000000000..675e2e83e5ab
--- /dev/null
+++ b/dmake/unix/bsd43/vf/vfprintf.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vfprintf.c 5.2 (Berkeley) 6/27/88";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <varargs.h>
+
+int
+vfprintf(iop, fmt, ap)
+ FILE *iop;
+ char *fmt;
+ va_list ap;
+{
+ int len;
+ char localbuf[BUFSIZ];
+
+ if (iop->_flag & _IONBF) {
+ iop->_flag &= ~_IONBF;
+ iop->_ptr = iop->_base = localbuf;
+ len = _doprnt(fmt, ap, iop);
+ (void) fflush(iop);
+ iop->_flag |= _IONBF;
+ iop->_base = NULL;
+ iop->_bufsiz = 0;
+ iop->_cnt = 0;
+ } else
+ len = _doprnt(fmt, ap, iop);
+
+ return (ferror(iop) ? EOF : len);
+}
+
diff --git a/dmake/unix/bsdarm32/config.mk b/dmake/unix/bsdarm32/config.mk
new file mode 100644
index 000000000000..e99937342e68
--- /dev/null
+++ b/dmake/unix/bsdarm32/config.mk
@@ -0,0 +1,27 @@
+# This is the BSD 4.3 UNIX configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+# The following sources are required for BSD4.3
+OSDSRC := putenv.c tempnam.c utime.c setvbuf.c
+.IF $(OSDSRC)
+ SRC += $(OSDSRC)
+ .SETDIR=$(osrdir) : $(OSDSRC)
+.END
+
+.SOURCE.h : $(osrdir)
+
+# Local configuration modifications for CFLAGS, there's local BSD includes
+# too.
+CFLAGS += -I$(osrdir)
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
diff --git a/dmake/unix/bsdarm32/dirent.h b/dmake/unix/bsdarm32/dirent.h
new file mode 100644
index 000000000000..b50fa18a9d9e
--- /dev/null
+++ b/dmake/unix/bsdarm32/dirent.h
@@ -0,0 +1,30 @@
+/* RCS $Id: dirent.h,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- dirent
+--
+-- DESCRIPTION
+-- Deal with sysV'ish dirent.h on BSD4.3 systems, which have the stuff
+-- in sys/dir.h
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <sys/dir.h>
+#include </usr/include/dirent.h>
+#define dirent direct
+
diff --git a/dmake/unix/bsdarm32/limits.h b/dmake/unix/bsdarm32/limits.h
new file mode 100644
index 000000000000..655d707bb4f6
--- /dev/null
+++ b/dmake/unix/bsdarm32/limits.h
@@ -0,0 +1,29 @@
+/* RCS $Id: limits.h,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- limits
+--
+-- DESCRIPTION
+-- Compensate for systems that don't have a limits.h header file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <sys/types.h>
+#include <sys/dirent.h>
+#include <sys/param.h>
+
diff --git a/dmake/unix/bsdarm32/make.sh b/dmake/unix/bsdarm32/make.sh
new file mode 100644
index 000000000000..f43dd9425774
--- /dev/null
+++ b/dmake/unix/bsdarm32/make.sh
@@ -0,0 +1,67 @@
+mkdir objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O infer.c
+mv infer.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O make.c
+mv make.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O stat.c
+mv stat.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O expand.c
+mv expand.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O dmstring.c
+mv dmstring.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O hash.c
+mv hash.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O dag.c
+mv dag.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O dmake.c
+mv dmake.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O path.c
+mv path.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O imacs.c
+mv imacs.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O sysintf.c
+mv sysintf.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O parse.c
+mv parse.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O getinp.c
+mv getinp.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O quit.c
+mv quit.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O state.c
+mv state.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O dmdump.c
+mv dmdump.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O macparse.c
+mv macparse.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O rulparse.c
+mv rulparse.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O percent.c
+mv percent.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O function.c
+mv function.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O unix/arlib.c
+mv arlib.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O unix/dirbrk.c
+mv dirbrk.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O unix/rmprq.c
+mv rmprq.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O unix/ruletab.c
+mv ruletab.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O unix/runargv.c
+mv runargv.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O unix/dcache.c
+mv dcache.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O unix/bsdarm32/putenv.c
+mv putenv.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O unix/bsdarm32/tempnam.c
+mv tempnam.o objects
+cc -c -I. -Iunix -Iunix/bsdarm32 -O unix/bsdarm32/utime.c
+mv utime.o objects
+cc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o \
+objects/dcache.o objects/putenv.o objects/tempnam.o objects/utime.o objects/setvbuf.o
+cp unix/bsdarm32/template.mk startup/config.mk
diff --git a/dmake/unix/bsdarm32/public.h b/dmake/unix/bsdarm32/public.h
new file mode 100644
index 000000000000..da4cc6c0b7c4
--- /dev/null
+++ b/dmake/unix/bsdarm32/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/bsdarm32/putenv.c b/dmake/unix/bsdarm32/putenv.c
new file mode 100644
index 000000000000..d0ed998158e0
--- /dev/null
+++ b/dmake/unix/bsdarm32/putenv.c
@@ -0,0 +1,78 @@
+/* RCS $Id: putenv.c,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- My own putenv for BSD like systems.
+--
+-- DESCRIPTION
+-- This originally came from MKS, but I rewrote it to fix a bug with
+-- replacing existing strings, probably never happened but the code
+-- was wrong nonetheless.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <stdio.h>
+#include <string.h>
+
+int
+putenv( str )/*
+===============
+ Take a string of the form NAME=value and stick it into the environment.
+ We do this by allocating a new set of pointers if we have to add a new
+ string and by replacing an existing pointer if the value replaces the value
+ of an existing string. */
+char *str;
+{
+ extern char **environ; /* The current environment. */
+ static char **ourenv = NULL; /* A new environment */
+ register char **p;
+ register char *q;
+ int size;
+
+ /* First search the current environment and see if we can replace a
+ * string. */
+ for( p=environ; *p; p++ ) {
+ register char *s = str;
+
+ for( q = *p; *q && *s && *s == *q; q++, s++ )
+ if( *s == '=' ) {
+ *p = str;
+ return(0); /* replaced it so go away */
+ }
+ }
+
+ /* Ok, can't replace a string so need to grow the environment. */
+ size = p - environ + 2; /* size of new environment */
+ /* size of old is size-1 */
+
+ /* It's the first time, so allocate a new environment since we don't know
+ * where the old one is comming from. */
+ if( ourenv == NULL ) {
+ if( (ourenv = (char **) malloc( sizeof(char *)*size )) == NULL )
+ return(1);
+
+ memcpy( (char *)ourenv, (char *)environ, (size-2)*sizeof(char *) );
+ }
+ else if( (ourenv = (char **)realloc( ourenv, size*sizeof(char *))) == NULL )
+ return(1);
+
+ ourenv[--size] = NULL;
+ ourenv[--size] = str;
+
+ environ = ourenv;
+ return(0);
+}
diff --git a/dmake/unix/bsdarm32/stdlib.h b/dmake/unix/bsdarm32/stdlib.h
new file mode 100644
index 000000000000..82ab9627cd65
--- /dev/null
+++ b/dmake/unix/bsdarm32/stdlib.h
@@ -0,0 +1,44 @@
+/* RCS $Id: stdlib.h,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- stdlib interface
+--
+-- DESCRIPTION
+-- Specially needed pieces of interface to the standard C lib.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _STDLIB_INCLUDED_
+#define _STDLIB_INCLUDED_
+
+extern /*GOTO*/ _exit();
+extern /*GOTO*/ exit();
+extern /*GOTO*/ abort();
+extern int system();
+extern char *getenv();
+extern char *calloc();
+extern char *malloc();
+extern char *realloc();
+extern free();
+extern int errno;
+
+#ifndef EIO
+# include <errno.h>
+#endif
+
+#endif /* _STDLIB_INCLUDED_ */
diff --git a/dmake/unix/bsdarm32/string.h b/dmake/unix/bsdarm32/string.h
new file mode 100644
index 000000000000..c8abdf137696
--- /dev/null
+++ b/dmake/unix/bsdarm32/string.h
@@ -0,0 +1,42 @@
+/* RCS $Id: string.h,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- string function headers
+--
+-- DESCRIPTION
+-- Supply correct definitions for certain string functions.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+
+/*
+** BSD does this wrong
+*/
+#include </usr/include/string.h>
+
+#include "stdmacs.h"
+extern char* strpbrk ANSI((const char* src, const char* any));
+
+#ifndef DBUG
+#define strchr(str,c) index(str,c)
+#define strrchr(str,c) rindex(str,c)
+#else
+char *strchr ANSI((char*, char));
+char *strrchr ANSI((char*, char));
+#endif
+
diff --git a/dmake/unix/bsdarm32/template.mk b/dmake/unix/bsdarm32/template.mk
new file mode 100644
index 000000000000..830e9958394c
--- /dev/null
+++ b/dmake/unix/bsdarm32/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= bsdarm32
+ OSENVIRONMENT *:=
diff --git a/dmake/unix/bsdarm32/tempnam.c b/dmake/unix/bsdarm32/tempnam.c
new file mode 100644
index 000000000000..a645f41abcf7
--- /dev/null
+++ b/dmake/unix/bsdarm32/tempnam.c
@@ -0,0 +1,105 @@
+/* RCS $Id: tempnam.c,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- tempnam
+--
+-- DESCRIPTION
+-- temp file name generation routines.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/*LINTLIBRARY*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define max(A,B) (((A)<(B))?(B):(A))
+
+extern char *mktemp();
+extern int access();
+
+static char *cpdir();
+static char seed[4]="AAA";
+
+/* BSD stdio.h doesn't define P_tmpdir, so let's do it here */
+#ifndef P_tmpdir
+static char *P_tmpdir = "/tmp";
+#endif
+
+
+char *
+tempnam(dir, prefix)
+const char *dir; /* use this directory please (if non-NULL) */
+const char *prefix; /* use this (if non-NULL) as filename prefix */
+{
+ register char *p, *q, *tmpdir;
+ int tl=0, dl=0, pl;
+
+ pl = strlen(P_tmpdir);
+
+ if( (tmpdir = getenv("TMPDIR")) != NULL ) tl = strlen(tmpdir);
+ if( dir != NULL ) dl = strlen(dir);
+
+ if( (p = malloc((unsigned)(max(max(dl,tl),pl)+16))) == NULL )
+ return(NULL);
+
+ *p = '\0';
+
+ if( (tl == 0) || (access( cpdir(p, tmpdir), 3) != 0) )
+ if( (dl == 0) || (access( cpdir(p, dir), 3) != 0) )
+ if( access( cpdir(p, P_tmpdir), 3) != 0 )
+ if( access( cpdir(p, "/tmp"), 3) != 0 )
+ return(NULL);
+
+ (void) strcat(p, "/");
+ if(prefix)
+ {
+ *(p+strlen(p)+5) = '\0';
+ (void)strncat(p, prefix, 5);
+ }
+
+ (void)strcat(p, seed);
+ (void)strcat(p, "XXXXXX");
+
+ q = seed;
+ while(*q == 'Z') *q++ = 'A';
+ ++*q;
+
+ if(*mktemp(p) == '\0') return(NULL);
+ return(p);
+}
+
+
+
+
+static char *
+cpdir(buf, str)
+char *buf;
+char *str;
+{
+ char *p;
+
+ if(str != NULL)
+ {
+ (void) strcpy(buf, str);
+ p = buf - 1 + strlen(buf);
+ if(*p == '/') *p = '\0';
+ }
+
+ return(buf);
+}
diff --git a/dmake/unix/bsdarm32/utime.c b/dmake/unix/bsdarm32/utime.c
new file mode 100644
index 000000000000..9d26700d8006
--- /dev/null
+++ b/dmake/unix/bsdarm32/utime.c
@@ -0,0 +1,70 @@
+/* RCS $Id: utime.c,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- utime
+--
+-- DESCRIPTION
+-- Provide our own utime function.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+
+int
+utime(name, timep)
+char* name;
+time_t timep[2];
+{
+ struct timeval tv[2], *tvp;
+ struct stat buf;
+ int fil;
+ char data;
+
+ if (timep!=0)
+ {
+ tvp = tv, tv[0].tv_sec = timep[0], tv[1].tv_sec = timep[1];
+ if (utimes(name, tvp)==0)
+ return (0);
+ }
+
+ if (stat(name, &buf) != 0)
+ return (-1);
+ if (buf.st_size != 0) {
+ if ((fil = open(name, O_RDWR, 0666)) < 0)
+ return (-1);
+ if (read(fil, &data, 1) < 1) {
+ close(fil);
+ return (-1);
+ }
+ lseek(fil, 0L, 0);
+ if (write(fil, &data, 1) < 1) {
+ close(fil);
+ return (-1);
+ }
+ close(fil);
+ return (0);
+ } else if ((fil = creat(name, 0666)) < 0) {
+ return (-1);
+ } else {
+ close(fil);
+ return (0);
+ }
+}
diff --git a/dmake/unix/coherent/config.mk b/dmake/unix/coherent/config.mk
new file mode 100644
index 000000000000..9c5890c8065d
--- /dev/null
+++ b/dmake/unix/coherent/config.mk
@@ -0,0 +1,26 @@
+# This is the COHERENT configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+# The following are required sources
+.IF $(OSDSRC)
+ SRC += $(OSDSRC)
+ .SETDIR=$(osrdir) : $(OSDSRC)
+.END
+
+.SOURCE.h : $(osrdir)
+
+# Local configuration modifications for CFLAGS, there's local SysV includes
+# too.
+CFLAGS += -I$(osrdir) -Dvoid=int
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
diff --git a/dmake/unix/coherent/stdlib.h b/dmake/unix/coherent/stdlib.h
new file mode 100644
index 000000000000..82ab9627cd65
--- /dev/null
+++ b/dmake/unix/coherent/stdlib.h
@@ -0,0 +1,44 @@
+/* RCS $Id: stdlib.h,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- stdlib interface
+--
+-- DESCRIPTION
+-- Specially needed pieces of interface to the standard C lib.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _STDLIB_INCLUDED_
+#define _STDLIB_INCLUDED_
+
+extern /*GOTO*/ _exit();
+extern /*GOTO*/ exit();
+extern /*GOTO*/ abort();
+extern int system();
+extern char *getenv();
+extern char *calloc();
+extern char *malloc();
+extern char *realloc();
+extern free();
+extern int errno;
+
+#ifndef EIO
+# include <errno.h>
+#endif
+
+#endif /* _STDLIB_INCLUDED_ */
diff --git a/dmake/unix/coherent/time.h b/dmake/unix/coherent/time.h
new file mode 100644
index 000000000000..e3509ed8ec8b
--- /dev/null
+++ b/dmake/unix/coherent/time.h
@@ -0,0 +1,32 @@
+/* RCS $Id: time.h,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- time_t
+--
+-- DESCRIPTION
+-- Properly define time_t.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef TIME_h
+#define TIME_h
+
+typedef long time_t; /* this is the thing we use */
+
+#endif TIME_h
+
diff --git a/dmake/unix/coherent/ver40/config.mk b/dmake/unix/coherent/ver40/config.mk
new file mode 100644
index 000000000000..df2a702ea02f
--- /dev/null
+++ b/dmake/unix/coherent/ver40/config.mk
@@ -0,0 +1,11 @@
+# This config file adds vfprintf.c and memcpy.c for those systems that
+# do not have it.
+#
+
+osredir := $(OS)$(DIRSEPSTR)$(OSRELEASE)$(DIRSEPSTR)$(OSENVIRONMENT)
+CFLAGS += -I$(osredir)
+
+# The following sources are required for coherent version 4.0
+OSDESRC := vfprintf.c getcwd.c
+SRC += $(OSDESRC)
+.SETDIR=$(osredir) : $(OSDESRC)
diff --git a/dmake/unix/coherent/ver40/getcwd.c b/dmake/unix/coherent/ver40/getcwd.c
new file mode 100644
index 000000000000..cc2772494611
--- /dev/null
+++ b/dmake/unix/coherent/ver40/getcwd.c
@@ -0,0 +1,49 @@
+/* RCS $Id: getcwd.c,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+--
+-- SYNOPSIS
+-- getcwd
+--
+-- DESCRIPTION
+-- Wrapper for getcwd.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#if __STDC__
+char *getcwd(char *buffer, int length)
+#else
+char *getcwd (buffer, length)
+char *buffer;
+int length;
+#endif
+{
+ extern char *getwd();
+
+ char *dir;
+ dir = getwd();
+ if (dir)
+ {
+ strncpy(buffer,dir,length);
+ return buffer;
+ }
+ else
+ {
+ *buffer = 0;
+ return (char *) 0;
+ }
+}
+
diff --git a/dmake/unix/coherent/ver40/make.sh b/dmake/unix/coherent/ver40/make.sh
new file mode 100644
index 000000000000..1a0c850452f0
--- /dev/null
+++ b/dmake/unix/coherent/ver40/make.sh
@@ -0,0 +1,64 @@
+mkdir objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O infer.c
+mv infer.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O make.c
+mv make.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O stat.c
+mv stat.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O expand.c
+mv expand.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O dmstring.c
+mv dmstring.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O hash.c
+mv hash.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O dag.c
+mv dag.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O dmake.c
+mv dmake.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O path.c
+mv path.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O imacs.c
+mv imacs.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O sysintf.c
+mv sysintf.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O parse.c
+mv parse.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O getinp.c
+mv getinp.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O quit.c
+mv quit.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O state.c
+mv state.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O dmdump.c
+mv dmdump.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O macparse.c
+mv macparse.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O rulparse.c
+mv rulparse.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O percent.c
+mv percent.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O function.c
+mv function.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O unix/arlib.c
+mv arlib.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O unix/dirbrk.c
+mv dirbrk.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O unix/rmprq.c
+mv rmprq.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O unix/ruletab.c
+mv ruletab.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O unix/runargv.c
+mv runargv.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O unix/dcache.c
+mv dcache.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O unix/coherent/ver40/vfprintf.c
+mv vfprintf.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver40 -O unix/coherent/ver40/getcwd.c
+mv getcwd.o objects
+cc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o objects/dcache.o objects/vfprintf.o objects/getcwd.o
+cp unix/coherent/ver40/template.mk startup/config.mk
diff --git a/dmake/unix/coherent/ver40/public.h b/dmake/unix/coherent/ver40/public.h
new file mode 100644
index 000000000000..da4cc6c0b7c4
--- /dev/null
+++ b/dmake/unix/coherent/ver40/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:34 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/coherent/ver40/template.mk b/dmake/unix/coherent/ver40/template.mk
new file mode 100644
index 000000000000..ef23550cf651
--- /dev/null
+++ b/dmake/unix/coherent/ver40/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= coherent
+ OSENVIRONMENT *:= ver40
diff --git a/dmake/unix/coherent/ver40/vfprintf.c b/dmake/unix/coherent/ver40/vfprintf.c
new file mode 100644
index 000000000000..907230db2081
--- /dev/null
+++ b/dmake/unix/coherent/ver40/vfprintf.c
@@ -0,0 +1,190 @@
+/* Portable vfprintf and vprintf by Robert A. Larson <blarson@skat.usc.edu> */
+
+/* Copyright 1989 Robert A. Larson.
+ * Distribution in any form is allowed as long as the author
+ * retains credit, changes are noted by their author and the
+ * copyright message remains intact. This program comes as-is
+ * with no warentee of fitness for any purpouse.
+ *
+ * Thanks to Doug Gwen, Chris Torek, and others who helped clarify
+ * the ansi printf specs.
+ *
+ * Please send any bug fixes and improvments to blarson@skat.usc.edu .
+ * The use of goto is NOT a bug.
+ */
+
+/* Feb 9, 1989 blarson First usenet release */
+
+/* This code implements the vfprintf function, without relying on
+ * the existance of _doprint or other system specific code.
+ *
+ * Define NOVOID if void * is not a supported type.
+ *
+ * Two compile options are available for efficency:
+ * INTSPRINTF should be defined if sprintf is int and returns
+ * the number of chacters formated.
+ * LONGINT should be defined if sizeof(long) == sizeof(int)
+ *
+ * They only make the code smaller and faster, they need not be
+ * defined.
+ *
+ * UNSIGNEDSPECIAL should be defined if unsigned is treated differently
+ * than int in argument passing. If this is definded, and LONGINT is not,
+ * the compiler must support the type unsingned long.
+ *
+ * Most quirks and bugs of the available fprintf fuction are duplicated,
+ * however * in the width and precision fields will work correctly
+ * even if fprintf does not support this. The %n format and the return
+ * count will only work if fprintf returns the number of characters
+ * formatted.
+ *
+ * Bad format strings, or those with very long width and precision
+ * fields (including expanded * fields) will cause undesired results.
+ */
+
+#ifdef OSK /* os9/68k can take advantage of both */
+#define INTSPRINTF
+#define LONGINT
+#endif
+#define NOVOID 1
+
+/* This must be a typedef not a #define! */
+#ifdef NOVOID
+typedef char *pointer;
+#else
+typedef void *pointer;
+#endif
+
+#include <stdio.h>
+
+#ifdef INTSPRINTF
+#define Sprintf(string,format,arg) (sprintf((string),(format),(arg)))
+#else
+#define Sprintf(string,format,arg) (\
+ sprintf((string),(format),(arg)),\
+ strlen(string)\
+)
+#endif
+
+#include <stdarg.h>
+
+typedef int *intp;
+
+int vfprintf(dest, format, args)
+FILE *dest;
+register char *format;
+va_list args;
+{
+ register char c;
+ register char *tp;
+ register int count = 0;
+ char tempfmt[64];
+#ifndef LONGINT
+ int longflag;
+#endif
+
+ tempfmt[0] = '%';
+ while(c = *format++) {
+ if(c=='%') {
+ tp = &tempfmt[1];
+#ifndef LONGINT
+ longflag = 0;
+#endif
+continue_format:
+ switch(c = *format++) {
+ case 's':
+ *tp++ = c;
+ *tp = '\0';
+ count += fprintf(dest, tempfmt, va_arg(args, char *));
+ break;
+ case 'u':
+ case 'x':
+ case 'o':
+ case 'X':
+#ifdef UNSIGNEDSPECIAL
+ *tp++ = c;
+ *tp = '\0';
+#ifndef LONGINT
+ if(longflag)
+ count += fprintf(dest, tempfmt, va_arg(args, unsigned long));
+ else
+#endif
+ count += fprintf(dest, tempfmt, va_arg(args, unsigned));
+ break;
+#endif
+ case 'd':
+ case 'c':
+ case 'i':
+ *tp++ = c;
+ *tp = '\0';
+#ifndef LONGINT
+ if(longflag)
+ count += fprintf(dest, tempfmt, va_arg(args, long));
+ else
+#endif
+ count += fprintf(dest, tempfmt, va_arg(args, int));
+ break;
+ case 'f':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ *tp++ = c;
+ *tp = '\0';
+ count += fprintf(dest, tempfmt, va_arg(args, double));
+ break;
+ case 'p':
+ *tp++ = c;
+ *tp = '\0';
+ count += fprintf(dest, tempfmt, va_arg(args, pointer));
+ break;
+ case '-':
+ case '+':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '.':
+ case ' ':
+ case '#':
+ case 'h':
+ *tp++ = c;
+ goto continue_format;
+ case 'l':
+#ifndef LONGINT
+ longflag = 1;
+ *tp++ = c;
+#endif
+ goto continue_format;
+ case '*':
+ tp += Sprintf(tp, "%d", va_arg(args, int));
+ goto continue_format;
+ case 'n':
+ *va_arg(args, intp) = count;
+ break;
+ case '%':
+ default:
+ putc(c, dest);
+ count++;
+ break;
+ }
+ } else {
+ putc(c, dest);
+ count++;
+ }
+ }
+ return count;
+}
+
+vprintf(format, args)
+char *format;
+va_list args;
+{
+ return vfprintf(stdout, format, args);
+}
diff --git a/dmake/unix/coherent/ver42/config.mk b/dmake/unix/coherent/ver42/config.mk
new file mode 100644
index 000000000000..2ff06b6b7917
--- /dev/null
+++ b/dmake/unix/coherent/ver42/config.mk
@@ -0,0 +1,11 @@
+# This config file adds vfprintf.c and memcpy.c for those systems that
+# do not have it.
+#
+
+osredir := $(OS)$(DIRSEPSTR)$(OSRELEASE)$(DIRSEPSTR)$(OSENVIRONMENT)
+CFLAGS += -I$(osredir)
+
+# The following sources are required for Coherent version 4.2
+#OSDESRC :=
+#SRC += $(OSDESRC)
+#.SETDIR=$(osredir) : $(OSDESRC)
diff --git a/dmake/unix/coherent/ver42/make.sh b/dmake/unix/coherent/ver42/make.sh
new file mode 100644
index 000000000000..bfc7f8252a5d
--- /dev/null
+++ b/dmake/unix/coherent/ver42/make.sh
@@ -0,0 +1,60 @@
+mkdir objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O infer.c
+mv infer.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O make.c
+mv make.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O stat.c
+mv stat.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O expand.c
+mv expand.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O dmstring.c
+mv dmstring.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O hash.c
+mv hash.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O dag.c
+mv dag.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O dmake.c
+mv dmake.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O path.c
+mv path.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O imacs.c
+mv imacs.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O sysintf.c
+mv sysintf.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O parse.c
+mv parse.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O getinp.c
+mv getinp.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O quit.c
+mv quit.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O state.c
+mv state.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O dmdump.c
+mv dmdump.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O macparse.c
+mv macparse.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O rulparse.c
+mv rulparse.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O percent.c
+mv percent.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O function.c
+mv function.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O unix/arlib.c
+mv arlib.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O unix/dirbrk.c
+mv dirbrk.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O unix/rmprq.c
+mv rmprq.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O unix/ruletab.c
+mv ruletab.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O unix/runargv.c
+mv runargv.o objects
+cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -Iunix/coherent/ver42 -O unix/dcache.c
+mv dcache.o objects
+cc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o objects/dcache.o
+cp unix/coherent/ver42/template.mk startup/config.mk
diff --git a/dmake/unix/coherent/ver42/public.h b/dmake/unix/coherent/ver42/public.h
new file mode 100644
index 000000000000..01e80862fbbd
--- /dev/null
+++ b/dmake/unix/coherent/ver42/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:35 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/coherent/ver42/template.mk b/dmake/unix/coherent/ver42/template.mk
new file mode 100644
index 000000000000..e5dd9f99ffac
--- /dev/null
+++ b/dmake/unix/coherent/ver42/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= coherent
+ OSENVIRONMENT *:= ver42
diff --git a/dmake/unix/config.mk b/dmake/unix/config.mk
new file mode 100644
index 000000000000..a6859ceb3c50
--- /dev/null
+++ b/dmake/unix/config.mk
@@ -0,0 +1,39 @@
+# This is an OS specific configuration file
+# It assumes that OBJDIR, TARGET and DEBUG are previously defined.
+# It defines CFLAGS, LDARGS, CPPFLAGS, STARTUPFILE, LDOBJS
+# PRINTER, PRINTFLAGS
+# It augments SRC, OBJDIR, TARGET, CFLAGS, LDLIBS
+#
+PRINTER = hw
+PRINTFLAGS = -P$(PRINTER)
+STARTUPFILE = $(OS)/startup.mk
+CPPFLAGS = $(CFLAGS)
+LDOBJS = $(CSTARTUP) $(OBJDIR)/{$(<:f)}
+LDARGS = $(LDFLAGS) -o $@ $(LDOBJS) $(LDLIBS)
+
+# Debug flags
+DB_CFLAGS = -g -DDBUG
+DB_LDFLAGS = -g
+DB_LDLIBS =
+
+# NO Debug flags
+NDB_CFLAGS = -O
+NDB_LDFLAGS = -O
+NDB_LDLIBS =
+
+# Local configuration modifications for CFLAGS.
+CFLAGS += -I$(OS)
+
+# Sources that must be defined for each different version
+OSSRC := arlib.c dirbrk.c rmprq.c ruletab.c runargv.c dcache.c
+SRC += $(OSSRC)
+.SETDIR=$(OS) : $(OSSRC)
+
+# Set source dirs so that we can find files named in this
+# config file.
+.SOURCE.h : $(OS)
+
+# See if we modify anything in the lower levels.
+.IF $(OSRELEASE) != $(NULL)
+ .INCLUDE .IGNORE : $(OS)$(DIRSEPSTR)$(OSRELEASE)$(DIRSEPSTR)config.mk
+.END
diff --git a/dmake/unix/dcache.c b/dmake/unix/dcache.c
new file mode 100644
index 000000000000..d9ab5d987584
--- /dev/null
+++ b/dmake/unix/dcache.c
@@ -0,0 +1,198 @@
+/* RCS $Id: dcache.c,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- Directory cache management routines.
+--
+-- DESCRIPTION
+-- This is the code that maintains a directory cache for each directory
+-- that dmake visits. The entire directory is thus only read once and
+-- the need for performing costly 'stat' calls when performing target
+-- inference is much reduced. The improvement in performance should be
+-- significant for NFS or remote mounted file systems.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* For Borland 5.00 compile, for some reason they seem to insist on pulling
+ * in the winnt.h if __WIN32__ is defined and you include <dirent.h>. This
+ * is, in my opinion, a BUG! on Borland's part.
+ */
+#if defined(__BORLANDC__) && defined(__WIN32__)
+#undef __WIN32__
+#endif
+
+#ifdef __APPLE__
+#include <sys/types.h>
+#endif
+#include <dirent.h>
+#include "extern.h"
+#include "sysintf.h"
+
+
+typedef struct ent {
+ char *name;
+ uint32 hkey;
+ time_t mtime;
+ int isdir;
+ struct ent *next;
+} Entry, *EntryPtr;
+
+
+typedef struct mydir {
+ char *path;
+ uint32 hkey;
+ EntryPtr entries;
+ struct mydir *next;
+} DirEntry, *DirEntryPtr;
+
+static DirEntryPtr dtab[HASH_TABLE_SIZE];
+
+
+/* Stat a path using the directory cache.
+ *
+ * We build a cannonical representation of the path using either an absolute
+ * path name if that is what 'path' is or the relative path name constructed
+ * from 'path' and the present value of Pwd.
+ *
+ * The present value of Pwd then gives a directory path that we search for
+ * in our cache using a hash lookup. If the directory component is located
+ * then we search the basename component of the path and return the result of
+ * the search: 0L if the component is not in the cache and it's time stamp
+ * otherwise.
+ *
+ * If the directory is not in our cache we insert it into the cache by
+ * openning the directory and reading all of the files within. Once read
+ * then we return the result of the above search.
+ *
+ * Optionally, if force is TRUE, and we did NOT read the directory to provide
+ * the result then stat the file anyway and update the internal cache.
+ */
+
+PUBLIC time_t
+CacheStat(path, force)
+char *path;
+int force;
+{
+ struct stat stbuf;
+ DirEntryPtr dp;
+ EntryPtr ep;
+ uint32 hkey;
+ uint16 hv;
+ char *fpath;
+ char *spath;
+ char *comp;
+ char *dir;
+ int loaded=FALSE;
+
+#ifdef __APPLE__
+ /* On Mac OS X, open, stat, and other system calls are case-insenstive.
+ Since this function keeps a case-sensitive cache, we need to force
+ a stat of the file if there is no match in the cache just to make sure
+ that we don't miss a file when only the case is different */
+ force = TRUE;
+#endif
+
+ if (If_root_path(path))
+ spath = path;
+ else
+ spath = Build_path(Pwd,path);
+
+ fpath = DmStrDup(spath);
+ comp = Basename(fpath);
+ dir = Filedir(fpath);
+
+ hv = Hash(dir,&hkey);
+
+ for(dp=dtab[hv]; dp; dp=dp->next)
+ if (hkey == dp->hkey && strcmp(dp->path,dir) == 0)
+ break;
+
+ if (!dp) {
+ DIR *dirp;
+ struct dirent *direntp;
+
+ if( Verbose & V_DIR_CACHE )
+ printf( "%s: Caching directory [%s]\n", Pname, dir );
+
+ /* Load the directory, we have the right hash position already */
+ loaded = TRUE;
+
+ TALLOC(dp,1,DirEntry);
+ dp->next = dtab[hv];
+ dtab[hv] = dp;
+ dp->path = DmStrDup(dir);
+ dp->hkey = hkey;
+
+ if (Set_dir(dir) == 0) {
+ if((dirp=opendir(".")) != NIL(DIR)) {
+ while((direntp=readdir(dirp)) != NULL) {
+ TALLOC(ep,1,Entry);
+ ep->name = DmStrDup(direntp->d_name);
+
+ /* Perform case mapping of name if appropriate */
+ DMSTRLWR(ep->name, comp);
+ Hash(ep->name, &ep->hkey);
+
+ ep->next = dp->entries;
+ dp->entries = ep;
+ DMSTAT(direntp->d_name,&stbuf);
+ ep->isdir = (stbuf.st_mode & S_IFDIR);
+ ep->mtime = stbuf.st_mtime;
+ }
+ closedir(dirp);
+ }
+ Set_dir(Pwd);
+ }
+ }
+
+ Hash(comp, &hkey);
+
+ if (dp) {
+ for(ep=dp->entries; ep; ep=ep->next)
+ if(hkey == ep->hkey && strcmp(ep->name,comp) == 0)
+ break;
+ }
+ else
+ ep = NULL;
+
+ if( force && !loaded) {
+ if (strlen(comp) > NameMax || DMSTAT(spath,&stbuf) != 0) {
+ if(ep)
+ ep->mtime = 0L;
+ }
+ else {
+ if (!ep) {
+ TALLOC(ep,1,Entry);
+ ep->name = DmStrDup(comp);
+ DMSTRLWR(ep->name, comp);
+ Hash(ep->name, &ep->hkey);
+ ep->next = dp->entries;
+ ep->isdir = (stbuf.st_mode & S_IFDIR);
+ dp->entries = ep;
+ }
+
+ ep->mtime = stbuf.st_mtime;
+ }
+
+ if( Verbose & V_DIR_CACHE )
+ printf("%s: Updating dir cache entry for [%s], new time is %d\n",
+ Pname, spath, ep ? ep->mtime : 0L);
+ }
+
+ FREE(fpath);
+ return(!ep ? (time_t)0L : ((STOBOOL(Augmake) && ep->isdir)?0L:ep->mtime));
+}
diff --git a/dmake/unix/dirbrk.c b/dmake/unix/dirbrk.c
new file mode 100644
index 000000000000..727df34f70a4
--- /dev/null
+++ b/dmake/unix/dirbrk.c
@@ -0,0 +1,42 @@
+/* RCS $Id: dirbrk.c,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- Define the directory separator string.
+--
+-- DESCRIPTION
+-- Define this string for any character that may appear in a path name
+-- and can be used as a directory separator. Also provide a function
+-- to indicate if a given path begins at the root of the file system.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+/* Unix only uses / */
+char* DirBrkStr = "/";
+
+/*
+** Return TRUE if the name is the full specification of a path name to a file
+** starting at the root of the file system, otherwise return FALSE
+*/
+PUBLIC int
+If_root_path(name)
+char *name;
+{
+ return( strchr(DirBrkStr, *name) != NIL(char) );
+}
diff --git a/dmake/unix/linux/config.mk b/dmake/unix/linux/config.mk
new file mode 100644
index 000000000000..75bcf3c2a211
--- /dev/null
+++ b/dmake/unix/linux/config.mk
@@ -0,0 +1,27 @@
+# This is the SysV R3 UNIX configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+# The following are required sources
+OSDSRC :=
+.IF $(OSDSRC)
+ SRC += $(OSDSRC)
+ .SETDIR=$(osrdir) : $(OSDSRC)
+.END
+
+.SOURCE.h : $(osrdir)
+
+# Local configuration modifications for CFLAGS, there's local SysV includes
+# too.
+CFLAGS += -I$(osrdir)
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
diff --git a/dmake/unix/linux/gnu/config.mk b/dmake/unix/linux/gnu/config.mk
new file mode 100644
index 000000000000..e351490a6b3d
--- /dev/null
+++ b/dmake/unix/linux/gnu/config.mk
@@ -0,0 +1,4 @@
+# This is the Linux gnu configuration file for DMAKE
+# It makes sure we include from the right place.
+#
+CFLAGS += -I$(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)
diff --git a/dmake/unix/linux/gnu/make.sh b/dmake/unix/linux/gnu/make.sh
new file mode 100644
index 000000000000..8e0aa400a80b
--- /dev/null
+++ b/dmake/unix/linux/gnu/make.sh
@@ -0,0 +1,193 @@
+platform=`uname -m`; export platform;
+
+mkdir objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O infer.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O infer.c
+fi
+mv infer.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O make.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O make.c
+fi
+mv make.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O stat.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O stat.c
+fi
+mv stat.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O expand.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O expand.c
+fi
+mv expand.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O dmstring.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O dmstring.c
+fi
+mv dmstring.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O hash.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O hash.c
+fi
+mv hash.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O dag.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O dag.c
+fi
+mv dag.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O dmake.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O dmake.c
+fi
+mv dmake.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O path.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O path.c
+fi
+mv path.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O imacs.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O imacs.c
+fi
+mv imacs.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O sysintf.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O sysintf.c
+fi
+mv sysintf.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O parse.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O parse.c
+fi
+mv parse.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O getinp.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O getinp.c
+fi
+mv getinp.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O quit.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O quit.c
+fi
+mv quit.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O state.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O state.c
+fi
+mv state.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O dmdump.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O dmdump.c
+fi
+mv dmdump.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O macparse.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O macparse.c
+fi
+mv macparse.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O rulparse.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O rulparse.c
+fi
+mv rulparse.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O percent.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O percent.c
+fi
+mv percent.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O function.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O function.c
+fi
+mv function.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O unix/arlib.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O unix/arlib.c
+fi
+mv arlib.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O unix/dirbrk.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O unix/dirbrk.c
+fi
+mv dirbrk.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O unix/rmprq.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O unix/rmprq.c
+fi
+mv rmprq.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O unix/ruletab.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O unix/ruletab.c
+fi
+mv ruletab.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O unix/runargv.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O unix/runargv.c
+fi
+mv runargv.o objects
+
+if test $platform = sparc -o $platform = sparc64; then
+gcc -c -ansi -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O unix/dcache.c
+else
+gcc -c -I. -Iunix -Iunix/linux -Iunix/linux/gnu -O unix/dcache.c
+fi
+mv dcache.o objects
+
+gcc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o objects/dcache.o
+cp unix/linux/gnu/template.mk startup/config.mk
diff --git a/dmake/unix/linux/gnu/public.h b/dmake/unix/linux/gnu/public.h
new file mode 100644
index 000000000000..01e80862fbbd
--- /dev/null
+++ b/dmake/unix/linux/gnu/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:35 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/linux/gnu/template.mk b/dmake/unix/linux/gnu/template.mk
new file mode 100644
index 000000000000..a0bcef64097b
--- /dev/null
+++ b/dmake/unix/linux/gnu/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= linux
+ OSENVIRONMENT *:= gnu
diff --git a/dmake/unix/macosx/config.mk b/dmake/unix/macosx/config.mk
new file mode 100644
index 000000000000..75bcf3c2a211
--- /dev/null
+++ b/dmake/unix/macosx/config.mk
@@ -0,0 +1,27 @@
+# This is the SysV R3 UNIX configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+# The following are required sources
+OSDSRC :=
+.IF $(OSDSRC)
+ SRC += $(OSDSRC)
+ .SETDIR=$(osrdir) : $(OSDSRC)
+.END
+
+.SOURCE.h : $(osrdir)
+
+# Local configuration modifications for CFLAGS, there's local SysV includes
+# too.
+CFLAGS += -I$(osrdir)
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
diff --git a/dmake/unix/macosx/gnu/config.mk b/dmake/unix/macosx/gnu/config.mk
new file mode 100644
index 000000000000..e351490a6b3d
--- /dev/null
+++ b/dmake/unix/macosx/gnu/config.mk
@@ -0,0 +1,4 @@
+# This is the Linux gnu configuration file for DMAKE
+# It makes sure we include from the right place.
+#
+CFLAGS += -I$(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)
diff --git a/dmake/unix/macosx/gnu/make.sh b/dmake/unix/macosx/gnu/make.sh
new file mode 100644
index 000000000000..b17a774defb4
--- /dev/null
+++ b/dmake/unix/macosx/gnu/make.sh
@@ -0,0 +1,60 @@
+mkdir objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O infer.c
+mv infer.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O make.c
+mv make.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O stat.c
+mv stat.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O expand.c
+mv expand.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O dmstring.c
+mv dmstring.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O hash.c
+mv hash.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O dag.c
+mv dag.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O dmake.c
+mv dmake.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O path.c
+mv path.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O imacs.c
+mv imacs.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O sysintf.c
+mv sysintf.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O parse.c
+mv parse.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O getinp.c
+mv getinp.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O quit.c
+mv quit.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O state.c
+mv state.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O dmdump.c
+mv dmdump.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O macparse.c
+mv macparse.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O rulparse.c
+mv rulparse.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O percent.c
+mv percent.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O function.c
+mv function.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O unix/arlib.c
+mv arlib.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O unix/dirbrk.c
+mv dirbrk.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O unix/rmprq.c
+mv rmprq.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O unix/ruletab.c
+mv ruletab.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O unix/runargv.c
+mv runargv.o objects
+cc -c -I. -Iunix -Iunix/macosx -Iunix/macosx/gnu -O unix/dcache.c
+mv dcache.o objects
+cc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o objects/dcache.o
+cp unix/macosx/gnu/template.mk startup/config.mk
diff --git a/dmake/unix/macosx/gnu/public.h b/dmake/unix/macosx/gnu/public.h
new file mode 100644
index 000000000000..01e80862fbbd
--- /dev/null
+++ b/dmake/unix/macosx/gnu/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:35 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/macosx/gnu/template.mk b/dmake/unix/macosx/gnu/template.mk
new file mode 100644
index 000000000000..672878dfa095
--- /dev/null
+++ b/dmake/unix/macosx/gnu/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= macosx
+ OSENVIRONMENT *:= gnu
diff --git a/dmake/unix/rmprq.c b/dmake/unix/rmprq.c
new file mode 100644
index 000000000000..3b95f237b7b8
--- /dev/null
+++ b/dmake/unix/rmprq.c
@@ -0,0 +1,96 @@
+/* RCS $Id: rmprq.c,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- Remove prerequisites code.
+--
+-- DESCRIPTION
+-- This code is different for DOS and for UNIX and parallel make
+-- architectures since the parallel case requires the rm's to be
+-- run in parallel, whereas DOS guarantees to run them sequentially.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include "extern.h"
+
+PUBLIC void
+Remove_prq( tcp )
+CELLPTR tcp;
+{
+ static LINKPTR rlp = NIL(LINK);
+ static flag = 0;
+ static HASHPTR m_at, m_q, m_b, m_g, m_l, m_bb, m_up;
+ char *m_at_s, *m_g_s, *m_q_s, *m_b_s, *m_l_s, *m_bb_s, *m_up_s;
+ LINKPTR tlp;
+
+ tcp->ce_flag &= ~(F_MADE|F_VISITED);
+ tcp->ce_time = 0L;
+
+ for( tlp=rlp; tlp !=NIL(LINK); tlp=tlp->cl_next )
+ if( (tlp->cl_prq->ce_flag & (F_VISITED|F_MADE)) != F_VISITED )
+ break;
+
+ if( tlp == NIL(LINK) ) {
+ TALLOC(tlp, 1, LINK);
+ TALLOC(tlp->cl_prq, 1, CELL);
+ tlp->cl_next = rlp;
+ rlp = tlp;
+ }
+
+ *tlp->cl_prq = *tcp;
+
+ /* We save the dynamic macro values here, as it is possible that the
+ * .REMOVE recipe is getting executed for a target while some other target
+ * is in the middle of executing it's list of recipe lines, in this case
+ * the values of $@ etc, must be preserved so that when we return to
+ * complete the other recipe we must make certain that the values of it's
+ * dynamic macros are unmodified. */
+
+ if( !flag ) {
+ /* Do the getting of the macros only once. */
+ flag = 1;
+ m_at = Get_name("@", Macs, TRUE);
+ m_g = Get_name(">", Macs, TRUE);
+ m_q = Get_name("?", Macs, TRUE);
+ m_b = Get_name("<", Macs, TRUE);
+ m_l = Get_name("&", Macs, TRUE);
+ m_bb = Get_name("*", Macs, TRUE);
+ m_up = Get_name("^", Macs, TRUE);
+ }
+
+ m_at_s = m_at->ht_value; m_at->ht_value = NIL(char);
+ m_g_s = m_g->ht_value; m_g->ht_value = NIL(char);
+ m_q_s = m_q->ht_value; m_q->ht_value = NIL(char);
+ m_b_s = m_b->ht_value; m_b->ht_value = NIL(char);
+ m_l_s = m_l->ht_value; m_l->ht_value = NIL(char);
+ m_bb_s = m_bb->ht_value; m_bb->ht_value = NIL(char);
+ m_up_s = m_up->ht_value; m_up->ht_value = NIL(char);
+
+ Make( tlp->cl_prq, tcp );
+ if( tlp->cl_prq->ce_dir ){
+ FREE(tlp->cl_prq->ce_dir);
+ tlp->cl_prq->ce_dir=NIL(char);
+ }
+
+ m_at->ht_value = m_at_s;
+ m_g->ht_value = m_g_s;
+ m_q->ht_value = m_q_s;
+ m_b->ht_value = m_b_s;
+ m_l->ht_value = m_l_s;
+ m_bb->ht_value = m_bb_s;
+ m_up->ht_value = m_up_s;
+}
diff --git a/dmake/unix/ruletab.c b/dmake/unix/ruletab.c
new file mode 100644
index 000000000000..a7723ad0e8bb
--- /dev/null
+++ b/dmake/unix/ruletab.c
@@ -0,0 +1,41 @@
+/* RCS $Id: ruletab.c,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- Default initial configuration of dmake.
+--
+-- DESCRIPTION
+-- Define here the initial set of rules that are defined before
+-- dmake performs any processing.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* These are control macros for dmake that MUST be defined at some point
+ * if they are NOT dmake will not work! These are default definitions. They
+ * may be overridden inside the .STARTUP makefile, they are here
+ * strictly so that dmake can parse the STARTUP makefile */
+
+static char *_rules[] = {
+ "MAXPROCESSLIMIT := 10",
+ "MAXLINELENGTH := 8190",
+ ".IMPORT .IGNORE: DMAKEROOT SOLARVER UPD INPATH OS UPDMINOREXT",
+ ".MAKEFILES : makefile.mk Makefile makefile",
+ ".SOURCE : .NULL",
+#include "startup.h"
+ 0 };
+
+char **Rule_tab = _rules; /* for sundry reasons in Get_environment() */
diff --git a/dmake/unix/runargv.c b/dmake/unix/runargv.c
new file mode 100644
index 000000000000..df795c2f6b6f
--- /dev/null
+++ b/dmake/unix/runargv.c
@@ -0,0 +1,307 @@
+/* RCS $Id: runargv.c,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- Invoke a sub process.
+--
+-- DESCRIPTION
+-- Use the standard methods of executing a sub process.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <signal.h>
+#include "extern.h"
+#include "sysintf.h"
+
+typedef struct prp {
+ char *prp_cmd;
+ int prp_group;
+ int prp_ignore;
+ int prp_last;
+ int prp_shell;
+ struct prp *prp_next;
+} RCP, *RCPPTR;
+
+typedef struct pr {
+ int pr_valid;
+ int pr_pid;
+ CELLPTR pr_target;
+ int pr_ignore;
+ int pr_last;
+ RCPPTR pr_recipe;
+ RCPPTR pr_recipe_end;
+ char *pr_dir;
+} PR;
+
+static PR *_procs = NIL(PR);
+static int _proc_cnt = 0;
+static int _abort_flg= FALSE;
+static int _use_i = -1;
+static int _do_upd = 0;
+
+static void _add_child ANSI((int, CELLPTR, int, int));
+static void _attach_cmd ANSI((char *, int, int, CELLPTR, int, int));
+static void _finished_child ANSI((int, int));
+static int _running ANSI((CELLPTR));
+
+PUBLIC int
+runargv(target, ignore, group, last, shell, cmd)
+CELLPTR target;
+int ignore;
+int group;
+int last;
+int shell;
+char *cmd;
+{
+ extern int errno;
+#ifndef __APPLE__
+#ifdef arm32
+ extern const char * const sys_errlist[];
+#else
+#ifdef linux
+ extern const char * const sys_errlist[];
+#else
+ extern char *sys_errlist[];
+#endif
+#endif
+#endif
+ int pid;
+ char **argv;
+
+ if( _running(target) /*&& Max_proc != 1*/ ) {
+ /* The command will be executed when the previous recipe
+ * line completes. */
+ _attach_cmd( cmd, group, ignore, target, last, shell );
+ return(1);
+ }
+
+ while( _proc_cnt == Max_proc )
+ if( Wait_for_child(FALSE, -1) == -1 ) Fatal( "Lost a child %d", errno );
+
+ argv = Pack_argv( group, shell, cmd );
+
+ switch( pid=fork() ){
+ int wid;
+ int status;
+
+ case -1: /* fork failed */
+ Error("%s: %s", argv[0], sys_errlist[errno]);
+ Handle_result(-1, ignore, _abort_flg, target);
+ return(-1);
+
+ case 0: /* child */
+ execvp(argv[0], argv);
+ Continue = TRUE; /* survive error message */
+ Error("%s: %s", argv[0], sys_errlist[errno]);
+ kill(getpid(), SIGTERM);
+ /*NOTREACHED*/
+
+ default: /* parent */
+ _add_child(pid, target, ignore, last);
+ }
+
+ return(1);
+}
+
+
+PUBLIC int
+Wait_for_child( abort_flg, pid )
+int abort_flg;
+int pid;
+{
+ int wid;
+ int status;
+ int waitchild;
+
+ waitchild = (pid == -1)? FALSE : Wait_for_completion;
+
+ do {
+ if( (wid = wait(&status)) == -1 ) return(-1);
+
+ _abort_flg = abort_flg;
+ _finished_child(wid, status);
+ _abort_flg = FALSE;
+ }
+ while( waitchild && pid != wid );
+
+ return(0);
+}
+
+
+PUBLIC void
+Clean_up_processes()
+{
+ register int i;
+
+ if( _procs != NIL(PR) ) {
+ for( i=0; i<Max_proc; i++ )
+ if( _procs[i].pr_valid )
+ kill(_procs[i].pr_pid, SIGTERM);
+
+ while( Wait_for_child(TRUE, -1) != -1 );
+ }
+}
+
+
+static void
+_add_child( pid, target, ignore, last )
+int pid;
+CELLPTR target;
+int ignore;
+int last;
+{
+ register int i;
+ register PR *pp;
+
+ if( _procs == NIL(PR) ) {
+ TALLOC( _procs, Max_proc, PR );
+ }
+
+ if( (i = _use_i) == -1 )
+ for( i=0; i<Max_proc; i++ )
+ if( !_procs[i].pr_valid )
+ break;
+
+ pp = _procs+i;
+
+ pp->pr_valid = 1;
+ pp->pr_pid = pid;
+ pp->pr_target = target;
+ pp->pr_ignore = ignore;
+ pp->pr_last = last;
+ pp->pr_dir = DmStrDup(Get_current_dir());
+
+ Current_target = NIL(CELL);
+
+ _proc_cnt++;
+
+ if( Wait_for_completion ) Wait_for_child( FALSE, pid );
+}
+
+
+static void
+_finished_child(pid, status)
+int pid;
+int status;
+{
+ register int i;
+ register PR *pp;
+ char *dir;
+
+ for( i=0; i<Max_proc; i++ )
+ if( _procs[i].pr_valid && _procs[i].pr_pid == pid )
+ break;
+
+ /* Some children we didn't make esp true if using /bin/sh to execute a
+ * a pipe and feed the output as a makefile into dmake. */
+ if( i == Max_proc ) return;
+ _procs[i].pr_valid = 0;
+ _proc_cnt--;
+ dir = DmStrDup(Get_current_dir());
+ Set_dir( _procs[i].pr_dir );
+
+ if( _procs[i].pr_recipe != NIL(RCP) && !_abort_flg ) {
+ RCPPTR rp = _procs[i].pr_recipe;
+
+
+ Current_target = _procs[i].pr_target;
+ Handle_result( status, _procs[i].pr_ignore, FALSE, _procs[i].pr_target );
+ Current_target = NIL(CELL);
+
+ if ( _procs[i].pr_target->ce_attr & A_ERROR ) {
+ Unlink_temp_files( _procs[i].pr_target );
+ _procs[i].pr_last = TRUE;
+ goto ABORT_REMAINDER_OF_RECIPE;
+ }
+
+ _procs[i].pr_recipe = rp->prp_next;
+
+ _use_i = i;
+ runargv( _procs[i].pr_target, rp->prp_ignore, rp->prp_group,
+ rp->prp_last, rp->prp_shell, rp->prp_cmd );
+ _use_i = -1;
+
+ FREE( rp->prp_cmd );
+ FREE( rp );
+
+ if( _proc_cnt == Max_proc ) Wait_for_child( FALSE, -1 );
+ }
+ else {
+ Unlink_temp_files( _procs[i].pr_target );
+ Handle_result(status,_procs[i].pr_ignore,_abort_flg,_procs[i].pr_target);
+
+ ABORT_REMAINDER_OF_RECIPE:
+ if( _procs[i].pr_last ) {
+ FREE(_procs[i].pr_dir );
+
+ if( !Doing_bang ) Update_time_stamp( _procs[i].pr_target );
+ }
+ }
+
+ Set_dir(dir);
+ FREE(dir);
+}
+
+
+static int
+_running( cp )
+CELLPTR cp;
+{
+ register int i;
+
+ if( !_procs ) return(FALSE);
+
+ for( i=0; i<Max_proc; i++ )
+ if( _procs[i].pr_valid &&
+ _procs[i].pr_target == cp )
+ break;
+
+ return( i != Max_proc );
+}
+
+
+static void
+_attach_cmd( cmd, group, ignore, cp, last, shell )
+char *cmd;
+int group;
+int ignore;
+CELLPTR cp;
+int last;
+int shell;
+{
+ register int i;
+ RCPPTR rp;
+
+ for( i=0; i<Max_proc; i++ )
+ if( _procs[i].pr_valid &&
+ _procs[i].pr_target == cp )
+ break;
+
+ TALLOC( rp, 1, RCP );
+ rp->prp_cmd = DmStrDup(cmd);
+ rp->prp_group = group;
+ rp->prp_ignore= ignore;
+ rp->prp_last = last;
+ rp->prp_shell = shell;
+
+ if( _procs[i].pr_recipe == NIL(RCP) )
+ _procs[i].pr_recipe = _procs[i].pr_recipe_end = rp;
+ else {
+ _procs[i].pr_recipe_end->prp_next = rp;
+ _procs[i].pr_recipe_end = rp;
+ }
+}
diff --git a/dmake/unix/solaris/config.mk b/dmake/unix/solaris/config.mk
new file mode 100644
index 000000000000..bc2364a33260
--- /dev/null
+++ b/dmake/unix/solaris/config.mk
@@ -0,0 +1,27 @@
+# This is the BSD 4.3 UNIX configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+# The following sources are required for Solaris 2.1 or greater
+OSDSRC := tempnam.c getcwd.c
+.IF $(OSDSRC)
+ SRC += $(OSDSRC)
+ .SETDIR=$(osrdir) : $(OSDSRC)
+.END
+
+.SOURCE.h : $(osrdir)
+
+# Local configuration modifications for CFLAGS, there's local BSD includes
+# too.
+CFLAGS += -I$(osrdir) -DSolaris
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
diff --git a/dmake/unix/solaris/getcwd.c b/dmake/unix/solaris/getcwd.c
new file mode 100644
index 000000000000..f2359bcc795b
--- /dev/null
+++ b/dmake/unix/solaris/getcwd.c
@@ -0,0 +1,231 @@
+/*
+ getcwd -- get pathname of current working directory
+
+ public-domain implementation
+
+ last edit: 03-Nov-1990 Gwyn@BRL.MIL
+
+ complies with the following standards:
+ IEEE Std 1003.1-1988
+ SVID Issue 3
+ X/Open Portability Guide Issue 2 (when "XPG2" is defined)
+ X/Open Portability Guide Issue 3
+
+ This implementation of getcwd() can be used to replace the UNIX
+ System V library routine (which uses popen() to capture the output of
+ the "pwd" command). Once that is done, "pwd" can be reimplemented as
+ just puts(getcwd((char*)0,0)), assuming "XPG2" is defined below.
+
+ This implementation depends on every directory having entries for
+ "." and "..". It also depends on the internals of the <dirent.h>
+ data structures to some degree.
+
+ I considered using chdir() to ascend the hierarchy, followed by a
+ final chdir() to the path being returned by getcwd() to restore the
+ location, but decided that error recovery was too difficult that way.
+ The algorithm I settled on was inspired by my rewrite of the "pwd"
+ utility, combined with the dotdots[] array trick from the SVR2 shell.
+*/
+#define XPG2 /* define to support obsolete XPG2-mandated feature */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef M_XENIX
+# include <sys/ndir.h>
+# define dirent direct
+#else
+# include <dirent.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+
+typedef char *pointer; /* (void *) if you have it */
+
+extern void free();
+extern pointer malloc();
+extern int fstat(), stat();
+
+extern int errno; /* normally done by <errno.h> */
+
+#ifndef NULL
+#define NULL 0 /* amorphous null pointer constant */
+#endif
+
+#ifndef NAME_MAX
+#define NAME_MAX 255 /* maximum directory entry size */
+#endif
+
+
+char *
+getcwd( buf, size ) /* returns pointer to CWD pathname */
+ char *buf; /* where to put name (NULL to malloc) */
+ int size; /* size of buf[] or malloc()ed memory */
+ {
+ static char dotdots[] =
+"../../../../../../../../../../../../../../../../../../../../../../../../../..";
+ char *dotdot; /* -> dotdots[.], right to left */
+ DIR *dirp; /* -> parent directory stream */
+ struct dirent *dir; /* -> directory entry */
+ struct stat stat1,
+ stat2; /* info from stat() */
+ struct stat *d = &stat1; /* -> info about "." */
+ struct stat *dd = &stat2; /* -> info about ".." */
+ register char *buffer; /* local copy of buf, or malloc()ed */
+ char *bufend; /* -> buffer[size] */
+ register char *endp; /* -> end of reversed string */
+ register char *dname; /* entry name ("" for root) */
+ int serrno = errno; /* save entry errno */
+
+ if ( buf != NULL && size <= 0
+#ifndef XPG2
+ || buf == NULL
+#endif
+ ) {
+ errno = EINVAL; /* invalid argument */
+ return NULL;
+ }
+
+ buffer = buf;
+#ifdef XPG2
+ if ( buf == NULL /* wants us to malloc() the string */
+ && (buffer = (char *) malloc( (unsigned) size )) == NULL
+ /* XXX -- actually should probably not pay attention to "size" arg */
+ ) {
+ errno = ENOMEM; /* cannot malloc() specified size */
+ return NULL;
+ }
+#endif
+
+ if ( stat( ".", dd ) != 0 ) /* prime the pump */
+ goto error; /* errno already set */
+
+ endp = buffer; /* initially, empty string */
+ bufend = &buffer[size];
+
+ for ( dotdot = &dotdots[sizeof dotdots]; dotdot != dotdots; )
+ {
+ dotdot -= 3; /* include one more "/.." section */
+ /* (first time is actually "..") */
+
+ /* swap stat() info buffers */
+ {
+ register struct stat *temp = d;
+
+ d = dd; /* new current dir is old parent dir */
+ dd = temp;
+ }
+
+ if ( (dirp = opendir( dotdot )) == NULL ) /* new parent */
+ goto error; /* errno already set */
+
+ if ( fstat( dirp->dd_fd, dd ) != 0 )
+ {
+ serrno = errno; /* set by fstat() */
+ (void)closedir( dirp );
+ errno = serrno; /* in case closedir() clobbered it */
+ goto error;
+ }
+
+ if ( d->st_dev == dd->st_dev )
+ { /* not crossing a mount point */
+ if ( d->st_ino == dd->st_ino )
+ { /* root directory */
+ dname = "";
+ goto append;
+ }
+
+ do
+ if ( (dir = readdir( dirp )) == NULL )
+ {
+ (void)closedir( dirp );
+ errno = ENOENT; /* missing entry */
+ goto error;
+ }
+ while ( dir->d_ino != d->st_ino );
+ }
+ else { /* crossing a mount point */
+ struct stat t; /* info re. test entry */
+ char name[sizeof dotdots + 1 + NAME_MAX];
+
+ (void)strcpy( name, dotdot );
+ dname = &name[strlen( name )];
+ *dname++ = '/';
+
+ do {
+ if ( (dir = readdir( dirp )) == NULL )
+ {
+ (void)closedir( dirp );
+ errno = ENOENT; /* missing entry */
+ goto error;
+ }
+
+ (void)strcpy( dname, dir->d_name );
+ /* must fit if NAME_MAX is not a lie */
+ }
+ while ( stat( name, &t ) != 0
+ || t.st_ino != d->st_ino
+ || t.st_dev != d->st_dev
+ );
+ }
+
+ dname = dir->d_name;
+
+ /* append "/" and reversed dname string onto buffer */
+ append:
+ if ( endp != buffer /* avoid trailing / in final name */
+ || dname[0] == '\0' /* but allow "/" when CWD is root */
+ )
+ *endp++ = '/';
+
+ {
+ register char *app; /* traverses dname string */
+
+ for ( app = dname; *app != '\0'; ++app )
+ ;
+
+ if ( app - dname >= bufend - endp )
+ {
+ (void)closedir( dirp );
+ errno = ERANGE; /* won't fit allotted space */
+ goto error;
+ }
+
+ while ( app != dname )
+ *endp++ = *--app;
+ }
+
+ (void)closedir( dirp );
+
+ if ( dname[0] == '\0' ) /* reached root; wrap it up */
+ {
+ register char *startp; /* -> buffer[.] */
+
+ *endp = '\0'; /* plant null terminator */
+
+ /* straighten out reversed pathname string */
+ for ( startp = buffer; --endp > startp; ++startp )
+ {
+ char temp = *endp;
+
+ *endp = *startp;
+ *startp = temp;
+ }
+
+ errno = serrno; /* restore entry errno */
+ /* XXX -- if buf==NULL, realloc here? */
+ return buffer;
+ }
+ }
+
+ errno = ENOMEM; /* actually, algorithm failure */
+
+ error:
+ if ( buf == NULL )
+ free( (pointer)buffer );
+
+ return NULL;
+ }
+
diff --git a/dmake/unix/solaris/gnu/config.mk b/dmake/unix/solaris/gnu/config.mk
new file mode 100644
index 000000000000..f6f4f2c68cbc
--- /dev/null
+++ b/dmake/unix/solaris/gnu/config.mk
@@ -0,0 +1,8 @@
+# This is the Solaris gcc configuration file for DMAKE
+# It modifies the value of CC to be gcc
+#
+
+CC = gcc
+
+# disable a gcc bug when compiling runargv.c
+runargv.o ?= CFLAGS += -g
diff --git a/dmake/unix/solaris/gnu/make.sh b/dmake/unix/solaris/gnu/make.sh
new file mode 100644
index 000000000000..10a50a837dfa
--- /dev/null
+++ b/dmake/unix/solaris/gnu/make.sh
@@ -0,0 +1,64 @@
+mkdir objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O infer.c
+mv infer.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O make.c
+mv make.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O stat.c
+mv stat.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O expand.c
+mv expand.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O dmstring.c
+mv dmstring.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O hash.c
+mv hash.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O dag.c
+mv dag.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O dmake.c
+mv dmake.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O path.c
+mv path.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O imacs.c
+mv imacs.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O sysintf.c
+mv sysintf.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O parse.c
+mv parse.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O getinp.c
+mv getinp.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O quit.c
+mv quit.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O state.c
+mv state.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O dmdump.c
+mv dmdump.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O macparse.c
+mv macparse.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O rulparse.c
+mv rulparse.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O percent.c
+mv percent.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O function.c
+mv function.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O unix/arlib.c
+mv arlib.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O unix/dirbrk.c
+mv dirbrk.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O unix/rmprq.c
+mv rmprq.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O unix/ruletab.c
+mv ruletab.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O -g unix/runargv.c
+mv runargv.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O unix/dcache.c
+mv dcache.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O unix/solaris/tempnam.c
+mv tempnam.o objects
+gcc -c -I. -Iunix -Iunix/solaris -DSolaris -O unix/solaris/getcwd.c
+mv getcwd.o objects
+gcc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o objects/dcache.o objects/tempnam.o objects/getcwd.o
+cp unix/solaris/gnu/template.mk startup/config.mk
diff --git a/dmake/unix/solaris/gnu/public.h b/dmake/unix/solaris/gnu/public.h
new file mode 100644
index 000000000000..01e80862fbbd
--- /dev/null
+++ b/dmake/unix/solaris/gnu/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:35 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/solaris/gnu/template.mk b/dmake/unix/solaris/gnu/template.mk
new file mode 100644
index 000000000000..3f9282027c5c
--- /dev/null
+++ b/dmake/unix/solaris/gnu/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= solaris
+ OSENVIRONMENT *:= gnu
diff --git a/dmake/unix/solaris/make.sh b/dmake/unix/solaris/make.sh
new file mode 100644
index 000000000000..21894778a642
--- /dev/null
+++ b/dmake/unix/solaris/make.sh
@@ -0,0 +1,64 @@
+mkdir objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O infer.c
+mv infer.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O make.c
+mv make.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O stat.c
+mv stat.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O expand.c
+mv expand.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O dmstring.c
+mv dmstring.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O hash.c
+mv hash.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O dag.c
+mv dag.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O dmake.c
+mv dmake.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O path.c
+mv path.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O imacs.c
+mv imacs.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O sysintf.c
+mv sysintf.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O parse.c
+mv parse.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O getinp.c
+mv getinp.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O quit.c
+mv quit.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O state.c
+mv state.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O dmdump.c
+mv dmdump.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O macparse.c
+mv macparse.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O rulparse.c
+mv rulparse.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O percent.c
+mv percent.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O function.c
+mv function.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O unix/arlib.c
+mv arlib.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O unix/dirbrk.c
+mv dirbrk.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O unix/rmprq.c
+mv rmprq.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O unix/ruletab.c
+mv ruletab.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O unix/runargv.c
+mv runargv.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O unix/dcache.c
+mv dcache.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O unix/solaris/tempnam.c
+mv tempnam.o objects
+cc -c -I. -Iunix -Iunix/solaris -DSolaris -O unix/solaris/getcwd.c
+mv getcwd.o objects
+cc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o objects/dcache.o objects/tempnam.o objects/getcwd.o
+cp unix/solaris/template.mk startup/config.mk
diff --git a/dmake/unix/solaris/public.h b/dmake/unix/solaris/public.h
new file mode 100644
index 000000000000..01e80862fbbd
--- /dev/null
+++ b/dmake/unix/solaris/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:35 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/solaris/template.mk b/dmake/unix/solaris/template.mk
new file mode 100644
index 000000000000..233917a6ba92
--- /dev/null
+++ b/dmake/unix/solaris/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= solaris
+ OSENVIRONMENT *:=
diff --git a/dmake/unix/solaris/tempnam.c b/dmake/unix/solaris/tempnam.c
new file mode 100644
index 000000000000..56f23fbe21d4
--- /dev/null
+++ b/dmake/unix/solaris/tempnam.c
@@ -0,0 +1,103 @@
+/* RCS $Id: tempnam.c,v 1.1.1.1 2000-09-22 15:33:35 hr Exp $
+--
+-- SYNOPSIS
+-- tempnam
+--
+-- DESCRIPTION
+-- temp file name generation routines.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/*LINTLIBRARY*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define max(A,B) (((A)<(B))?(B):(A))
+
+extern char *mktemp();
+extern int access();
+
+static char *cpdir();
+static char seed[4]="AAA";
+
+/* BSD stdio.h doesn't define P_tmpdir, so let's do it here */
+#ifndef P_tmpdir
+static char *P_tmpdir = "/tmp";
+#endif
+
+char *
+tempnam(dir, prefix)
+const char *dir; /* use this directory please (if non-NULL) */
+const char *prefix; /* use this (if non-NULL) as filename prefix */
+{
+ register char *p, *q, *tmpdir;
+ int tl=0, dl=0, pl;
+
+ pl = strlen(P_tmpdir);
+
+ if( (tmpdir = getenv("TMPDIR")) != NULL ) tl = strlen(tmpdir);
+ if( dir != NULL ) dl = strlen(dir);
+
+ if( (p = malloc((unsigned)(max(max(dl,tl),pl)+16))) == NULL )
+ return(NULL);
+
+ *p = '\0';
+
+ if( (tl == 0) || (access( cpdir(p, tmpdir), 3) != 0) )
+ if( (dl == 0) || (access( cpdir(p, dir), 3) != 0) )
+ if( access( cpdir(p, P_tmpdir), 3) != 0 )
+ if( access( cpdir(p, "/tmp"), 3) != 0 )
+ return(NULL);
+
+ (void) strcat(p, "/");
+ if(prefix)
+ {
+ *(p+strlen(p)+5) = '\0';
+ (void)strncat(p, prefix, 5);
+ }
+
+ (void)strcat(p, seed);
+ (void)strcat(p, "XXXXXX");
+
+ q = seed;
+ while(*q == 'Z') *q++ = 'A';
+ ++*q;
+
+ if(*mktemp(p) == '\0') return(NULL);
+ return(p);
+}
+
+
+
+static char *
+cpdir(buf, str)
+char *buf;
+char *str;
+{
+ char *p;
+
+ if(str != NULL)
+ {
+ (void) strcpy(buf, str);
+ p = buf - 1 + strlen(buf);
+ if(*p == '/') *p = '\0';
+ }
+
+ return(buf);
+}
diff --git a/dmake/unix/startup.h b/dmake/unix/startup.h
new file mode 100644
index 000000000000..b445a86cecef
--- /dev/null
+++ b/dmake/unix/startup.h
@@ -0,0 +1,27 @@
+/* RCS $Id: startup.h,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- Definition of MAKESTARTUP
+--
+-- DESCRIPTION
+-- Default MAKESTARTUP value defining where dmake locates the
+-- startup file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+"MAKESTARTUP := $(DMAKEROOT)/startup.mk",
diff --git a/dmake/unix/sysintf.h b/dmake/unix/sysintf.h
new file mode 100644
index 000000000000..36bf60c559ee
--- /dev/null
+++ b/dmake/unix/sysintf.h
@@ -0,0 +1,51 @@
+/* RCS $Id: sysintf.h,v 1.1.1.1 2000-09-22 15:33:33 hr Exp $
+--
+-- SYNOPSIS
+-- Interfaces for sysintf.c
+--
+-- DESCRIPTION
+-- Abstractions of functions in sysintf.c
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#define DMSTAT stat
+#define VOID_LCACHE(l,m) (void) void_lcache(l,m)
+#define Hook_std_writes(A)
+#define GETPID getpid()
+#define DMSTRLWR(A,B)
+
+#ifndef S_IFDIR
+#define S_IFDIR 0040000
+#endif
+
+#ifndef S_IFMT
+#define S_IFMT 0170000
+#endif
+
+/*
+** standard C items
+*/
+
+/*
+** DOS interface standard items
+*/
+#define getswitchar() '-'
+
+/*
+** Make parameters
+*/
diff --git a/dmake/unix/sysvr1/config.mk b/dmake/unix/sysvr1/config.mk
new file mode 100644
index 000000000000..d1cd2d8810f5
--- /dev/null
+++ b/dmake/unix/sysvr1/config.mk
@@ -0,0 +1,28 @@
+# This is the SysV R3 UNIX configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+# The following are required sources
+OSDSRC := vfprintf.c
+
+.IF $(OSDSRC)
+ SRC += $(OSDSRC)
+ .SETDIR=$(osrdir) : $(OSDSRC)
+.END
+
+.SOURCE.h : $(osrdir)
+
+# Local configuration modifications for CFLAGS, there's local SysV includes
+# too.
+CFLAGS += -I$(osrdir)
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
diff --git a/dmake/unix/sysvr1/make.sh b/dmake/unix/sysvr1/make.sh
new file mode 100644
index 000000000000..1db251f3361e
--- /dev/null
+++ b/dmake/unix/sysvr1/make.sh
@@ -0,0 +1,62 @@
+mkdir objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O infer.c
+mv infer.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O make.c
+mv make.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O stat.c
+mv stat.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O expand.c
+mv expand.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O dmstring.c
+mv dmstring.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O hash.c
+mv hash.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O dag.c
+mv dag.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O dmake.c
+mv dmake.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O path.c
+mv path.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O imacs.c
+mv imacs.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O sysintf.c
+mv sysintf.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O parse.c
+mv parse.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O getinp.c
+mv getinp.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O quit.c
+mv quit.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O state.c
+mv state.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O dmdump.c
+mv dmdump.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O macparse.c
+mv macparse.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O rulparse.c
+mv rulparse.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O percent.c
+mv percent.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O function.c
+mv function.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O unix/arlib.c
+mv arlib.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O unix/dirbrk.c
+mv dirbrk.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O unix/rmprq.c
+mv rmprq.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O unix/ruletab.c
+mv ruletab.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O unix/runargv.c
+mv runargv.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O unix/dcache.c
+mv dcache.o objects
+cc -c -I. -Iunix -Iunix/sysvr1 -O unix/sysvr1/vfprintf.c
+mv vfprintf.o objects
+cc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o objects/dcache.o objects/vfprintf.o
+cp unix/sysvr1/template.mk startup/config.mk
diff --git a/dmake/unix/sysvr1/public.h b/dmake/unix/sysvr1/public.h
new file mode 100644
index 000000000000..01e80862fbbd
--- /dev/null
+++ b/dmake/unix/sysvr1/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:35 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/sysvr1/putenv.c b/dmake/unix/sysvr1/putenv.c
new file mode 100644
index 000000000000..1453852710c2
--- /dev/null
+++ b/dmake/unix/sysvr1/putenv.c
@@ -0,0 +1,78 @@
+/* RCS $Id: putenv.c,v 1.1.1.1 2000-09-22 15:33:35 hr Exp $
+--
+-- SYNOPSIS
+-- My own putenv for BSD like systems.
+--
+-- DESCRIPTION
+-- This originally came from MKS, but I rewrote it to fix a bug with
+-- replacing existing strings, probably never happened but the code
+-- was wrong nonetheless.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <stdio.h>
+#include <string.h>
+
+int
+putenv( str )/*
+===============
+ Take a string of the form NAME=value and stick it into the environment.
+ We do this by allocating a new set of pointers if we have to add a new
+ string and by replacing an existing pointer if the value replaces the value
+ of an existing string. */
+char *str;
+{
+ extern char **environ; /* The current environment. */
+ static char **ourenv = NULL; /* A new environment */
+ register char **p;
+ register char *q;
+ int size;
+
+ /* First search the current environment and see if we can replace a
+ * string. */
+ for( p=environ; *p; p++ ) {
+ register char *s = str;
+
+ for( q = *p; *q && *s && *s == *q; q++, s++ )
+ if( *s == '=' ) {
+ *p = str;
+ return(0); /* replaced it so go away */
+ }
+ }
+
+ /* Ok, can't replace a string so need to grow the environment. */
+ size = p - environ + 2; /* size of new environment */
+ /* size of old is size-1 */
+
+ /* It's the first time, so allocate a new environment since we don't know
+ * where the old one is comming from. */
+ if( ourenv == NULL ) {
+ if( (ourenv = (char **) malloc( sizeof(char *)*size )) == NULL )
+ return(1);
+
+ memcpy( (char *)ourenv, (char *)environ, (size-2)*sizeof(char *) );
+ }
+ else if( (ourenv = (char **)realloc( ourenv, size*sizeof(char *))) == NULL )
+ return(1);
+
+ ourenv[--size] = NULL;
+ ourenv[--size] = str;
+
+ environ = ourenv;
+ return(0);
+}
diff --git a/dmake/unix/sysvr1/stdlib.h b/dmake/unix/sysvr1/stdlib.h
new file mode 100644
index 000000000000..3b612c2fd601
--- /dev/null
+++ b/dmake/unix/sysvr1/stdlib.h
@@ -0,0 +1,44 @@
+/* RCS $Id: stdlib.h,v 1.1.1.1 2000-09-22 15:33:35 hr Exp $
+--
+-- SYNOPSIS
+-- stdlib interface
+--
+-- DESCRIPTION
+-- Specially needed pieces of interface to the standard C lib.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _STDLIB_INCLUDED_
+#define _STDLIB_INCLUDED_
+
+extern /*GOTO*/ _exit();
+extern /*GOTO*/ exit();
+extern /*GOTO*/ abort();
+extern int system();
+extern char *getenv();
+extern char *calloc();
+extern char *malloc();
+extern char *realloc();
+extern free();
+extern int errno;
+
+#ifndef EIO
+# include <errno.h>
+#endif
+
+#endif /* _STDLIB_INCLUDED_ */
diff --git a/dmake/unix/sysvr1/template.mk b/dmake/unix/sysvr1/template.mk
new file mode 100644
index 000000000000..4eb40febb3a1
--- /dev/null
+++ b/dmake/unix/sysvr1/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= sysvr1
+ OSENVIRONMENT *:=
diff --git a/dmake/unix/sysvr1/time.h b/dmake/unix/sysvr1/time.h
new file mode 100644
index 000000000000..3b3dfac5684f
--- /dev/null
+++ b/dmake/unix/sysvr1/time.h
@@ -0,0 +1,32 @@
+/* RCS $Id: time.h,v 1.1.1.1 2000-09-22 15:33:35 hr Exp $
+--
+-- SYNOPSIS
+-- time_t
+--
+-- DESCRIPTION
+-- Properly define time_t.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef TIME_h
+#define TIME_h
+
+typedef long time_t; /* this is the thing we use */
+
+#endif TIME_h
+
diff --git a/dmake/unix/sysvr1/vfprintf.c b/dmake/unix/sysvr1/vfprintf.c
new file mode 100644
index 000000000000..1d24a1c19b08
--- /dev/null
+++ b/dmake/unix/sysvr1/vfprintf.c
@@ -0,0 +1,58 @@
+/* From:
+ * John Limpert johnl@gronk.UUCP uunet!n3dmc!gronk!johnl
+ */
+
+#include <stdio.h>
+#include <varargs.h>
+
+#ifndef BUFSIZ
+#include <stdio.h>
+#endif
+
+#ifndef va_dcl
+#include <varargs.h>
+#endif
+
+int
+vsprintf(str, fmt, ap)
+ char *str, *fmt;
+ va_list ap;
+{
+ FILE f;
+ int len;
+
+ f._flag = _IOWRT+_IOMYBUF;
+ f._ptr = (char *)str; /* My copy of BSD stdio.h has this as (char *)
+ * with a comment that it should be
+ * (unsigned char *). Since this code is
+ * intended for use on a vanilla BSD system,
+ * we'll stick with (char *) for now.
+ */
+ f._cnt = 32767;
+ len = _doprnt(fmt, ap, &f);
+ *f._ptr = 0;
+ return (len);
+}
+
+int
+vfprintf(iop, fmt, ap)
+ FILE *iop;
+ char *fmt;
+ va_list ap;
+{
+ int len;
+
+ len = _doprnt(fmt, ap, iop);
+ return (ferror(iop) ? EOF : len);
+}
+
+int
+vprintf(fmt, ap)
+ char *fmt;
+ va_list ap;
+{
+ int len;
+
+ len = _doprnt(fmt, ap, stdout);
+ return (ferror(stdout) ? EOF : len);
+}
diff --git a/dmake/unix/sysvr3/config.mk b/dmake/unix/sysvr3/config.mk
new file mode 100644
index 000000000000..75bcf3c2a211
--- /dev/null
+++ b/dmake/unix/sysvr3/config.mk
@@ -0,0 +1,27 @@
+# This is the SysV R3 UNIX configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+# The following are required sources
+OSDSRC :=
+.IF $(OSDSRC)
+ SRC += $(OSDSRC)
+ .SETDIR=$(osrdir) : $(OSDSRC)
+.END
+
+.SOURCE.h : $(osrdir)
+
+# Local configuration modifications for CFLAGS, there's local SysV includes
+# too.
+CFLAGS += -I$(osrdir)
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
diff --git a/dmake/unix/sysvr3/gnu/public.h b/dmake/unix/sysvr3/gnu/public.h
new file mode 100644
index 000000000000..d5c3111d1345
--- /dev/null
+++ b/dmake/unix/sysvr3/gnu/public.h
@@ -0,0 +1,162 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:35 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+int Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+int Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/sysvr3/make.sh b/dmake/unix/sysvr3/make.sh
new file mode 100644
index 000000000000..505670f8b708
--- /dev/null
+++ b/dmake/unix/sysvr3/make.sh
@@ -0,0 +1,60 @@
+mkdir objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O infer.c
+mv infer.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O make.c
+mv make.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O stat.c
+mv stat.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O expand.c
+mv expand.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O dmstring.c
+mv dmstring.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O hash.c
+mv hash.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O dag.c
+mv dag.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O dmake.c
+mv dmake.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O path.c
+mv path.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O imacs.c
+mv imacs.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O sysintf.c
+mv sysintf.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O parse.c
+mv parse.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O getinp.c
+mv getinp.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O quit.c
+mv quit.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O state.c
+mv state.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O dmdump.c
+mv dmdump.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O macparse.c
+mv macparse.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O rulparse.c
+mv rulparse.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O percent.c
+mv percent.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O function.c
+mv function.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O unix/arlib.c
+mv arlib.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O unix/dirbrk.c
+mv dirbrk.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O unix/rmprq.c
+mv rmprq.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O unix/ruletab.c
+mv ruletab.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O unix/runargv.c
+mv runargv.o objects
+gcc -c -I. -Iunix -Iunix/sysvr3 -O unix/dcache.c
+mv dcache.o objects
+gcc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o objects/dcache.o
+cp unix/sysvr3/template.mk startup/config.mk
diff --git a/dmake/unix/sysvr3/public.h b/dmake/unix/sysvr3/public.h
new file mode 100644
index 000000000000..01e80862fbbd
--- /dev/null
+++ b/dmake/unix/sysvr3/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:35 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/sysvr3/pwd/config.mk b/dmake/unix/sysvr3/pwd/config.mk
new file mode 100644
index 000000000000..86c535a64c1d
--- /dev/null
+++ b/dmake/unix/sysvr3/pwd/config.mk
@@ -0,0 +1,20 @@
+# This is the Sys VR3 PWD configuration file. It configures SysvR3 unix
+# versions of dmake to use a provided version of getcwd rather than the
+# standard library version that uses popen to capture the output of pwd.
+#
+
+osredir := $(OS)$(DIRSEPSTR)$(OSRELEASE)$(DIRSEPSTR)$(OSENVIRONMENT)
+
+# The following are required sources
+OSRESRC := getcwd.c
+
+.IF $(OSRESRC)
+ SRC += $(OSRESRC)
+ .SETDIR=$(osredir) : $(OSRESRC)
+.END
+
+.SOURCE.h : $(osredir)
+
+# Local configuration modifications for CFLAGS, there's local SysV includes
+# too.
+CFLAGS += -I$(osredir)
diff --git a/dmake/unix/sysvr3/pwd/getcwd.c b/dmake/unix/sysvr3/pwd/getcwd.c
new file mode 100644
index 000000000000..f2359bcc795b
--- /dev/null
+++ b/dmake/unix/sysvr3/pwd/getcwd.c
@@ -0,0 +1,231 @@
+/*
+ getcwd -- get pathname of current working directory
+
+ public-domain implementation
+
+ last edit: 03-Nov-1990 Gwyn@BRL.MIL
+
+ complies with the following standards:
+ IEEE Std 1003.1-1988
+ SVID Issue 3
+ X/Open Portability Guide Issue 2 (when "XPG2" is defined)
+ X/Open Portability Guide Issue 3
+
+ This implementation of getcwd() can be used to replace the UNIX
+ System V library routine (which uses popen() to capture the output of
+ the "pwd" command). Once that is done, "pwd" can be reimplemented as
+ just puts(getcwd((char*)0,0)), assuming "XPG2" is defined below.
+
+ This implementation depends on every directory having entries for
+ "." and "..". It also depends on the internals of the <dirent.h>
+ data structures to some degree.
+
+ I considered using chdir() to ascend the hierarchy, followed by a
+ final chdir() to the path being returned by getcwd() to restore the
+ location, but decided that error recovery was too difficult that way.
+ The algorithm I settled on was inspired by my rewrite of the "pwd"
+ utility, combined with the dotdots[] array trick from the SVR2 shell.
+*/
+#define XPG2 /* define to support obsolete XPG2-mandated feature */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef M_XENIX
+# include <sys/ndir.h>
+# define dirent direct
+#else
+# include <dirent.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+
+typedef char *pointer; /* (void *) if you have it */
+
+extern void free();
+extern pointer malloc();
+extern int fstat(), stat();
+
+extern int errno; /* normally done by <errno.h> */
+
+#ifndef NULL
+#define NULL 0 /* amorphous null pointer constant */
+#endif
+
+#ifndef NAME_MAX
+#define NAME_MAX 255 /* maximum directory entry size */
+#endif
+
+
+char *
+getcwd( buf, size ) /* returns pointer to CWD pathname */
+ char *buf; /* where to put name (NULL to malloc) */
+ int size; /* size of buf[] or malloc()ed memory */
+ {
+ static char dotdots[] =
+"../../../../../../../../../../../../../../../../../../../../../../../../../..";
+ char *dotdot; /* -> dotdots[.], right to left */
+ DIR *dirp; /* -> parent directory stream */
+ struct dirent *dir; /* -> directory entry */
+ struct stat stat1,
+ stat2; /* info from stat() */
+ struct stat *d = &stat1; /* -> info about "." */
+ struct stat *dd = &stat2; /* -> info about ".." */
+ register char *buffer; /* local copy of buf, or malloc()ed */
+ char *bufend; /* -> buffer[size] */
+ register char *endp; /* -> end of reversed string */
+ register char *dname; /* entry name ("" for root) */
+ int serrno = errno; /* save entry errno */
+
+ if ( buf != NULL && size <= 0
+#ifndef XPG2
+ || buf == NULL
+#endif
+ ) {
+ errno = EINVAL; /* invalid argument */
+ return NULL;
+ }
+
+ buffer = buf;
+#ifdef XPG2
+ if ( buf == NULL /* wants us to malloc() the string */
+ && (buffer = (char *) malloc( (unsigned) size )) == NULL
+ /* XXX -- actually should probably not pay attention to "size" arg */
+ ) {
+ errno = ENOMEM; /* cannot malloc() specified size */
+ return NULL;
+ }
+#endif
+
+ if ( stat( ".", dd ) != 0 ) /* prime the pump */
+ goto error; /* errno already set */
+
+ endp = buffer; /* initially, empty string */
+ bufend = &buffer[size];
+
+ for ( dotdot = &dotdots[sizeof dotdots]; dotdot != dotdots; )
+ {
+ dotdot -= 3; /* include one more "/.." section */
+ /* (first time is actually "..") */
+
+ /* swap stat() info buffers */
+ {
+ register struct stat *temp = d;
+
+ d = dd; /* new current dir is old parent dir */
+ dd = temp;
+ }
+
+ if ( (dirp = opendir( dotdot )) == NULL ) /* new parent */
+ goto error; /* errno already set */
+
+ if ( fstat( dirp->dd_fd, dd ) != 0 )
+ {
+ serrno = errno; /* set by fstat() */
+ (void)closedir( dirp );
+ errno = serrno; /* in case closedir() clobbered it */
+ goto error;
+ }
+
+ if ( d->st_dev == dd->st_dev )
+ { /* not crossing a mount point */
+ if ( d->st_ino == dd->st_ino )
+ { /* root directory */
+ dname = "";
+ goto append;
+ }
+
+ do
+ if ( (dir = readdir( dirp )) == NULL )
+ {
+ (void)closedir( dirp );
+ errno = ENOENT; /* missing entry */
+ goto error;
+ }
+ while ( dir->d_ino != d->st_ino );
+ }
+ else { /* crossing a mount point */
+ struct stat t; /* info re. test entry */
+ char name[sizeof dotdots + 1 + NAME_MAX];
+
+ (void)strcpy( name, dotdot );
+ dname = &name[strlen( name )];
+ *dname++ = '/';
+
+ do {
+ if ( (dir = readdir( dirp )) == NULL )
+ {
+ (void)closedir( dirp );
+ errno = ENOENT; /* missing entry */
+ goto error;
+ }
+
+ (void)strcpy( dname, dir->d_name );
+ /* must fit if NAME_MAX is not a lie */
+ }
+ while ( stat( name, &t ) != 0
+ || t.st_ino != d->st_ino
+ || t.st_dev != d->st_dev
+ );
+ }
+
+ dname = dir->d_name;
+
+ /* append "/" and reversed dname string onto buffer */
+ append:
+ if ( endp != buffer /* avoid trailing / in final name */
+ || dname[0] == '\0' /* but allow "/" when CWD is root */
+ )
+ *endp++ = '/';
+
+ {
+ register char *app; /* traverses dname string */
+
+ for ( app = dname; *app != '\0'; ++app )
+ ;
+
+ if ( app - dname >= bufend - endp )
+ {
+ (void)closedir( dirp );
+ errno = ERANGE; /* won't fit allotted space */
+ goto error;
+ }
+
+ while ( app != dname )
+ *endp++ = *--app;
+ }
+
+ (void)closedir( dirp );
+
+ if ( dname[0] == '\0' ) /* reached root; wrap it up */
+ {
+ register char *startp; /* -> buffer[.] */
+
+ *endp = '\0'; /* plant null terminator */
+
+ /* straighten out reversed pathname string */
+ for ( startp = buffer; --endp > startp; ++startp )
+ {
+ char temp = *endp;
+
+ *endp = *startp;
+ *startp = temp;
+ }
+
+ errno = serrno; /* restore entry errno */
+ /* XXX -- if buf==NULL, realloc here? */
+ return buffer;
+ }
+ }
+
+ errno = ENOMEM; /* actually, algorithm failure */
+
+ error:
+ if ( buf == NULL )
+ free( (pointer)buffer );
+
+ return NULL;
+ }
+
diff --git a/dmake/unix/sysvr3/pwd/make.sh b/dmake/unix/sysvr3/pwd/make.sh
new file mode 100644
index 000000000000..1f57569f61df
--- /dev/null
+++ b/dmake/unix/sysvr3/pwd/make.sh
@@ -0,0 +1,62 @@
+mkdir objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O infer.c
+mv infer.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O make.c
+mv make.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O stat.c
+mv stat.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O expand.c
+mv expand.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O dmstring.c
+mv dmstring.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O hash.c
+mv hash.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O dag.c
+mv dag.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O dmake.c
+mv dmake.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O path.c
+mv path.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O imacs.c
+mv imacs.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O sysintf.c
+mv sysintf.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O parse.c
+mv parse.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O getinp.c
+mv getinp.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O quit.c
+mv quit.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O state.c
+mv state.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O dmdump.c
+mv dmdump.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O macparse.c
+mv macparse.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O rulparse.c
+mv rulparse.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O percent.c
+mv percent.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O function.c
+mv function.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O unix/arlib.c
+mv arlib.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O unix/dirbrk.c
+mv dirbrk.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O unix/rmprq.c
+mv rmprq.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O unix/ruletab.c
+mv ruletab.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O unix/runargv.c
+mv runargv.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O unix/dcache.c
+mv dcache.o objects
+cc -c -I. -Iunix -Iunix/sysvr3 -Iunix/sysvr3/pwd -O unix/sysvr3/pwd/getcwd.c
+mv getcwd.o objects
+cc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o objects/dcache.o objects/getcwd.o
+cp unix/sysvr3/pwd/template.mk startup/config.mk
diff --git a/dmake/unix/sysvr3/pwd/public.h b/dmake/unix/sysvr3/pwd/public.h
new file mode 100644
index 000000000000..ea923dad37d1
--- /dev/null
+++ b/dmake/unix/sysvr3/pwd/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/sysvr3/pwd/template.mk b/dmake/unix/sysvr3/pwd/template.mk
new file mode 100644
index 000000000000..fa6b4aa6bd1b
--- /dev/null
+++ b/dmake/unix/sysvr3/pwd/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= sysvr3
+ OSENVIRONMENT *:= pwd
diff --git a/dmake/unix/sysvr3/stdlib.h b/dmake/unix/sysvr3/stdlib.h
new file mode 100644
index 000000000000..077123d5494f
--- /dev/null
+++ b/dmake/unix/sysvr3/stdlib.h
@@ -0,0 +1,55 @@
+/* RCS $Id: stdlib.h,v 1.1.1.1 2000-09-22 15:33:35 hr Exp $
+--
+-- SYNOPSIS
+-- stdlib interface
+--
+-- DESCRIPTION
+-- Specially needed pieces of interface to the standard C lib.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _STDLIB_INCLUDED_
+#define _STDLIB_INCLUDED_
+
+#ifndef _AIX
+extern /*GOTO*/ _exit();
+extern /*GOTO*/ exit();
+extern /*GOTO*/ abort();
+extern int system();
+extern char *getenv();
+extern char *calloc();
+extern char *malloc();
+extern char *realloc();
+
+/* The AIX compiler dies on illegal redefinition of free */
+extern free();
+#endif
+
+/* AIX doesn't use NAME_MAX anylonger... */
+#ifdef _AIX
+#include <unistd.h>
+#define NAME_MAX pathconf("/dev/null",_PC_NAME_MAX)
+#endif
+
+extern int errno;
+
+#ifndef EIO
+# include <errno.h>
+#endif
+
+#endif /* _STDLIB_INCLUDED_ */
diff --git a/dmake/unix/sysvr3/template.mk b/dmake/unix/sysvr3/template.mk
new file mode 100644
index 000000000000..3cb518671142
--- /dev/null
+++ b/dmake/unix/sysvr3/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= sysvr3
+ OSENVIRONMENT *:=
diff --git a/dmake/unix/sysvr3/time.h b/dmake/unix/sysvr3/time.h
new file mode 100644
index 000000000000..3b3dfac5684f
--- /dev/null
+++ b/dmake/unix/sysvr3/time.h
@@ -0,0 +1,32 @@
+/* RCS $Id: time.h,v 1.1.1.1 2000-09-22 15:33:35 hr Exp $
+--
+-- SYNOPSIS
+-- time_t
+--
+-- DESCRIPTION
+-- Properly define time_t.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef TIME_h
+#define TIME_h
+
+typedef long time_t; /* this is the thing we use */
+
+#endif TIME_h
+
diff --git a/dmake/unix/sysvr4/config.mk b/dmake/unix/sysvr4/config.mk
new file mode 100644
index 000000000000..6443ff6a91c9
--- /dev/null
+++ b/dmake/unix/sysvr4/config.mk
@@ -0,0 +1,27 @@
+# This is the SysV R4 UNIX configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+# The following are required sources
+OSDSRC :=
+.IF $(OSDSRC)
+ SRC += $(OSDSRC)
+ .SETDIR=$(osrdir) : $(OSDSRC)
+.END
+
+.SOURCE.h : $(osrdir)
+
+# Local configuration modifications for CFLAGS, there's local SysV includes
+# too.
+CFLAGS += -I$(osrdir)
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
diff --git a/dmake/unix/sysvr4/make.sh b/dmake/unix/sysvr4/make.sh
new file mode 100644
index 000000000000..9ab5904422f0
--- /dev/null
+++ b/dmake/unix/sysvr4/make.sh
@@ -0,0 +1,60 @@
+mkdir objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O infer.c
+mv infer.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O make.c
+mv make.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O stat.c
+mv stat.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O expand.c
+mv expand.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O dmstring.c
+mv dmstring.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O hash.c
+mv hash.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O dag.c
+mv dag.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O dmake.c
+mv dmake.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O path.c
+mv path.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O imacs.c
+mv imacs.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O sysintf.c
+mv sysintf.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O parse.c
+mv parse.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O getinp.c
+mv getinp.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O quit.c
+mv quit.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O state.c
+mv state.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O dmdump.c
+mv dmdump.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O macparse.c
+mv macparse.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O rulparse.c
+mv rulparse.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O percent.c
+mv percent.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O function.c
+mv function.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O unix/arlib.c
+mv arlib.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O unix/dirbrk.c
+mv dirbrk.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O unix/rmprq.c
+mv rmprq.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O unix/ruletab.c
+mv ruletab.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O unix/runargv.c
+mv runargv.o objects
+cc -c -I. -Iunix -Iunix/sysvr4 -O unix/dcache.c
+mv dcache.o objects
+cc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o objects/dcache.o
+cp unix/sysvr4/template.mk startup/config.mk
diff --git a/dmake/unix/sysvr4/public.h b/dmake/unix/sysvr4/public.h
new file mode 100644
index 000000000000..ea923dad37d1
--- /dev/null
+++ b/dmake/unix/sysvr4/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/sysvr4/template.mk b/dmake/unix/sysvr4/template.mk
new file mode 100644
index 000000000000..553878268e59
--- /dev/null
+++ b/dmake/unix/sysvr4/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= sysvr4
+ OSENVIRONMENT *:=
diff --git a/dmake/unix/xenix/config.mk b/dmake/unix/xenix/config.mk
new file mode 100644
index 000000000000..a4f8f78f3ee1
--- /dev/null
+++ b/dmake/unix/xenix/config.mk
@@ -0,0 +1,27 @@
+# This is the SysV R3 UNIX configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+# The following are required sources
+OSDSRC :=
+.IF $(OSDSRC)
+ SRC += $(OSDSRC)
+ .SETDIR=$(osrdir) : $(OSDSRC)
+.END
+
+.SOURCE.h : $(osrdir)
+
+# Local configuration modifications for CFLAGS, there's local SysV includes
+# too.
+CFLAGS += -I$(osrdir) -DM_XENIX
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
diff --git a/dmake/unix/xenix/make.sh b/dmake/unix/xenix/make.sh
new file mode 100644
index 000000000000..597936f38061
--- /dev/null
+++ b/dmake/unix/xenix/make.sh
@@ -0,0 +1,60 @@
+mkdir objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O infer.c
+mv infer.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O make.c
+mv make.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O stat.c
+mv stat.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O expand.c
+mv expand.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O dmstring.c
+mv dmstring.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O hash.c
+mv hash.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O dag.c
+mv dag.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O dmake.c
+mv dmake.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O path.c
+mv path.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O imacs.c
+mv imacs.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O sysintf.c
+mv sysintf.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O parse.c
+mv parse.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O getinp.c
+mv getinp.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O quit.c
+mv quit.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O state.c
+mv state.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O dmdump.c
+mv dmdump.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O macparse.c
+mv macparse.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O rulparse.c
+mv rulparse.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O percent.c
+mv percent.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O function.c
+mv function.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O unix/arlib.c
+mv arlib.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O unix/dirbrk.c
+mv dirbrk.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O unix/rmprq.c
+mv rmprq.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O unix/ruletab.c
+mv ruletab.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O unix/runargv.c
+mv runargv.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -O unix/dcache.c
+mv dcache.o objects
+cc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o objects/dcache.o
+cp unix/xenix/template.mk startup/config.mk
diff --git a/dmake/unix/xenix/public.h b/dmake/unix/xenix/public.h
new file mode 100644
index 000000000000..ea923dad37d1
--- /dev/null
+++ b/dmake/unix/xenix/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/xenix/pwd/config.mk b/dmake/unix/xenix/pwd/config.mk
new file mode 100644
index 000000000000..095ff3587a68
--- /dev/null
+++ b/dmake/unix/xenix/pwd/config.mk
@@ -0,0 +1,23 @@
+# This is the Sys VR3 PWD configuration file. It configures SysvR3 unix
+# versions of dmake to use a provided version of getcwd rather than the
+# standard library version that uses popen to capture the output of pwd.
+#
+
+osredir := $(OS)$(DIRSEPSTR)$(OSRELEASE)$(DIRSEPSTR)$(OSENVIRONMENT)
+
+# The following are required sources
+OSRESRC := getcwd.c
+
+.IF $(OSRESRC)
+ SRC += $(OSRESRC)
+ .SETDIR=$(osredir) : $(OSRESRC)
+.END
+
+.SOURCE.h : $(osredir)
+
+# Local configuration modifications for CFLAGS, there's local SysV includes
+# too.
+CFLAGS += -I$(osredir)
+
+# Xenix needs -lx in order to link successfully.
+LDLIBS += -lx
diff --git a/dmake/unix/xenix/pwd/getcwd.c b/dmake/unix/xenix/pwd/getcwd.c
new file mode 100644
index 000000000000..f2359bcc795b
--- /dev/null
+++ b/dmake/unix/xenix/pwd/getcwd.c
@@ -0,0 +1,231 @@
+/*
+ getcwd -- get pathname of current working directory
+
+ public-domain implementation
+
+ last edit: 03-Nov-1990 Gwyn@BRL.MIL
+
+ complies with the following standards:
+ IEEE Std 1003.1-1988
+ SVID Issue 3
+ X/Open Portability Guide Issue 2 (when "XPG2" is defined)
+ X/Open Portability Guide Issue 3
+
+ This implementation of getcwd() can be used to replace the UNIX
+ System V library routine (which uses popen() to capture the output of
+ the "pwd" command). Once that is done, "pwd" can be reimplemented as
+ just puts(getcwd((char*)0,0)), assuming "XPG2" is defined below.
+
+ This implementation depends on every directory having entries for
+ "." and "..". It also depends on the internals of the <dirent.h>
+ data structures to some degree.
+
+ I considered using chdir() to ascend the hierarchy, followed by a
+ final chdir() to the path being returned by getcwd() to restore the
+ location, but decided that error recovery was too difficult that way.
+ The algorithm I settled on was inspired by my rewrite of the "pwd"
+ utility, combined with the dotdots[] array trick from the SVR2 shell.
+*/
+#define XPG2 /* define to support obsolete XPG2-mandated feature */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef M_XENIX
+# include <sys/ndir.h>
+# define dirent direct
+#else
+# include <dirent.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+
+typedef char *pointer; /* (void *) if you have it */
+
+extern void free();
+extern pointer malloc();
+extern int fstat(), stat();
+
+extern int errno; /* normally done by <errno.h> */
+
+#ifndef NULL
+#define NULL 0 /* amorphous null pointer constant */
+#endif
+
+#ifndef NAME_MAX
+#define NAME_MAX 255 /* maximum directory entry size */
+#endif
+
+
+char *
+getcwd( buf, size ) /* returns pointer to CWD pathname */
+ char *buf; /* where to put name (NULL to malloc) */
+ int size; /* size of buf[] or malloc()ed memory */
+ {
+ static char dotdots[] =
+"../../../../../../../../../../../../../../../../../../../../../../../../../..";
+ char *dotdot; /* -> dotdots[.], right to left */
+ DIR *dirp; /* -> parent directory stream */
+ struct dirent *dir; /* -> directory entry */
+ struct stat stat1,
+ stat2; /* info from stat() */
+ struct stat *d = &stat1; /* -> info about "." */
+ struct stat *dd = &stat2; /* -> info about ".." */
+ register char *buffer; /* local copy of buf, or malloc()ed */
+ char *bufend; /* -> buffer[size] */
+ register char *endp; /* -> end of reversed string */
+ register char *dname; /* entry name ("" for root) */
+ int serrno = errno; /* save entry errno */
+
+ if ( buf != NULL && size <= 0
+#ifndef XPG2
+ || buf == NULL
+#endif
+ ) {
+ errno = EINVAL; /* invalid argument */
+ return NULL;
+ }
+
+ buffer = buf;
+#ifdef XPG2
+ if ( buf == NULL /* wants us to malloc() the string */
+ && (buffer = (char *) malloc( (unsigned) size )) == NULL
+ /* XXX -- actually should probably not pay attention to "size" arg */
+ ) {
+ errno = ENOMEM; /* cannot malloc() specified size */
+ return NULL;
+ }
+#endif
+
+ if ( stat( ".", dd ) != 0 ) /* prime the pump */
+ goto error; /* errno already set */
+
+ endp = buffer; /* initially, empty string */
+ bufend = &buffer[size];
+
+ for ( dotdot = &dotdots[sizeof dotdots]; dotdot != dotdots; )
+ {
+ dotdot -= 3; /* include one more "/.." section */
+ /* (first time is actually "..") */
+
+ /* swap stat() info buffers */
+ {
+ register struct stat *temp = d;
+
+ d = dd; /* new current dir is old parent dir */
+ dd = temp;
+ }
+
+ if ( (dirp = opendir( dotdot )) == NULL ) /* new parent */
+ goto error; /* errno already set */
+
+ if ( fstat( dirp->dd_fd, dd ) != 0 )
+ {
+ serrno = errno; /* set by fstat() */
+ (void)closedir( dirp );
+ errno = serrno; /* in case closedir() clobbered it */
+ goto error;
+ }
+
+ if ( d->st_dev == dd->st_dev )
+ { /* not crossing a mount point */
+ if ( d->st_ino == dd->st_ino )
+ { /* root directory */
+ dname = "";
+ goto append;
+ }
+
+ do
+ if ( (dir = readdir( dirp )) == NULL )
+ {
+ (void)closedir( dirp );
+ errno = ENOENT; /* missing entry */
+ goto error;
+ }
+ while ( dir->d_ino != d->st_ino );
+ }
+ else { /* crossing a mount point */
+ struct stat t; /* info re. test entry */
+ char name[sizeof dotdots + 1 + NAME_MAX];
+
+ (void)strcpy( name, dotdot );
+ dname = &name[strlen( name )];
+ *dname++ = '/';
+
+ do {
+ if ( (dir = readdir( dirp )) == NULL )
+ {
+ (void)closedir( dirp );
+ errno = ENOENT; /* missing entry */
+ goto error;
+ }
+
+ (void)strcpy( dname, dir->d_name );
+ /* must fit if NAME_MAX is not a lie */
+ }
+ while ( stat( name, &t ) != 0
+ || t.st_ino != d->st_ino
+ || t.st_dev != d->st_dev
+ );
+ }
+
+ dname = dir->d_name;
+
+ /* append "/" and reversed dname string onto buffer */
+ append:
+ if ( endp != buffer /* avoid trailing / in final name */
+ || dname[0] == '\0' /* but allow "/" when CWD is root */
+ )
+ *endp++ = '/';
+
+ {
+ register char *app; /* traverses dname string */
+
+ for ( app = dname; *app != '\0'; ++app )
+ ;
+
+ if ( app - dname >= bufend - endp )
+ {
+ (void)closedir( dirp );
+ errno = ERANGE; /* won't fit allotted space */
+ goto error;
+ }
+
+ while ( app != dname )
+ *endp++ = *--app;
+ }
+
+ (void)closedir( dirp );
+
+ if ( dname[0] == '\0' ) /* reached root; wrap it up */
+ {
+ register char *startp; /* -> buffer[.] */
+
+ *endp = '\0'; /* plant null terminator */
+
+ /* straighten out reversed pathname string */
+ for ( startp = buffer; --endp > startp; ++startp )
+ {
+ char temp = *endp;
+
+ *endp = *startp;
+ *startp = temp;
+ }
+
+ errno = serrno; /* restore entry errno */
+ /* XXX -- if buf==NULL, realloc here? */
+ return buffer;
+ }
+ }
+
+ errno = ENOMEM; /* actually, algorithm failure */
+
+ error:
+ if ( buf == NULL )
+ free( (pointer)buffer );
+
+ return NULL;
+ }
+
diff --git a/dmake/unix/xenix/pwd/make.sh b/dmake/unix/xenix/pwd/make.sh
new file mode 100644
index 000000000000..e7c02e53ace6
--- /dev/null
+++ b/dmake/unix/xenix/pwd/make.sh
@@ -0,0 +1,62 @@
+mkdir objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O infer.c
+mv infer.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O make.c
+mv make.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O stat.c
+mv stat.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O expand.c
+mv expand.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O dmstring.c
+mv dmstring.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O hash.c
+mv hash.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O dag.c
+mv dag.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O dmake.c
+mv dmake.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O path.c
+mv path.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O imacs.c
+mv imacs.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O sysintf.c
+mv sysintf.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O parse.c
+mv parse.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O getinp.c
+mv getinp.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O quit.c
+mv quit.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O state.c
+mv state.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O dmdump.c
+mv dmdump.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O macparse.c
+mv macparse.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O rulparse.c
+mv rulparse.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O percent.c
+mv percent.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O function.c
+mv function.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O unix/arlib.c
+mv arlib.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O unix/dirbrk.c
+mv dirbrk.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O unix/rmprq.c
+mv rmprq.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O unix/ruletab.c
+mv ruletab.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O unix/runargv.c
+mv runargv.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O unix/dcache.c
+mv dcache.o objects
+cc -c -I. -Iunix -Iunix/xenix -DM_XENIX -Iunix/xenix/pwd -O unix/xenix/pwd/getcwd.c
+mv getcwd.o objects
+cc -O -o dmake objects/infer.o objects/make.o objects/stat.o objects/expand.o \
+objects/dmstring.o objects/hash.o objects/dag.o objects/dmake.o objects/path.o \
+objects/imacs.o objects/sysintf.o objects/parse.o objects/getinp.o \
+objects/quit.o objects/state.o objects/dmdump.o objects/macparse.o \
+objects/rulparse.o objects/percent.o objects/function.o objects/arlib.o \
+objects/dirbrk.o objects/rmprq.o objects/ruletab.o objects/runargv.o objects/dcache.o objects/getcwd.o -lx
+cp unix/xenix/pwd/template.mk startup/config.mk
diff --git a/dmake/unix/xenix/pwd/public.h b/dmake/unix/xenix/pwd/public.h
new file mode 100644
index 000000000000..ea923dad37d1
--- /dev/null
+++ b/dmake/unix/xenix/pwd/public.h
@@ -0,0 +1,164 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+time_t seek_arch ANSI((char *, char *));
+int If_root_path ANSI((char *));
+void Remove_prq ANSI((CELLPTR));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+
+#endif
diff --git a/dmake/unix/xenix/pwd/template.mk b/dmake/unix/xenix/pwd/template.mk
new file mode 100644
index 000000000000..abd4066c347b
--- /dev/null
+++ b/dmake/unix/xenix/pwd/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= xenix
+ OSENVIRONMENT *:= pwd
diff --git a/dmake/unix/xenix/stdlib.h b/dmake/unix/xenix/stdlib.h
new file mode 100644
index 000000000000..fe814c798a0b
--- /dev/null
+++ b/dmake/unix/xenix/stdlib.h
@@ -0,0 +1,50 @@
+/* RCS $Id: stdlib.h,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+--
+-- SYNOPSIS
+-- stdlib interface
+--
+-- DESCRIPTION
+-- Specially needed pieces of interface to the standard C lib.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+
+#ifndef _STDLIB_INCLUDED_
+#define _STDLIB_INCLUDED_
+
+extern /*GOTO*/ _exit();
+extern /*GOTO*/ exit();
+extern /*GOTO*/ abort();
+extern int system();
+extern char *getenv();
+extern char *calloc();
+extern char *malloc();
+extern char *realloc();
+
+#ifndef _AIX
+/* The AIX compiler dies on illegal redefinition of free */
+extern free();
+#endif
+
+extern int errno;
+
+#ifndef EIO
+# include <errno.h>
+#endif
+
+#endif /* _STDLIB_INCLUDED_ */
diff --git a/dmake/unix/xenix/template.mk b/dmake/unix/xenix/template.mk
new file mode 100644
index 000000000000..7ab223fbdb9f
--- /dev/null
+++ b/dmake/unix/xenix/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= unix
+ OSRELEASE *:= xenix
+ OSENVIRONMENT *:=
diff --git a/dmake/unix/xenix/time.h b/dmake/unix/xenix/time.h
new file mode 100644
index 000000000000..c7102cfc18cb
--- /dev/null
+++ b/dmake/unix/xenix/time.h
@@ -0,0 +1,32 @@
+/* RCS $Id: time.h,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+--
+-- SYNOPSIS
+-- time_t
+--
+-- DESCRIPTION
+-- Properly define time_t.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef TIME_h
+#define TIME_h
+
+typedef long time_t; /* this is the thing we use */
+
+#endif TIME_h
+
diff --git a/dmake/vextern.h b/dmake/vextern.h
new file mode 100644
index 000000000000..84ded883d4c7
--- /dev/null
+++ b/dmake/vextern.h
@@ -0,0 +1,107 @@
+/* RCS $Id: vextern.h,v 1.1.1.1 2000-09-22 15:33:26 hr Exp $
+--
+-- SYNOPSIS
+-- Global variable declarations.
+--
+-- DESCRIPTION
+-- Leave _DEFINE_GLOBALS_ undefined and the following declarations
+-- will be defined as global variables, otherwise you get the
+-- external declarations to the same global variables.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* These two are defined in dir/ruletab.c and dir/dirbrk.c, and are always
+ * imported as externals by the other code. Their defining modules do not
+ * #include this file. */
+extern char* DirBrkStr; /* pointer to value of macro DIRBRKSTR */
+extern char** Rule_tab; /* Builtin rules */
+
+#ifndef _DEFINE_GLOBALS_
+#define EXTERN extern
+#else
+#define EXTERN
+#endif
+
+EXTERN int Line_number; /* Current line number in make file parse */
+EXTERN t_attr Glob_attr; /* Global attrs to control global ops */
+EXTERN char* Makedir; /* pointer to macro value for MAKEDIR */
+EXTERN char* Shell; /* pointer to macro value for SHELL */
+EXTERN char* Shell_flags; /* pointer to macro value for SHELLFLAGS */
+EXTERN char* GShell; /* pointer to macro value for GROUPSHELL */
+EXTERN char* GShell_flags; /* pointer to macro value for GROUPFLAGS */
+EXTERN char* Shell_metas; /* pointer to macro value for SHELLMETAS */
+EXTERN char* Grp_suff; /* pointer to macro value for GROUPSUFFIX */
+EXTERN char* DirSepStr; /* pointer to macro value for DIRSEPSTR */
+EXTERN char* Pname; /* dmake process invoke name */
+EXTERN char* Pwd; /* current working dir, value of PWD */
+EXTERN char* Tmd; /* path to directory where dmake started */
+EXTERN char* Keep_state; /* current .KEEP_STATE file */
+EXTERN char* Escape_char; /* Current escape character */
+EXTERN char* LastMacName; /* Last macro successfully parsed */
+EXTERN char* UseDirCache; /* The value of .DIRCACHE */
+EXTERN char* DcacheRespCase; /* TRUE if we are to respect dcache case */
+EXTERN int Target; /* TRUE if target found in makefile */
+EXTERN int If_expand; /* TRUE if calling Expand from getinp.c */
+EXTERN int Suppress_temp_file;/* TRUE if doing a test in _exec_recipe*/
+EXTERN int Readenv; /* TRUE if defining macro from environment*/
+EXTERN int Makemkf; /* TRUE if making makefile(s) */
+EXTERN int Nest_level; /* Nesting level for .IF .ELSE .END ... */
+EXTERN int Prep; /* Value of macro PREP */
+EXTERN int Def_targets; /* TRUE if defining targets */
+EXTERN int Skip_to_eof; /* TRUE if asked to skip to eof on input */
+EXTERN int DynamicNestLevel;/* Value of DYNAMICNESTINGLEVEL macro */
+EXTERN int NameMax; /* The value of NAMEMAX */
+
+
+EXTERN CELLPTR Root; /* Root of the make graph */
+EXTERN CELLPTR Targets; /* Targets in makefile */
+
+EXTERN CELLPTR Current_target; /* cell of current target being made */
+EXTERN int Wait_for_completion;
+EXTERN int Doing_bang;
+EXTERN int Packed_shell; /* TRUE if packed args to use a shell */
+EXTERN int Swap_on_exec; /* TRUE if going to swap on exec call */
+EXTERN int State; /* parser state */
+EXTERN int Group; /* parsing a group recipe ==> TRUE */
+
+/* Command line option flags are defined here. They correspond one-for one
+ * with the flags defined in dmake.c */
+
+EXTERN char *Augmake; /* -A */
+EXTERN char Comment; /* -c */
+EXTERN char Get_env; /* -e or -E */
+EXTERN char* Notabs; /* -B */
+EXTERN int Continue; /* -k */
+EXTERN int Force; /* -u */
+EXTERN int Listing; /* -p */
+EXTERN int Rules; /* -r */
+EXTERN int Trace; /* -n */
+EXTERN int Touch; /* -t */
+EXTERN int Check; /* -q */
+EXTERN uint16 Verbose; /* -v */
+EXTERN int Microsoft; /* -M */
+EXTERN int Transitive; /* -T */
+EXTERN int No_exec; /* -X */
+
+EXTERN HASHPTR Defs[HASH_TABLE_SIZE];
+EXTERN HASHPTR Macs[HASH_TABLE_SIZE];
+
+EXTERN char *Buffer; /* a general purpose buffer */
+EXTERN int Buffer_size;
+EXTERN int Max_proclmt; /* limit of max # of conc procs */
+EXTERN int Max_proc; /* max # of conc procs */
diff --git a/dmake/win95/borland/bcc50/config.h b/dmake/win95/borland/bcc50/config.h
new file mode 100644
index 000000000000..c39a4816f54f
--- /dev/null
+++ b/dmake/win95/borland/bcc50/config.h
@@ -0,0 +1,44 @@
+/* RCS $Id: config.h,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+--
+-- SYNOPSIS
+-- Configurarion include file.
+--
+-- DESCRIPTION
+-- There is one of these for each specific machine configuration.
+-- It can be used to further tweek the machine specific sources
+-- so that they compile.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* define this for configurations that don't have the coreleft function
+ * so that the code compiles. To my knowledge coreleft exists only on
+ * Turbo C, but it is needed here since the function is used in many debug
+ * macros. */
+/*#define coreleft() 0L*/
+extern unsigned int coreleft();
+
+#define SIGQUIT SIGBREAK /* turbo C doesn't understand SIGQUIT */
+
+/* Turbo-C understands const declarations. */
+#define CONST const
+
+/* a small problem with pointer to voids on some unix machines needs this */
+#define PVOID void *
+
+/* Borland redefined the environment variable, sigh */
+#define environ _environ
diff --git a/dmake/win95/borland/bcc50/config.mk b/dmake/win95/borland/bcc50/config.mk
new file mode 100644
index 000000000000..b63cae1c1977
--- /dev/null
+++ b/dmake/win95/borland/bcc50/config.mk
@@ -0,0 +1,14 @@
+# Definition of macros for library, and C startup code.
+osedir = $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)
+
+# Change the CCROOT variable to reflect the installation directory of your
+# C++ compiler.
+.IMPORT .IGNORE : CCVER
+
+CCVER *:= c:/cc/borland/$(OSENVIRONMENT)
+
+# Definitions for compiles and links
+CSTARTUP = $(CCVER)/lib/c0x32.obj
+LDLIBS = $(CCVER)/lib/cw32 $(CCVER)/lib/import32
+
+CFLAGS += -A- -w-pro -I$(osedir)
diff --git a/dmake/win95/borland/bcc50/lib.rsp b/dmake/win95/borland/bcc50/lib.rsp
new file mode 100644
index 000000000000..6b6ffb39dc4e
--- /dev/null
+++ b/dmake/win95/borland/bcc50/lib.rsp
@@ -0,0 +1,2 @@
+c:\cc\borland\bcc50\lib\cw32+
+c:\cc\borland\bcc50\lib\import32
diff --git a/dmake/win95/borland/bcc50/mk.bat b/dmake/win95/borland/bcc50/mk.bat
new file mode 100755
index 000000000000..1c77b3799df5
--- /dev/null
+++ b/dmake/win95/borland/bcc50/mk.bat
@@ -0,0 +1,96 @@
+md objects
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 infer.c
+copy infer.obj objects
+del infer.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 make.c
+copy make.obj objects
+del make.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 stat.c
+copy stat.obj objects
+del stat.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 expand.c
+copy expand.obj objects
+del expand.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 dmstring.c
+copy dmstring.obj objects
+del dmstring.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 hash.c
+copy hash.obj objects
+del hash.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 dag.c
+copy dag.obj objects
+del dag.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 dmake.c
+copy dmake.obj objects
+del dmake.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 path.c
+copy path.obj objects
+del path.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 imacs.c
+copy imacs.obj objects
+del imacs.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 sysintf.c
+copy sysintf.obj objects
+del sysintf.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 parse.c
+copy parse.obj objects
+del parse.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 getinp.c
+copy getinp.obj objects
+del getinp.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 quit.c
+copy quit.obj objects
+del quit.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 state.c
+copy state.obj objects
+del state.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 dmdump.c
+copy dmdump.obj objects
+del dmdump.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 macparse.c
+copy macparse.obj objects
+del macparse.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 rulparse.c
+copy rulparse.obj objects
+del rulparse.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 percent.c
+copy percent.obj objects
+del percent.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 function.c
+copy function.obj objects
+del function.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 win95\dchdir.c
+copy dchdir.obj objects
+del dchdir.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 win95\switchar.c
+copy switchar.obj objects
+del switchar.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 msdos\dstrlwr.c
+copy dstrlwr.obj objects
+del dstrlwr.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 msdos\arlib.c
+copy arlib.obj objects
+del arlib.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 msdos\dirbrk.c
+copy dirbrk.obj objects
+del dirbrk.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 win95\borland\tempnam.c
+copy tempnam.obj objects
+del tempnam.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 win95\borland\ruletab.c
+copy ruletab.obj objects
+del ruletab.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 win95\borland\utime.c
+copy utime.obj objects
+del utime.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 win95\borland\runargv.c
+copy runargv.obj objects
+del runargv.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 unix\dcache.c
+copy dcache.obj objects
+del dcache.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 unix\rmprq.c
+copy rmprq.obj objects
+del rmprq.obj
+tlink32 @win95\borland\bcc50\obj.rsp,dmake.exe,NUL.MAP,@win95\borland\bcc50\lib.rsp
+copy win95\borland\bcc50\template.mk startup\config.mk
diff --git a/dmake/win95/borland/bcc50/obj.rsp b/dmake/win95/borland/bcc50/obj.rsp
new file mode 100644
index 000000000000..0301270860f0
--- /dev/null
+++ b/dmake/win95/borland/bcc50/obj.rsp
@@ -0,0 +1,32 @@
+c:\cc\borland\bcc50\lib\c0x32.obj+
+objects\infer.obj+
+objects\make.obj+
+objects\stat.obj+
+objects\expand.obj+
+objects\dmstring.obj+
+objects\hash.obj+
+objects\dag.obj+
+objects\dmake.obj+
+objects\path.obj+
+objects\imacs.obj+
+objects\sysintf.obj+
+objects\parse.obj+
+objects\getinp.obj+
+objects\quit.obj+
+objects\state.obj+
+objects\dmdump.obj+
+objects\macparse.obj+
+objects\rulparse.obj+
+objects\percent.obj+
+objects\function.obj+
+objects\dchdir.obj+
+objects\switchar.obj+
+objects\dstrlwr.obj+
+objects\arlib.obj+
+objects\dirbrk.obj+
+objects\tempnam.obj+
+objects\ruletab.obj+
+objects\utime.obj+
+objects\runargv.obj+
+objects\dcache.obj+
+objects\rmprq.obj
diff --git a/dmake/win95/borland/bcc50/public.h b/dmake/win95/borland/bcc50/public.h
new file mode 100644
index 000000000000..26d5871102a4
--- /dev/null
+++ b/dmake/win95/borland/bcc50/public.h
@@ -0,0 +1,167 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+int dchdir ANSI((char *));
+void dstrlwr ANSI((char *, char *));
+time_t seek_arch ANSI((char*, char*));
+int touch_arch ANSI((char*, char*));
+int If_root_path ANSI((char *));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+void Remove_prq ANSI((CELLPTR));
+
+#endif
diff --git a/dmake/win95/borland/bcc50/template.mk b/dmake/win95/borland/bcc50/template.mk
new file mode 100644
index 000000000000..b5095c40ce2a
--- /dev/null
+++ b/dmake/win95/borland/bcc50/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= win95
+ OSRELEASE *:= borland
+ OSENVIRONMENT *:= bcc50
diff --git a/dmake/win95/borland/config.mk b/dmake/win95/borland/config.mk
new file mode 100644
index 000000000000..8d5d69df5bd7
--- /dev/null
+++ b/dmake/win95/borland/config.mk
@@ -0,0 +1,51 @@
+# This is the Turbo C++ 2.0 DOS configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+# OS specific sources
+OSR_SRC += tempnam.c ruletab.c
+DOS_SRC += runargv.c rmprq.c
+
+SRC += $(OSR_SRC) $(DOS_SRC)
+.SOURCE.h : $(osrdir)
+
+# Local configuration modifications for CFLAGS. Make sure your turboc.cfg
+# file contains a -D__STDC__=1 and -DM_I86=1, if not then uncomment the line
+# below!
+#CFLAGS += -DM_I86=1 -D__STDC__=1
+
+# You can get a smaller executable still, buy adding a -1 to the list of
+# flags below, but then you can't run this on an 8086/88 cpu.
+#CFLAGS += -1
+CFLAGS += -I$(osrdir) -d -O -N- -w-nod
+ASFLAGS += -t -mx $(S_$(MODEL))
+
+LDOBJS = $(CSTARTUP) $(OBJDIR)/{$(<:f)}
+LDARGS = $(LDHEAD) @$(LDTMPOBJ),$(TARGET),NUL.MAP$(LDTAIL)
+LDTAIL = $(_libs)$(LDFLAGS:s/ //)
+_libs = $(!null,$(LDLIBS) ,@$(LDTMPLIB))
+LDTMPOBJ = $(mktmp,,$(DIVFILE) $(LDOBJS:s,/,\\,:t"+\n")\n)
+LDTMPLIB = $(mktmp,,$(DIVFILE) $(LDLIBS:s,/,\\,:t"+\n")\n)
+
+# Debugging information for Turbo-C
+DB_CFLAGS += -v
+DB_LDFLAGS += /v
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
+
+.SETDIR=$(osrdir) : $(OSR_SRC)
+.SETDIR=msdos : $(DOS_SRC)
+
+S_s = -dmsmall
+S_m = -dmmedium
+S_c = -dmcompact
+S_l = -dmlarge
diff --git a/dmake/win95/borland/ruletab.c b/dmake/win95/borland/ruletab.c
new file mode 100644
index 000000000000..04aab804b587
--- /dev/null
+++ b/dmake/win95/borland/ruletab.c
@@ -0,0 +1,44 @@
+/* RCS $Id: ruletab.c,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+--
+-- SYNOPSIS
+-- Default initial configuration of dmake.
+--
+-- DESCRIPTION
+-- Define here the initial set of rules that are defined before
+-- dmake performs any processing.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* These are control macros for dmake that MUST be defined at some point
+ * if they are NOT dmake will not work! These are default definitions. They
+ * may be overridden inside the .STARTUP makefile, they are here
+ * strictly so that dmake can parse the STARTUP makefile */
+
+#include <stdio.h>
+
+static char *_rules[] = {
+ "MAXLINELENGTH := 2046",
+ "MAXPROCESSLIMIT := 4",
+ ".IMPORT .IGNORE: ROOTDIR",
+ ".MAKEFILES : makefile.mk makefile",
+ ".SOURCE : .NULL",
+#include "startup.h"
+ (char *)NULL };
+
+char **Rule_tab = _rules; /* for sundry reasons in Get_environment() */
+
diff --git a/dmake/win95/borland/sysintf.h b/dmake/win95/borland/sysintf.h
new file mode 100644
index 000000000000..bae67b65e967
--- /dev/null
+++ b/dmake/win95/borland/sysintf.h
@@ -0,0 +1,56 @@
+/* RCS $Id: sysintf.h,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+--
+-- SYNOPSIS
+-- Interfaces for sysintf.c
+--
+-- DESCRIPTION
+-- Abstractions of functions in sysintf.c
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#define DMSTAT stat
+#define VOID_LCACHE(l,m)
+#define GETPID _psp
+#define Hook_std_writes(A)
+#define DMSTRLWR(A,B) dstrlwr((A),(B))
+
+extern char * tempnam();
+extern char * getcwd();
+
+/*
+** standard C items
+*/
+
+/*
+** DOS interface standard items
+*/
+#define chdir(p) dchdir(p)
+#define CacheStat(A,B) really_dostat(A,&buf)
+
+/*
+** make parameters
+*/
+#ifdef _POSIX_NAME_MAX
+#undef _POSIX_NAME_MAX
+#endif
+#define _POSIX_NAME_MAX 12
+
+#ifdef _POSIX_PATH_MAX
+#undef _POSIX_PATH_MAX
+#endif
+#define _POSIX_PATH_MAX 64
diff --git a/dmake/win95/borland/tempnam.c b/dmake/win95/borland/tempnam.c
new file mode 100644
index 000000000000..cb1bd9f5eb53
--- /dev/null
+++ b/dmake/win95/borland/tempnam.c
@@ -0,0 +1,114 @@
+/* RCS $Id: tempnam.c,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+--
+-- SYNOPSIS
+-- tempnam
+--
+-- DESCRIPTION
+-- temp file name generation routines.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/*LINTLIBRARY*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dos.h>
+
+#if defined(max)
+# undef max
+#endif
+#define max(A,B) (((A)<(B))?(B):(A))
+
+extern char *mktemp();
+extern int access();
+int d_access();
+
+/* Turbo C stdio.h doesn't define P_tmpdir, so let's do it here */
+/* Under DOS leave the default tmpdir pointing here! */
+#ifndef P_tmpdir
+static char *P_tmpdir = "";
+#endif
+
+char *
+tempnam(dir, prefix)
+char *dir; /* use this directory please (if non-NULL) */
+char *prefix; /* use this (if non-NULL) as filename prefix */
+{
+ static int count = 0;
+ register char *p, *q, *tmpdir;
+ int tl=0, dl=0, pl;
+ char buf[30];
+
+#if defined(__WIN32__)
+ unsigned int _psp = rand();
+#endif
+
+ pl = strlen(P_tmpdir);
+
+ if( (tmpdir = getenv("TMPDIR")) != NULL ) tl = strlen(tmpdir);
+ else if( (tmpdir = getenv("TMP")) != NULL ) tl = strlen(tmpdir);
+ if( dir != NULL ) dl = strlen(dir);
+
+ if( (p = malloc((unsigned)(max(max(dl,tl),pl)+13))) == NULL )
+ return(NULL);
+
+ *p = '\0';
+
+ if( (tl == 0) || (d_access( strcpy(p, tmpdir), 0) != 0) )
+ if( (dl == 0) || (d_access( strcpy(p, dir), 0) != 0) )
+ if( d_access( strcpy(p, P_tmpdir), 0) != 0 )
+ if( !prefix )
+ prefix = "tp";
+
+ if(prefix)
+ {
+ *(p+strlen(p)+2) = '\0';
+ (void)strncat(p, prefix, 2);
+ }
+
+ sprintf( buf, "%08x", _psp );
+ buf[6]='\0';
+ (void)strcat(p, buf );
+ sprintf( buf, "%04d", count++ );
+ q=p+strlen(p)-6;
+ *q++ = buf[0]; *q++ = buf[1];
+ *q++ = buf[2]; *q = buf[3];
+
+ if( (q = strrchr(p,'.')) != NULL ) *q = '\0';
+
+ return(p);
+}
+
+
+
+d_access( name, flag )
+char *name;
+int flag;
+{
+ extern char *DirSepStr;
+ char *p;
+ int r;
+
+ if( name == NULL || !*name ) return(1); /* NULL dir means current dir */
+ r = access( name, flag );
+ p = name+strlen(name)-1;
+
+ if(*p != '/' && *p != '\\') strcat( p, DirSepStr );
+
+ return( r );
+}
diff --git a/dmake/win95/config.mk b/dmake/win95/config.mk
new file mode 100644
index 000000000000..721be05b00f4
--- /dev/null
+++ b/dmake/win95/config.mk
@@ -0,0 +1,53 @@
+# This is an OS specific configuration file
+# It assumes that OBJDIR, TARGET and DEBUG are previously defined.
+# It defines CFLAGS, LDARGS, CPPFLAGS, STARTUPFILE, LDOBJS
+# It augments SRC, OBJDIR, TARGET, CFLAGS, LDLIBS
+#
+
+# Memory model to compile for
+# set to s - small, m - medium, c - compact, l - large
+# Need large model now, dmake has grown up :-)
+MODEL = l
+
+STARTUPFILE = startup/startup.mk
+
+CPPFLAGS = $(CFLAGS)
+
+# Debug flags
+DB_CFLAGS = -DDBUG
+DB_LDFLAGS =
+DB_LDLIBS =
+
+# NO Debug flags
+NDB_CFLAGS =
+NDB_LDFLAGS =
+NDB_LDLIBS =
+
+# Local configuration modifications for CFLAGS.
+CFLAGS += -I$(OS)
+
+# Common Win32 source files.
+OS_SRC += dchdir.c switchar.c
+
+# Imported MSDOS Files.
+DOSSRC += dstrlwr.c arlib.c dirbrk.c
+
+SRC += $(OS_SRC) $(UNIXSRC) $(DOSSRC)
+
+# Provide our own %$O : %$S rule.
+%$O : %$S
+ +$(AS) $(ASFLAGS) \
+ $(<:s,\,${__.DIVSEP-sh-${USESHELL}},:s,/,${__.DIVSEP-sh-${USESHELL}},);
+ mv $(@:f) $(OBJDIR)
+
+# Set source dirs so that we can find files named in this
+# config file.
+.SOURCE.h : $(OS)
+
+# See if we modify anything in the lower levels.
+.IF $(OSRELEASE) != $(NULL)
+ .INCLUDE : $(OS)$(DIRSEPSTR)$(OSRELEASE)$(DIRSEPSTR)config.mk
+.END
+
+.SETDIR=msdos : $(DOSSRC)
+.SETDIR=$(OS) : $(ASRC) $(OS_SRC)
diff --git a/dmake/win95/dchdir.c b/dmake/win95/dchdir.c
new file mode 100644
index 000000000000..dab1d7163ede
--- /dev/null
+++ b/dmake/win95/dchdir.c
@@ -0,0 +1,49 @@
+/* RCS $Id: dchdir.c,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+--
+-- SYNOPSIS
+-- Change directory.
+--
+-- DESCRIPTION
+-- Under DOS change the current drive as well as the current directory.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#if 0
+#include <dir.h>
+#endif
+#include <direct.h>
+#include "extern.h"
+
+PUBLIC int
+dchdir(path)
+char *path;
+{
+ int res;
+
+ res = chdir(path);
+
+ if (res != -1 && path[1] == ':') {
+ unsigned new_drive;
+
+ /* for WIN32 just use the _chdrive library call */
+ new_drive = (*path & ~0x20) - 'A' + 1;
+ _chdrive(new_drive);
+ }
+
+ return (res);
+}
diff --git a/dmake/win95/microsft/config.h b/dmake/win95/microsft/config.h
new file mode 100644
index 000000000000..862b1d5b181c
--- /dev/null
+++ b/dmake/win95/microsft/config.h
@@ -0,0 +1,78 @@
+/* RCS $Id: config.h,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+--
+-- SYNOPSIS
+-- Configurarion include file.
+--
+-- DESCRIPTION
+-- There is one of these for each specific machine configuration.
+-- It can be used to further tweek the machine specific sources
+-- so that they compile.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#if defined (_MSC_VER)
+# if _MSC_VER < 500
+ Force a compile-time blowup.
+ Do not define "#define _MSC_VER" for MSC compilers earlier than 5.0.
+# endif
+#endif
+
+/* define this for configurations that don't have the coreleft function
+ * so that the code compiles. To my knowledge coreleft exists only on
+ * Turbo C, but it is needed here since the function is used in many debug
+ * macros. */
+#define coreleft() 0L
+
+/* MSC Version 4.0 doesn't understand SIGTERM, later versions do. */
+#ifndef SIGTERM
+# define SIGTERM SIGINT
+#endif
+
+/* Fixes unimplemented line buffering for MSC 5.x and 6.0.
+ * MSC _IOLBF is the same as _IOFBF
+ */
+#if defined(MSDOS) && defined (_MSC_VER)
+# undef _IOLBF
+# define _IOLBF _IONBF
+#endif
+
+/* in alloc.h: size_t is redefined
+ * defined in stdio.h which is included by alloc.h
+ */
+#if defined(MSDOS) && defined (_MSC_VER)
+# define _TYPES_
+#endif
+
+/* in sysintf.c: SIGQUIT is used, this is not defined in MSC */
+#ifndef SIGQUIT
+# define SIGQUIT SIGTERM
+#endif
+
+/* MSC doesn't seem to care about CONST */
+#define CONST
+
+#ifndef MSDOS
+# define MSDOS 1
+#endif
+
+/* a small problem with pointer to voids on some unix machines needs this */
+#define PVOID void *
+
+/* Use my own tempnam */
+#define tempnam dtempnam
+
diff --git a/dmake/win95/microsft/config.mk b/dmake/win95/microsft/config.mk
new file mode 100644
index 000000000000..352eed716d2f
--- /dev/null
+++ b/dmake/win95/microsft/config.mk
@@ -0,0 +1,61 @@
+# This is the MSC 4.0 and higher DOS configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+TMPDIR :=
+.EXPORT : TMPDIR
+
+# Definition of macros for library, and C startup code.
+
+# The following sources are required for MSC
+OSR_SRC += tempnam.c ruletab.c
+DOS_SRC += runargv.c rmprq.c
+
+.SETDIR=$(osrdir) : $(OSR_SRC)
+.SETDIR=msdos : $(DOS_SRC)
+
+SRC += $(OSR_SRC) $(DOS_SRC)
+.SOURCE.h : $(osrdir)
+
+SET_STACK = /stack:4096
+ASFLAGS += -t -mx $(S_$(MODEL))
+
+# Microsoft C doesn't need tail but needs head
+LDTAIL !=
+LDHEAD != $(LDFLAGS)
+LDARGS != $(LDHEAD) -out:$(TARGET) @$(LDTMPOBJ) $(LDTAIL)
+LDTAIL != $(_libs)
+_libs != $(!null,$(LDLIBS) ,@$(LDTMPLIB))
+LDTMPOBJ != $(mktmp,,$(DIVFILE) $(LDOBJS:s,/,\\,:t"\n")\n)
+LDTMPLIB != $(mktmp,,$(DIVFILE) $(LDLIBS:s,/,\\,:t"\n")\n)
+
+# Debugging libraries and flags
+DB_LDFLAGS += /nologo /co /li /map
+DB_LDLIBS +=
+DB_CFLAGS += -Zi
+
+# NO Debug MSC flags:
+# Set the environment variable MSC_VER to be one of 5.1, 6.0, 8.0 (for VC++4.0)
+# to get these by default when you make dmake using 'dmake'.
+#
+
+NDB_LDFLAGS += /nologo
+CFLAGS += -I$(osrdir)
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
+
+CFLAGS += /nologo
+
+S_s = -Dmsmall
+S_m = -Dmmedium
+S_c = -Dmcompact
+S_l = -Dmlarge
diff --git a/dmake/win95/microsft/optoff.h b/dmake/win95/microsft/optoff.h
new file mode 100644
index 000000000000..019605931851
--- /dev/null
+++ b/dmake/win95/microsft/optoff.h
@@ -0,0 +1,27 @@
+/* RCS $Id: optoff.h,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+--
+-- SYNOPSIS
+-- Turn off microsoft loop optimization.
+--
+-- DESCRIPTION
+-- This is broken in some pre 600 compilers so just turn it off.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+#if _MSC_VER < 600
+# pragma loop_opt(off)
+#endif
diff --git a/dmake/win95/microsft/ruletab.c b/dmake/win95/microsft/ruletab.c
new file mode 100644
index 000000000000..353e1eb7802e
--- /dev/null
+++ b/dmake/win95/microsft/ruletab.c
@@ -0,0 +1,45 @@
+/* RCS $Id: ruletab.c,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+--
+-- SYNOPSIS
+-- Default initial configuration of dmake.
+--
+-- DESCRIPTION
+-- Define here the initial set of rules that are defined before
+-- dmake performs any processing.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* These are control macros for dmake that MUST be defined at some point
+ * if they are NOT dmake will not work! These are default definitions. They
+ * may be overridden inside the .STARTUP makefile, they are here
+ * strictly so that dmake can parse the STARTUP makefile */
+
+#include <stdio.h>
+
+static char *_rules[] = {
+ "MAXLINELENGTH := 2046",
+ "MAXPROCESSLIMIT := 4",
+ "MAXPROCESS := 1",
+ ".IMPORT .IGNORE: DMAKEROOT SOLARVER UPD INPATH OS UPDMINOREXT",
+ ".MAKEFILES : makefile.mk makefile",
+ ".SOURCE : .NULL",
+#include "startup.h"
+ (char *)NULL };
+
+char **Rule_tab = _rules; /* for sundry reasons in Get_environment() */
+
diff --git a/dmake/win95/microsft/sysintf.h b/dmake/win95/microsft/sysintf.h
new file mode 100644
index 000000000000..426be8c6059d
--- /dev/null
+++ b/dmake/win95/microsft/sysintf.h
@@ -0,0 +1,58 @@
+/* RCS $Id: sysintf.h,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- Interfaces for sysintf.c
+--
+-- DESCRIPTION
+-- Abstractions of functions in sysintf.c
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#define DMSTAT stat
+#define VOID_LCACHE(l,m)
+#define GETPID _psp
+#define Hook_std_writes(A)
+#define DMSTRLWR(A,B) dstrlwr((A),(B))
+
+extern char * tempnam();
+extern char * getcwd();
+
+/* for directory cache */
+#define CacheStat(A,B) really_dostat(A,&buf)
+
+/*
+** standard C items
+*/
+
+/*
+** DOS interface standard items
+*/
+#define chdir(p) dchdir(p)
+
+/*
+** make parameters
+*/
+#ifdef _POSIX_NAME_MAX
+#undef _POSIX_NAME_MAX
+#endif
+#define _POSIX_NAME_MAX 12
+
+#ifdef _POSIX_PATH_MAX
+#undef _POSIX_PATH_MAX
+#endif
+#define _POSIX_PATH_MAX _MAX_PATH
diff --git a/dmake/win95/microsft/tempnam.c b/dmake/win95/microsft/tempnam.c
new file mode 100644
index 000000000000..c3a8fa140f29
--- /dev/null
+++ b/dmake/win95/microsft/tempnam.c
@@ -0,0 +1,110 @@
+/* RCS $Id: tempnam.c,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- tempnam
+--
+-- DESCRIPTION
+-- temp file name generation routines.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/*LINTLIBRARY*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <process.h>
+
+#if defined(max)
+# undef max
+#endif
+#define max(A,B) (((A)<(B))?(B):(A))
+
+extern char *mktemp();
+extern int access();
+int d_access();
+
+/* MSC stdio.h defines P_tmpdir, so let's undo it here */
+/* Under DOS leave the default tmpdir pointing here! */
+#ifdef P_tmpdir
+#undef P_tmpdir
+#endif
+static char *P_tmpdir = "";
+
+char *
+dtempnam(dir, prefix)
+char *dir; /* use this directory please (if non-NULL) */
+char *prefix; /* use this (if non-NULL) as filename prefix */
+{
+ static int count = 0;
+ register char *p, *q, *tmpdir;
+ int tl=0, dl=0, pl;
+ char buf[30];
+
+ pl = strlen(P_tmpdir);
+
+ if( (tmpdir = getenv("TMPDIR")) != NULL ) tl = strlen(tmpdir);
+ else if( (tmpdir = getenv("TMP")) != NULL ) tl = strlen(tmpdir);
+ if( dir != NULL ) dl = strlen(dir);
+
+ if( (p = malloc((unsigned)(max(max(dl,tl),pl)+13))) == NULL )
+ return(NULL);
+
+ *p = '\0';
+
+ if( (tl == 0) || (d_access( strcpy(p, tmpdir), 0) != 0) )
+ if( (dl == 0) || (d_access( strcpy(p, dir), 0) != 0) )
+ if( d_access( strcpy(p, P_tmpdir), 0) != 0 )
+ if( !prefix )
+ prefix = "tp";
+
+ if(prefix)
+ {
+ *(p+strlen(p)+2) = '\0';
+ (void)strncat(p, prefix, 2);
+ }
+
+ sprintf( buf, "%08x", getpid() );
+ buf[6]='\0';
+ (void)strcat(p, buf );
+ sprintf( buf, "%04d", count++ );
+ q=p+strlen(p)-6;
+ *q++ = buf[0]; *q++ = buf[1];
+ *q++ = buf[2]; *q++ = buf[3];
+
+ if( (q = strrchr(p,'.')) != NULL ) *q = '\0';
+
+ return(p);
+}
+
+
+
+d_access( name, flag )
+char *name;
+int flag;
+{
+ extern char *DirSepStr;
+ char *p;
+ int r;
+
+ if( name == NULL || !*name ) return(1); /* NULL dir means current dir */
+ r = access( name, flag );
+ p = name+strlen(name)-1;
+ if(*p != '/' && *p != '\\') strcat( p, DirSepStr );
+
+ return( r );
+}
diff --git a/dmake/win95/microsft/vpp40/config.mk b/dmake/win95/microsft/vpp40/config.mk
new file mode 100644
index 000000000000..14fe952eac00
--- /dev/null
+++ b/dmake/win95/microsft/vpp40/config.mk
@@ -0,0 +1,14 @@
+# Definition of macros for library, and C startup code.
+osedir = $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)
+
+.IMPORT .IGNORE : MSC_VER
+MSC_VER *= 8.0
+
+CFLAGS += -I$(osedir)
+
+NDB_CFLAGS += -Od -GF -Ge
+NDB_LDFLAGS +=
+NDB_LDLIBS +=
+
+# Redefine rule for making our objects, we don't need mv
+%$O : %.c ;% $(CC) -c $(CFLAGS) -Fo$@ $<
diff --git a/dmake/win95/microsft/vpp40/lib.rsp b/dmake/win95/microsft/vpp40/lib.rsp
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/dmake/win95/microsft/vpp40/lib.rsp
@@ -0,0 +1 @@
+
diff --git a/dmake/win95/microsft/vpp40/mk.bat b/dmake/win95/microsft/vpp40/mk.bat
new file mode 100755
index 000000000000..b1f73ba7e18f
--- /dev/null
+++ b/dmake/win95/microsft/vpp40/mk.bat
@@ -0,0 +1,37 @@
+if "%1" != "" goto link
+md objects
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\infer.obj infer.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\make.obj make.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\stat.obj stat.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\expand.obj expand.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\dmstring.obj dmstring.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\hash.obj hash.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\dag.obj dag.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\dmake.obj dmake.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\path.obj path.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\imacs.obj imacs.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\sysintf.obj sysintf.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\parse.obj parse.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\getinp.obj getinp.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\quit.obj quit.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\state.obj state.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\dmdump.obj dmdump.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\macparse.obj macparse.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\rulparse.obj rulparse.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\percent.obj percent.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\function.obj function.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\dchdir.obj win95\dchdir.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\switchar.obj win95\switchar.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\dstrlwr.obj msdos\dstrlwr.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\arlib.obj msdos\arlib.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\dirbrk.obj msdos\dirbrk.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\tempnam.obj tempnam.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\ruletab.obj win95\microsft\ruletab.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\runargv.obj msdos\runargv.c
+cl -c %c_flg -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\rmprq.obj msdos\rmprq.c
+
+:link
+rem link /nologo /out:dmake.exe @fix95nt\win95\microsft\vpp40\obj.rsp
+if "%c_flg" == "" link /out:dmake.exe @.\win95\microsft\vpp40\obj.rsp
+if "%c_flg" != "" link /DEBUG:notmapped,full /DEBUGTYPE:cv /PDB:NONE /out:dmake.exe @.\win95\microsft\vpp40\obj.rsp
+copy win95\microsft\vpp40\template.mk startup\config.mk
diff --git a/dmake/win95/microsft/vpp40/obj.rsp b/dmake/win95/microsft/vpp40/obj.rsp
new file mode 100644
index 000000000000..e9e03972b791
--- /dev/null
+++ b/dmake/win95/microsft/vpp40/obj.rsp
@@ -0,0 +1,29 @@
+objects\infer.obj
+objects\make.obj
+objects\stat.obj
+objects\expand.obj
+objects\dmstring.obj
+objects\hash.obj
+objects\dag.obj
+objects\dmake.obj
+objects\path.obj
+objects\imacs.obj
+objects\sysintf.obj
+objects\parse.obj
+objects\getinp.obj
+objects\quit.obj
+objects\state.obj
+objects\dmdump.obj
+objects\macparse.obj
+objects\rulparse.obj
+objects\percent.obj
+objects\function.obj
+objects\dchdir.obj
+objects\switchar.obj
+objects\dstrlwr.obj
+objects\arlib.obj
+objects\dirbrk.obj
+objects\tempnam.obj
+objects\ruletab.obj
+objects\runargv.obj
+objects\rmprq.obj
diff --git a/dmake/win95/microsft/vpp40/public.h b/dmake/win95/microsft/vpp40/public.h
new file mode 100644
index 000000000000..f867838344c5
--- /dev/null
+++ b/dmake/win95/microsft/vpp40/public.h
@@ -0,0 +1,166 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+int dchdir ANSI((char *));
+void dstrlwr ANSI((char *, char *));
+time_t seek_arch ANSI((char*, char*));
+int touch_arch ANSI((char*, char*));
+int If_root_path ANSI((char *));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+void Clean_up_processes ANSI(());
+int Wait_for_child ANSI((int, int));
+void Remove_prq ANSI((CELLPTR));
+
+#endif
diff --git a/dmake/win95/microsft/vpp40/runargv.c b/dmake/win95/microsft/vpp40/runargv.c
new file mode 100644
index 000000000000..fd0cbe355109
--- /dev/null
+++ b/dmake/win95/microsft/vpp40/runargv.c
@@ -0,0 +1,290 @@
+Blake sent me the wrong one.
+
+/* RCS $Id: runargv.c,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- Invoke a sub process.
+--
+-- DESCRIPTION
+-- Use the standard methods of executing a sub process.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <process.h>
+#include <errno.h>
+#include <signal.h>
+#include "extern.h"
+#include "sysintf.h"
+
+extern char **environ;
+
+typedef struct prp {
+ char *prp_cmd;
+ int prp_group;
+ int prp_ignore;
+ int prp_last;
+ int prp_shell;
+ struct prp *prp_next;
+} RCP, *RCPPTR;
+
+typedef struct pr {
+ int pr_valid;
+ int pr_pid;
+ CELLPTR pr_target;
+ int pr_ignore;
+ int pr_last;
+ RCPPTR pr_recipe;
+ RCPPTR pr_recipe_end;
+ char *pr_dir;
+} PR;
+
+static PR *_procs = NIL(PR);
+static int _proc_cnt = 0;
+static int _abort_flg= FALSE;
+static int _use_i = -1;
+static int _do_upd = 0;
+
+static void _add_child ANSI((int, CELLPTR, int, int));
+static void _attach_cmd ANSI((char *, int, int, CELLPTR, int, int));
+static void _finished_child ANSI((int, int));
+static int _running ANSI((CELLPTR));
+
+PUBLIC int
+runargv(target, ignore, group, last, shell, cmd)
+CELLPTR target;
+int ignore;
+int group;
+int last;
+int shell;
+char *cmd;
+{
+ extern int errno;
+ extern char *sys_errlist[];
+ int pid;
+ char **argv;
+
+ if( _running(target) /*&& Max_proc != 1*/ ) {
+ /* The command will be executed when the previous recipe
+ * line completes. */
+ _attach_cmd( cmd, group, ignore, target, last, shell );
+ return(1);
+ }
+
+ while( _proc_cnt == Max_proc )
+ if( Wait_for_child(FALSE, -1) == -1 ) Fatal( "Lost a child %d", errno );
+
+ argv = Pack_argv( group, shell, cmd );
+
+ pid = _spawnvpe(_P_NOWAIT, argv[0], argv, environ);
+ if (pid == -1) { /* failed */
+ Error("%s: %s", argv[0], sys_errlist[errno]);
+ Handle_result(-1, ignore, _abort_flg, target);
+ return(-1);
+ } else
+ _add_child(pid, target, ignore, last);
+
+ return(1);
+}
+
+
+PUBLIC int
+Wait_for_child( abort_flg, pid )
+int abort_flg;
+int pid;
+{
+ int wid;
+ int status;
+ int waitchild;
+
+ waitchild = (pid == -1)? FALSE : Wait_for_completion;
+
+ do {
+ if( (wid = wait(&status)) == -1 ) return(-1);
+
+ _abort_flg = abort_flg;
+ _finished_child(wid, status);
+ _abort_flg = FALSE;
+ } while( waitchild && pid != wid );
+
+ return(0);
+}
+
+
+PUBLIC void
+Clean_up_processes()
+{
+ register int i;
+
+ if( _procs != NIL(PR) ) {
+ for( i=0; i<Max_proc; i++ )
+ if( _procs[i].pr_valid )
+ kill(_procs[i].pr_pid, SIGTERM);
+
+ while( Wait_for_child(TRUE, -1) != -1 );
+ }
+}
+
+
+static void
+_add_child( pid, target, ignore, last )
+int pid;
+CELLPTR target;
+int ignore;
+int last;
+{
+ register int i;
+ register PR *pp;
+
+ if( _procs == NIL(PR) ) {
+ TALLOC( _procs, Max_proc, PR );
+ }
+
+ if( (i = _use_i) == -1 )
+ for( i=0; i<Max_proc; i++ )
+ if( !_procs[i].pr_valid )
+ break;
+
+ pp = _procs+i;
+
+ pp->pr_valid = 1;
+ pp->pr_pid = pid;
+ pp->pr_target = target;
+ pp->pr_ignore = ignore;
+ pp->pr_last = last;
+ pp->pr_dir = DmStrDup(Get_current_dir());
+
+ Current_target = NIL(CELL);
+
+ _proc_cnt++;
+
+ if( Wait_for_completion ) Wait_for_child( FALSE, pid );
+}
+
+
+static void
+_finished_child(pid, status)
+int pid;
+int status;
+{
+ register int i;
+ register PR *pp;
+ char *dir;
+
+ for( i=0; i<Max_proc; i++ )
+ if( _procs[i].pr_valid && _procs[i].pr_pid == pid )
+ break;
+
+ /* Some children we didn't make esp true if using /bin/sh to execute a
+ * a pipe and feed the output as a makefile into dmake. */
+ if( i == Max_proc ) return;
+ _procs[i].pr_valid = 0;
+ _proc_cnt--;
+ dir = DmStrDup(Get_current_dir());
+ Set_dir( _procs[i].pr_dir );
+
+ if( _procs[i].pr_recipe != NIL(RCP) && !_abort_flg ) {
+ RCPPTR rp = _procs[i].pr_recipe;
+
+
+ Current_target = _procs[i].pr_target;
+ Handle_result( status, _procs[i].pr_ignore, FALSE, _procs[i].pr_target );
+ Current_target = NIL(CELL);
+
+ if ( _procs[i].pr_target->ce_attr & A_ERROR ) {
+ Unlink_temp_files( _procs[i].pr_target );
+ _procs[i].pr_last = TRUE;
+ goto ABORT_REMAINDER_OF_RECIPE;
+ }
+
+ _procs[i].pr_recipe = rp->prp_next;
+
+ _use_i = i;
+ runargv( _procs[i].pr_target, rp->prp_ignore, rp->prp_group,
+ rp->prp_last, rp->prp_shell, rp->prp_cmd );
+ _use_i = -1;
+
+ FREE( rp->prp_cmd );
+ FREE( rp );
+
+ if( _proc_cnt == Max_proc ) Wait_for_child( FALSE, -1 );
+ }
+ else {
+ Unlink_temp_files( _procs[i].pr_target );
+ Handle_result(status,_procs[i].pr_ignore,_abort_flg,_procs[i].pr_target);
+
+ ABORT_REMAINDER_OF_RECIPE:
+ if( _procs[i].pr_last ) {
+ FREE(_procs[i].pr_dir );
+
+ if( !Doing_bang ) Update_time_stamp( _procs[i].pr_target );
+ }
+ }
+
+ Set_dir(dir);
+ FREE(dir);
+}
+
+
+static int
+_running( cp )
+CELLPTR cp;
+{
+ register int i;
+
+ if( !_procs ) return(FALSE);
+
+ for( i=0; i<Max_proc; i++ )
+ if( _procs[i].pr_valid &&
+ _procs[i].pr_target == cp )
+ break;
+
+ return( i != Max_proc );
+}
+
+
+static void
+_attach_cmd( cmd, group, ignore, cp, last, shell )
+char *cmd;
+int group;
+int ignore;
+CELLPTR cp;
+int last;
+int shell;
+{
+ register int i;
+ RCPPTR rp;
+
+ for( i=0; i<Max_proc; i++ )
+ if( _procs[i].pr_valid &&
+ _procs[i].pr_target == cp )
+ break;
+
+ TALLOC( rp, 1, RCP );
+ rp->prp_cmd = DmStrDup(cmd);
+ rp->prp_group = group;
+ rp->prp_ignore= ignore;
+ rp->prp_last = last;
+ rp->prp_shell = shell;
+
+ if( _procs[i].pr_recipe == NIL(RCP) )
+ _procs[i].pr_recipe = _procs[i].pr_recipe_end = rp;
+ else {
+ _procs[i].pr_recipe_end->prp_next = rp;
+ _procs[i].pr_recipe_end = rp;
+ }
+}
diff --git a/dmake/win95/microsft/vpp40/template.mk b/dmake/win95/microsft/vpp40/template.mk
new file mode 100644
index 000000000000..d4e6c9eb9f40
--- /dev/null
+++ b/dmake/win95/microsft/vpp40/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= win95
+ OSRELEASE *:= microsft
+ OSENVIRONMENT *:= vpp40
diff --git a/dmake/win95/microsft/vpp40/tempnam.c b/dmake/win95/microsft/vpp40/tempnam.c
new file mode 100644
index 000000000000..c27da47c7602
--- /dev/null
+++ b/dmake/win95/microsft/vpp40/tempnam.c
@@ -0,0 +1,110 @@
+/* RCS $Id: tempnam.c,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- tempnam
+--
+-- DESCRIPTION
+-- temp file name generation routines.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/*LINTLIBRARY*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dos.h>
+
+#if defined(max)
+# undef max
+#endif
+#define max(A,B) (((A)<(B))?(B):(A))
+
+extern char *mktemp();
+extern int access();
+int d_access();
+
+/* MSC stdio.h defines P_tmpdir, so let's undo it here */
+/* Under DOS leave the default tmpdir pointing here! */
+#ifdef P_tmpdir
+#undef P_tmpdir
+#endif
+static char *P_tmpdir = "";
+
+char *
+tempnam(dir, prefix)
+char *dir; /* use this directory please (if non-NULL) */
+char *prefix; /* use this (if non-NULL) as filename prefix */
+{
+ static int count = 0;
+ register char *p, *q, *tmpdir;
+ int tl=0, dl=0, pl;
+ char buf[30];
+
+ pl = strlen(P_tmpdir);
+
+ if( (tmpdir = getenv("TMPDIR")) != NULL ) tl = strlen(tmpdir);
+ else if( (tmpdir = getenv("TMP")) != NULL ) tl = strlen(tmpdir);
+ if( dir != NULL ) dl = strlen(dir);
+
+ if( (p = malloc((unsigned)(max(max(dl,tl),pl)+13))) == NULL )
+ return(NULL);
+
+ *p = '\0';
+
+ if( (tl == 0) || (d_access( strcpy(p, tmpdir), 0) != 0) )
+ if( (dl == 0) || (d_access( strcpy(p, dir), 0) != 0) )
+ if( d_access( strcpy(p, P_tmpdir), 0) != 0 )
+ if( !prefix )
+ prefix = "tp";
+
+ if(prefix)
+ {
+ *(p+strlen(p)+2) = '\0';
+ (void)strncat(p, prefix, 2);
+ }
+
+ sprintf( buf, "%08x", _psp );
+ buf[6]='\0';
+ (void)strcat(p, buf );
+ sprintf( buf, "%04d", count++ );
+ q=p+strlen(p)-6;
+ *q++ = buf[0]; *q++ = buf[1];
+ *q++ = buf[2]; *q++ = buf[3];
+
+ if( (q = strrchr(p,'.')) != NULL ) *q = '\0';
+
+ return(p);
+}
+
+
+
+d_access( name, flag )
+char *name;
+int flag;
+{
+ extern char *DirSepStr;
+ char *p;
+ int r;
+
+ if( name == NULL || !*name ) return(1); /* NULL dir means current dir */
+ r = access( name, flag );
+ p = name+strlen(name)-1;
+ if(*p != '/' && *p != '\\') strcat( p, DirSepStr );
+
+ return( r );
+}
diff --git a/dmake/win95/startup.h b/dmake/win95/startup.h
new file mode 100644
index 000000000000..b2731353c6b5
--- /dev/null
+++ b/dmake/win95/startup.h
@@ -0,0 +1,28 @@
+/* RCS $Id: startup.h,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+--
+-- SYNOPSIS
+-- Definition of MAKESTARTUP
+--
+-- DESCRIPTION
+-- Default MAKESTARTUP value defining where dmake locates the
+-- startup file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/*"MAKESTARTUP := $(MAKECMD:d)startup/startup.mk",*/
+"MAKESTARTUP := $(DMAKEROOT)\\startup.mk",
diff --git a/dmake/win95/switchar.c b/dmake/win95/switchar.c
new file mode 100644
index 000000000000..783d02cefe77
--- /dev/null
+++ b/dmake/win95/switchar.c
@@ -0,0 +1,43 @@
+/* RCS $Id: switchar.c,v 1.1.1.1 2000-09-22 15:33:36 hr Exp $
+--
+-- SYNOPSIS
+-- switchar settings
+--
+-- DESCRIPTION
+-- Figure out the value of switchar.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "stdmacs.h"
+
+getswitchar()/*
+===============
+ Try the environment first. If you don't find SWITCHAR there, then use
+ the DOS call. The call is undocumented, and doesn't work for DOS versions
+ 4.0 and up, so the check of the environment will fix that. */
+{
+ static char *_env_switchar = NIL(char);
+
+ if( _env_switchar != NIL(char) ||
+ (_env_switchar = (char *)getenv("SWITCHAR")) != NIL(char) )
+ return(*_env_switchar);
+
+ return ('/');
+}
diff --git a/dmake/winnt/borland/bcc50/config.h b/dmake/winnt/borland/bcc50/config.h
new file mode 100644
index 000000000000..dc9f72b439bd
--- /dev/null
+++ b/dmake/winnt/borland/bcc50/config.h
@@ -0,0 +1,44 @@
+/* RCS $Id: config.h,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- Configurarion include file.
+--
+-- DESCRIPTION
+-- There is one of these for each specific machine configuration.
+-- It can be used to further tweek the machine specific sources
+-- so that they compile.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* define this for configurations that don't have the coreleft function
+ * so that the code compiles. To my knowledge coreleft exists only on
+ * Turbo C, but it is needed here since the function is used in many debug
+ * macros. */
+/*#define coreleft() 0L*/
+extern unsigned int coreleft();
+
+#define SIGQUIT SIGBREAK /* turbo C doesn't understand SIGQUIT */
+
+/* Turbo-C understands const declarations. */
+#define CONST const
+
+/* a small problem with pointer to voids on some unix machines needs this */
+#define PVOID void *
+
+/* Borland redefined the environment variable, sigh */
+#define environ _environ
diff --git a/dmake/winnt/borland/bcc50/config.mk b/dmake/winnt/borland/bcc50/config.mk
new file mode 100644
index 000000000000..6e4fbd89e368
--- /dev/null
+++ b/dmake/winnt/borland/bcc50/config.mk
@@ -0,0 +1,12 @@
+# Definition of macros for library, and C startup code.
+osedir = $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)
+
+# Change the CCROOT variable to reflect the installation directory of your
+# C++ compiler.
+CCVER *:= c:/cc/borland/$(OSENVIRONMENT)
+
+# Definitions for compiles and links
+CSTARTUP = $(CCVER)/lib/c0x32.obj
+LDLIBS = $(CCVER)/lib/cw32 $(CCVER)/lib/import32
+
+CFLAGS += -A- -w-pro -I$(osedir)
diff --git a/dmake/winnt/borland/bcc50/lib.rsp b/dmake/winnt/borland/bcc50/lib.rsp
new file mode 100644
index 000000000000..0bad32e7128d
--- /dev/null
+++ b/dmake/winnt/borland/bcc50/lib.rsp
@@ -0,0 +1,2 @@
+c:\cc\borland\bcc50\lib\cw32
+c:\cc\borland\bcc50\lib\import32
diff --git a/dmake/winnt/borland/bcc50/mk.bat b/dmake/winnt/borland/bcc50/mk.bat
new file mode 100755
index 000000000000..f6e3c75fce78
--- /dev/null
+++ b/dmake/winnt/borland/bcc50/mk.bat
@@ -0,0 +1,95 @@
+md objects
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 infer.c
+copy infer.obj objects
+del infer.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 make.c
+copy make.obj objects
+del make.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 stat.c
+copy stat.obj objects
+del stat.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 expand.c
+copy expand.obj objects
+del expand.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 dmstring.c
+copy dmstring.obj objects
+del dmstring.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 hash.c
+copy hash.obj objects
+del hash.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 dag.c
+copy dag.obj objects
+del dag.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 dmake.c
+copy dmake.obj objects
+del dmake.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 path.c
+copy path.obj objects
+del path.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 imacs.c
+copy imacs.obj objects
+del imacs.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 sysintf.c
+copy sysintf.obj objects
+del sysintf.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 parse.c
+copy parse.obj objects
+del parse.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 getinp.c
+copy getinp.obj objects
+del getinp.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 quit.c
+copy quit.obj objects
+del quit.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 state.c
+copy state.obj objects
+del state.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 dmdump.c
+copy dmdump.obj objects
+del dmdump.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 macparse.c
+copy macparse.obj objects
+del macparse.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 rulparse.c
+copy rulparse.obj objects
+del rulparse.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 percent.c
+copy percent.obj objects
+del percent.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 function.c
+copy function.obj objects
+del function.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 win95\dchdir.c
+copy dchdir.obj objects
+del dchdir.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 win95\switchar.c
+copy switchar.obj objects
+del switchar.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 msdos\dstrlwr.c
+copy dstrlwr.obj objects
+del dstrlwr.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 msdos\arlib.c
+copy arlib.obj objects
+del arlib.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 msdos\dirbrk.c
+copy dirbrk.obj objects
+del dirbrk.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 win95\borland\tempnam.c
+copy tempnam.obj objects
+del tempnam.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 win95\borland\utime.c
+copy utime.obj objects
+del utime.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 win95\borland\ruletab.c
+copy ruletab.obj objects
+del ruletab.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 win95\borland\runargv.c
+copy runargv.obj objects
+del runargv.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 unix\dcache.c
+copy dcache.obj objects
+del dcache.obj
+bcc32 -c -I. -Iwin95 -Iwin95\borland -d -O -N- -w-nod -A- -w-pro -Iwin95\borland\bcc50 unix\rmprq.c
+copy rmprq.obj objects
+del rmprq.obj
+tlink32 @win95\borland\bcc50\obj.rsp,dmake.exe,NUL.MAP,@win95\borland\bcc50\lib.rsp
diff --git a/dmake/winnt/borland/bcc50/mk.cmd b/dmake/winnt/borland/bcc50/mk.cmd
new file mode 100755
index 000000000000..7f212e9c4f09
--- /dev/null
+++ b/dmake/winnt/borland/bcc50/mk.cmd
@@ -0,0 +1,93 @@
+md objects
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 infer.c
+copy infer.obj objects
+del infer.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 make.c
+copy make.obj objects
+del make.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 stat.c
+copy stat.obj objects
+del stat.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 expand.c
+copy expand.obj objects
+del expand.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 dmstring.c
+copy dmstring.obj objects
+del dmstring.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 hash.c
+copy hash.obj objects
+del hash.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 dag.c
+copy dag.obj objects
+del dag.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 dmake.c
+copy dmake.obj objects
+del dmake.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 path.c
+copy path.obj objects
+del path.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 imacs.c
+copy imacs.obj objects
+del imacs.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 sysintf.c
+copy sysintf.obj objects
+del sysintf.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 parse.c
+copy parse.obj objects
+del parse.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 getinp.c
+copy getinp.obj objects
+del getinp.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 quit.c
+copy quit.obj objects
+del quit.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 state.c
+copy state.obj objects
+del state.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 dmdump.c
+copy dmdump.obj objects
+del dmdump.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 macparse.c
+copy macparse.obj objects
+del macparse.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 rulparse.c
+copy rulparse.obj objects
+del rulparse.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 percent.c
+copy percent.obj objects
+del percent.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 function.c
+copy function.obj objects
+del function.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 winnt\dchdir.c
+copy dchdir.obj objects
+del dchdir.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 msdos\dstrlwr.c
+copy dstrlwr.obj objects
+del dstrlwr.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 msdos\arlib.c
+copy arlib.obj objects
+del arlib.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 msdos\dirbrk.c
+copy dirbrk.obj objects
+del dirbrk.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 winnt\borland\tempnam.c
+copy tempnam.obj objects
+del tempnam.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 winnt\borland\ruletab.c
+copy ruletab.obj objects
+del ruletab.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 winnt\borland\utime.c
+copy utime.obj objects
+del utime.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 winnt\borland\runargv.c
+copy runargv.obj objects
+del runargv.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 unix\dcache.c
+copy dcache.obj objects
+del dcache.obj
+bcc32 -c -I. -Iwinnt -Iwinnt\borland -d -O -N- -w-nod -A- -w-pro -Iwinnt\borland\bcc50 unix\rmprq.c
+copy rmprq.obj objects
+del rmprq.obj
+tlink32 @fix95nt\winnt\borland\bcc50\obj.rsp,dmake.exe,NUL.MAP,@fix95nt\winnt\borland\bcc50\lib.rsp
+copy winnt\borland\bcc50\template.mk startup\config.mk
diff --git a/dmake/winnt/borland/bcc50/obj.rsp b/dmake/winnt/borland/bcc50/obj.rsp
new file mode 100644
index 000000000000..9cf59afdedd2
--- /dev/null
+++ b/dmake/winnt/borland/bcc50/obj.rsp
@@ -0,0 +1,31 @@
+c:\cc\borland\bcc50\lib\c0x32.obj
+objects\infer.obj
+objects\make.obj
+objects\stat.obj
+objects\expand.obj
+objects\dmstring.obj
+objects\hash.obj
+objects\dag.obj
+objects\dmake.obj
+objects\path.obj
+objects\imacs.obj
+objects\sysintf.obj
+objects\parse.obj
+objects\getinp.obj
+objects\quit.obj
+objects\state.obj
+objects\dmdump.obj
+objects\macparse.obj
+objects\rulparse.obj
+objects\percent.obj
+objects\function.obj
+objects\dchdir.obj
+objects\dstrlwr.obj
+objects\arlib.obj
+objects\dirbrk.obj
+objects\tempnam.obj
+objects\ruletab.obj
+objects\utime.obj
+objects\runargv.obj
+objects\dcache.obj
+objects\rmprq.obj
diff --git a/dmake/winnt/borland/bcc50/public.h b/dmake/winnt/borland/bcc50/public.h
new file mode 100644
index 000000000000..8e9567e016a3
--- /dev/null
+++ b/dmake/winnt/borland/bcc50/public.h
@@ -0,0 +1,167 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+int dchdir ANSI((char *));
+void dstrlwr ANSI((char *, char *));
+time_t seek_arch ANSI((char*, char*));
+int touch_arch ANSI((char*, char*));
+int If_root_path ANSI((char *));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+int Wait_for_child ANSI((int, int));
+void Clean_up_processes ANSI(());
+time_t CacheStat ANSI((char *, int));
+void Remove_prq ANSI((CELLPTR));
+
+#endif
diff --git a/dmake/winnt/borland/bcc50/template.mk b/dmake/winnt/borland/bcc50/template.mk
new file mode 100644
index 000000000000..b94ac034e0a1
--- /dev/null
+++ b/dmake/winnt/borland/bcc50/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= winnt
+ OSRELEASE *:= borland
+ OSENVIRONMENT *:= bcc50
diff --git a/dmake/winnt/borland/config.mk b/dmake/winnt/borland/config.mk
new file mode 100644
index 000000000000..85c929b4163e
--- /dev/null
+++ b/dmake/winnt/borland/config.mk
@@ -0,0 +1,51 @@
+# This is the Turbo C++ 2.0 DOS configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+# OS specific sources
+OSR_SRC += tempnam.c ruletab.c
+DOS_SRC += runargv.c rmprq.c
+
+SRC += $(OSR_SRC) $(DOS_SRC)
+.SOURCE.h : $(osrdir)
+
+# Local configuration modifications for CFLAGS. Make sure your turboc.cfg
+# file contains a -D__STDC__=1 and -DM_I86=1, if not then uncomment the line
+# below!
+#CFLAGS += -DM_I86=1 -D__STDC__=1
+
+# You can get a smaller executable still, buy adding a -1 to the list of
+# flags below, but then you can't run this on an 8086/88 cpu.
+#CFLAGS += -1
+CFLAGS += -I$(osrdir) -d -O -N- -w-nod
+ASFLAGS += -t -mx $(S_$(MODEL))
+
+LDOBJS = $(CSTARTUP) $(OBJDIR)/{$(<:f)}
+LDARGS = $(LDHEAD) @$(LDTMPOBJ),$(TARGET),NUL.MAP$(LDTAIL)
+LDTAIL = $(_libs)$(LDFLAGS:s/ //)
+_libs = $(!null,$(LDLIBS) ,@$(LDTMPLIB))
+LDTMPOBJ = $(mktmp,,$(DIVFILE) $(LDOBJS:s,/,\\,:t"+\n")\n)
+LDTMPLIB = $(mktmp,,$(DIVFILE) $(LDLIBS:s,/,\\,:t"+\n")\n)
+
+# Debugging information for Turbo-C
+DB_CFLAGS += -v
+DB_LDFLAGS += /v
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
+
+.SETDIR=$(osrdir) : $(OSR_SRC)
+.SETDIR=msdos : $(DOS_SRC)
+
+S_s = -dmsmall
+S_m = -dmmedium
+S_c = -dmcompact
+S_l = -dmlarge
diff --git a/dmake/winnt/borland/ruletab.c b/dmake/winnt/borland/ruletab.c
new file mode 100644
index 000000000000..8522d617363c
--- /dev/null
+++ b/dmake/winnt/borland/ruletab.c
@@ -0,0 +1,44 @@
+/* RCS $Id: ruletab.c,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- Default initial configuration of dmake.
+--
+-- DESCRIPTION
+-- Define here the initial set of rules that are defined before
+-- dmake performs any processing.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* These are control macros for dmake that MUST be defined at some point
+ * if they are NOT dmake will not work! These are default definitions. They
+ * may be overridden inside the .STARTUP makefile, they are here
+ * strictly so that dmake can parse the STARTUP makefile */
+
+#include <stdio.h>
+
+static char *_rules[] = {
+ "MAXLINELENGTH := 2046",
+ "MAXPROCESSLIMIT := 4",
+ ".IMPORT .IGNORE: ROOTDIR",
+ ".MAKEFILES : makefile.mk makefile",
+ ".SOURCE : .NULL",
+#include "startup.h"
+ (char *)NULL };
+
+char **Rule_tab = _rules; /* for sundry reasons in Get_environment() */
+
diff --git a/dmake/winnt/borland/sysintf.h b/dmake/winnt/borland/sysintf.h
new file mode 100644
index 000000000000..6a24a5f0c04e
--- /dev/null
+++ b/dmake/winnt/borland/sysintf.h
@@ -0,0 +1,56 @@
+/* RCS $Id: sysintf.h,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- Interfaces for sysintf.c
+--
+-- DESCRIPTION
+-- Abstractions of functions in sysintf.c
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#define DMSTAT stat
+#define VOID_LCACHE(l,m)
+#define GETPID _psp
+#define Hook_std_writes(A)
+#define DMSTRLWR(A,B) dstrlwr((A),(B))
+
+extern char * tempnam();
+extern char * getcwd();
+
+/*
+** standard C items
+*/
+
+/*
+** DOS interface standard items
+*/
+#define chdir(p) dchdir(p)
+#define CacheStat(A,B) really_dostat(A,&buf)
+
+/*
+** make parameters
+*/
+#ifdef _POSIX_NAME_MAX
+#undef _POSIX_NAME_MAX
+#endif
+#define _POSIX_NAME_MAX 12
+
+#ifdef _POSIX_PATH_MAX
+#undef _POSIX_PATH_MAX
+#endif
+#define _POSIX_PATH_MAX 64
diff --git a/dmake/winnt/borland/tempnam.c b/dmake/winnt/borland/tempnam.c
new file mode 100644
index 000000000000..a7d0df8d962b
--- /dev/null
+++ b/dmake/winnt/borland/tempnam.c
@@ -0,0 +1,114 @@
+/* RCS $Id: tempnam.c,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- tempnam
+--
+-- DESCRIPTION
+-- temp file name generation routines.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/*LINTLIBRARY*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dos.h>
+
+#if defined(max)
+# undef max
+#endif
+#define max(A,B) (((A)<(B))?(B):(A))
+
+extern char *mktemp();
+extern int access();
+int d_access();
+
+/* Turbo C stdio.h doesn't define P_tmpdir, so let's do it here */
+/* Under DOS leave the default tmpdir pointing here! */
+#ifndef P_tmpdir
+static char *P_tmpdir = "";
+#endif
+
+char *
+tempnam(dir, prefix)
+char *dir; /* use this directory please (if non-NULL) */
+char *prefix; /* use this (if non-NULL) as filename prefix */
+{
+ static int count = 0;
+ register char *p, *q, *tmpdir;
+ int tl=0, dl=0, pl;
+ char buf[30];
+
+#if defined(__WIN32__)
+ unsigned int _psp = rand();
+#endif
+
+ pl = strlen(P_tmpdir);
+
+ if( (tmpdir = getenv("TMPDIR")) != NULL ) tl = strlen(tmpdir);
+ else if( (tmpdir = getenv("TMP")) != NULL ) tl = strlen(tmpdir);
+ if( dir != NULL ) dl = strlen(dir);
+
+ if( (p = malloc((unsigned)(max(max(dl,tl),pl)+13))) == NULL )
+ return(NULL);
+
+ *p = '\0';
+
+ if( (tl == 0) || (d_access( strcpy(p, tmpdir), 0) != 0) )
+ if( (dl == 0) || (d_access( strcpy(p, dir), 0) != 0) )
+ if( d_access( strcpy(p, P_tmpdir), 0) != 0 )
+ if( !prefix )
+ prefix = "tp";
+
+ if(prefix)
+ {
+ *(p+strlen(p)+2) = '\0';
+ (void)strncat(p, prefix, 2);
+ }
+
+ sprintf( buf, "%08x", _psp );
+ buf[6]='\0';
+ (void)strcat(p, buf );
+ sprintf( buf, "%04d", count++ );
+ q=p+strlen(p)-6;
+ *q++ = buf[0]; *q++ = buf[1];
+ *q++ = buf[2]; *q = buf[3];
+
+ if( (q = strrchr(p,'.')) != NULL ) *q = '\0';
+
+ return(p);
+}
+
+
+
+d_access( name, flag )
+char *name;
+int flag;
+{
+ extern char *DirSepStr;
+ char *p;
+ int r;
+
+ if( name == NULL || !*name ) return(1); /* NULL dir means current dir */
+ r = access( name, flag );
+ p = name+strlen(name)-1;
+
+ if(*p != '/' && *p != '\\') strcat( p, DirSepStr );
+
+ return( r );
+}
diff --git a/dmake/winnt/config.mk b/dmake/winnt/config.mk
new file mode 100644
index 000000000000..2abcb8ad66c6
--- /dev/null
+++ b/dmake/winnt/config.mk
@@ -0,0 +1,57 @@
+# This is an OS specific configuration file
+# It assumes that OBJDIR, TARGET and DEBUG are previously defined.
+# It defines CFLAGS, LDARGS, CPPFLAGS, STARTUPFILE, LDOBJS
+# It augments SRC, OBJDIR, TARGET, CFLAGS, LDLIBS
+#
+
+# Memory model to compile for
+# set to s - small, m - medium, c - compact, l - large
+# Need large model now, dmake has grown up :-)
+MODEL = l
+
+STARTUPFILE = startup/startup.mk
+
+CPPFLAGS = $(CFLAGS)
+
+# Debug flags
+DB_CFLAGS = -DDBUG
+DB_LDFLAGS =
+DB_LDLIBS =
+
+# NO Debug flags
+NDB_CFLAGS =
+NDB_LDFLAGS =
+NDB_LDLIBS =
+
+# Local configuration modifications for CFLAGS.
+CFLAGS += -I$(OS)
+
+# Common Win32 source files.
+OS_SRC += dchdir.c
+
+# Imported Win95 files.
+WIN95SRC += switchar.c
+
+# Imported MSDOS Files.
+DOSSRC += dstrlwr.c arlib.c dirbrk.c
+
+SRC += $(OS_SRC) $(UNIXSRC) $(DOSSRC)
+
+# Provide our own %$O : %$S rule.
+%$O : %$S
+ +$(AS) $(ASFLAGS) \
+ $(<:s,\,${__.DIVSEP-sh-${USESHELL}},:s,/,${__.DIVSEP-sh-${USESHELL}},);
+ mv $(@:f) $(OBJDIR)
+
+# Set source dirs so that we can find files named in this
+# config file.
+.SOURCE.h : $(OS)
+
+# See if we modify anything in the lower levels.
+.IF $(OSRELEASE) != $(NULL)
+ .INCLUDE : $(OS)$(DIRSEPSTR)$(OSRELEASE)$(DIRSEPSTR)config.mk
+.END
+
+.SETDIR=msdos : $(DOSSRC)
+.SETDIR=win95 : $(WIN95SRC)
+.SETDIR=$(OS) : $(ASRC) $(OS_SRC)
diff --git a/dmake/winnt/dchdir.c b/dmake/winnt/dchdir.c
new file mode 100644
index 000000000000..de2cf18041a8
--- /dev/null
+++ b/dmake/winnt/dchdir.c
@@ -0,0 +1,47 @@
+/* RCS $Id: dchdir.c,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- Change directory.
+--
+-- DESCRIPTION
+-- Under DOS change the current drive as well as the current directory.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <dir.h>
+#include <direct.h>
+#include "extern.h"
+
+PUBLIC int
+dchdir(path)
+char *path;
+{
+ int res;
+
+ res = chdir(path);
+
+ if (res != -1 && path[1] == ':') {
+ unsigned new_drive;
+
+ /* for WIN32 just use the _chdrive library call */
+ new_drive = (*path & ~0x20) - 'A' + 1;
+ _chdrive(new_drive);
+ }
+
+ return (res);
+}
diff --git a/dmake/winnt/microsft/config.h b/dmake/winnt/microsft/config.h
new file mode 100644
index 000000000000..9ecc029a51ef
--- /dev/null
+++ b/dmake/winnt/microsft/config.h
@@ -0,0 +1,78 @@
+/* RCS $Id: config.h,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- Configurarion include file.
+--
+-- DESCRIPTION
+-- There is one of these for each specific machine configuration.
+-- It can be used to further tweek the machine specific sources
+-- so that they compile.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#if defined (_MSC_VER)
+# if _MSC_VER < 500
+ Force a compile-time blowup.
+ Do not define "#define _MSC_VER" for MSC compilers earlier than 5.0.
+# endif
+#endif
+
+/* define this for configurations that don't have the coreleft function
+ * so that the code compiles. To my knowledge coreleft exists only on
+ * Turbo C, but it is needed here since the function is used in many debug
+ * macros. */
+#define coreleft() 0L
+
+/* MSC Version 4.0 doesn't understand SIGTERM, later versions do. */
+#ifndef SIGTERM
+# define SIGTERM SIGINT
+#endif
+
+/* Fixes unimplemented line buffering for MSC 5.x and 6.0.
+ * MSC _IOLBF is the same as _IOFBF
+ */
+#if defined(MSDOS) && defined (_MSC_VER)
+# undef _IOLBF
+# define _IOLBF _IONBF
+#endif
+
+/* in alloc.h: size_t is redefined
+ * defined in stdio.h which is included by alloc.h
+ */
+#if defined(MSDOS) && defined (_MSC_VER)
+# define _TYPES_
+#endif
+
+/* in sysintf.c: SIGQUIT is used, this is not defined in MSC */
+#ifndef SIGQUIT
+# define SIGQUIT SIGTERM
+#endif
+
+/* MSC doesn't seem to care about CONST */
+#define CONST
+
+#ifndef MSDOS
+# define MSDOS 1
+#endif
+
+/* a small problem with pointer to voids on some unix machines needs this */
+#define PVOID void *
+
+/* Use my own tempnam */
+#define tempnam dtempnam
+
diff --git a/dmake/winnt/microsft/config.mk b/dmake/winnt/microsft/config.mk
new file mode 100644
index 000000000000..352eed716d2f
--- /dev/null
+++ b/dmake/winnt/microsft/config.mk
@@ -0,0 +1,61 @@
+# This is the MSC 4.0 and higher DOS configuration file for DMAKE
+# It simply modifies the values of SRC, and checks to see if
+# OSENVIRONMENT is defined. If so it includes the appropriate
+# config.mk file.
+#
+# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
+# directory.
+#
+osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
+
+TMPDIR :=
+.EXPORT : TMPDIR
+
+# Definition of macros for library, and C startup code.
+
+# The following sources are required for MSC
+OSR_SRC += tempnam.c ruletab.c
+DOS_SRC += runargv.c rmprq.c
+
+.SETDIR=$(osrdir) : $(OSR_SRC)
+.SETDIR=msdos : $(DOS_SRC)
+
+SRC += $(OSR_SRC) $(DOS_SRC)
+.SOURCE.h : $(osrdir)
+
+SET_STACK = /stack:4096
+ASFLAGS += -t -mx $(S_$(MODEL))
+
+# Microsoft C doesn't need tail but needs head
+LDTAIL !=
+LDHEAD != $(LDFLAGS)
+LDARGS != $(LDHEAD) -out:$(TARGET) @$(LDTMPOBJ) $(LDTAIL)
+LDTAIL != $(_libs)
+_libs != $(!null,$(LDLIBS) ,@$(LDTMPLIB))
+LDTMPOBJ != $(mktmp,,$(DIVFILE) $(LDOBJS:s,/,\\,:t"\n")\n)
+LDTMPLIB != $(mktmp,,$(DIVFILE) $(LDLIBS:s,/,\\,:t"\n")\n)
+
+# Debugging libraries and flags
+DB_LDFLAGS += /nologo /co /li /map
+DB_LDLIBS +=
+DB_CFLAGS += -Zi
+
+# NO Debug MSC flags:
+# Set the environment variable MSC_VER to be one of 5.1, 6.0, 8.0 (for VC++4.0)
+# to get these by default when you make dmake using 'dmake'.
+#
+
+NDB_LDFLAGS += /nologo
+CFLAGS += -I$(osrdir)
+
+# See if we modify anything in the lower levels.
+.IF $(OSENVIRONMENT) != $(NULL)
+ .INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
+.END
+
+CFLAGS += /nologo
+
+S_s = -Dmsmall
+S_m = -Dmmedium
+S_c = -Dmcompact
+S_l = -Dmlarge
diff --git a/dmake/winnt/microsft/optoff.h b/dmake/winnt/microsft/optoff.h
new file mode 100644
index 000000000000..7dd3cb839572
--- /dev/null
+++ b/dmake/winnt/microsft/optoff.h
@@ -0,0 +1,27 @@
+/* RCS $Id: optoff.h,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- Turn off microsoft loop optimization.
+--
+-- DESCRIPTION
+-- This is broken in some pre 600 compilers so just turn it off.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+#if _MSC_VER < 600
+# pragma loop_opt(off)
+#endif
diff --git a/dmake/winnt/microsft/ruletab.c b/dmake/winnt/microsft/ruletab.c
new file mode 100644
index 000000000000..6c7febfddf64
--- /dev/null
+++ b/dmake/winnt/microsft/ruletab.c
@@ -0,0 +1,45 @@
+/* RCS $Id: ruletab.c,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- Default initial configuration of dmake.
+--
+-- DESCRIPTION
+-- Define here the initial set of rules that are defined before
+-- dmake performs any processing.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/* These are control macros for dmake that MUST be defined at some point
+ * if they are NOT dmake will not work! These are default definitions. They
+ * may be overridden inside the .STARTUP makefile, they are here
+ * strictly so that dmake can parse the STARTUP makefile */
+
+#include <stdio.h>
+
+static char *_rules[] = {
+ "MAXLINELENGTH := 2046",
+ "MAXPROCESSLIMIT := 4",
+ "MAXPROCESS := 1",
+ ".IMPORT .IGNORE: DMAKEROOT SOLARVER UPD INPATH OS UPDMINOREXT"
+ ".MAKEFILES : makefile.mk makefile",
+ ".SOURCE : .NULL",
+#include "startup.h"
+ (char *)NULL };
+
+char **Rule_tab = _rules; /* for sundry reasons in Get_environment() */
+
diff --git a/dmake/winnt/microsft/sysintf.h b/dmake/winnt/microsft/sysintf.h
new file mode 100644
index 000000000000..86607fd6d7dc
--- /dev/null
+++ b/dmake/winnt/microsft/sysintf.h
@@ -0,0 +1,58 @@
+/* RCS $Id: sysintf.h,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- Interfaces for sysintf.c
+--
+-- DESCRIPTION
+-- Abstractions of functions in sysintf.c
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#define DMSTAT stat
+#define VOID_LCACHE(l,m)
+#define GETPID _psp
+#define Hook_std_writes(A)
+#define DMSTRLWR(A,B) dstrlwr((A),(B))
+
+extern char * tempnam();
+extern char * getcwd();
+
+/* for directory cache */
+#define CacheStat(A,B) really_dostat(A,&buf)
+
+/*
+** standard C items
+*/
+
+/*
+** DOS interface standard items
+*/
+#define chdir(p) dchdir(p)
+
+/*
+** make parameters
+*/
+#ifdef _POSIX_NAME_MAX
+#undef _POSIX_NAME_MAX
+#endif
+#define _POSIX_NAME_MAX 12
+
+#ifdef _POSIX_PATH_MAX
+#undef _POSIX_PATH_MAX
+#endif
+#define _POSIX_PATH_MAX 64
diff --git a/dmake/winnt/microsft/tempnam.c b/dmake/winnt/microsft/tempnam.c
new file mode 100644
index 000000000000..c3a8fa140f29
--- /dev/null
+++ b/dmake/winnt/microsft/tempnam.c
@@ -0,0 +1,110 @@
+/* RCS $Id: tempnam.c,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- tempnam
+--
+-- DESCRIPTION
+-- temp file name generation routines.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/*LINTLIBRARY*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <process.h>
+
+#if defined(max)
+# undef max
+#endif
+#define max(A,B) (((A)<(B))?(B):(A))
+
+extern char *mktemp();
+extern int access();
+int d_access();
+
+/* MSC stdio.h defines P_tmpdir, so let's undo it here */
+/* Under DOS leave the default tmpdir pointing here! */
+#ifdef P_tmpdir
+#undef P_tmpdir
+#endif
+static char *P_tmpdir = "";
+
+char *
+dtempnam(dir, prefix)
+char *dir; /* use this directory please (if non-NULL) */
+char *prefix; /* use this (if non-NULL) as filename prefix */
+{
+ static int count = 0;
+ register char *p, *q, *tmpdir;
+ int tl=0, dl=0, pl;
+ char buf[30];
+
+ pl = strlen(P_tmpdir);
+
+ if( (tmpdir = getenv("TMPDIR")) != NULL ) tl = strlen(tmpdir);
+ else if( (tmpdir = getenv("TMP")) != NULL ) tl = strlen(tmpdir);
+ if( dir != NULL ) dl = strlen(dir);
+
+ if( (p = malloc((unsigned)(max(max(dl,tl),pl)+13))) == NULL )
+ return(NULL);
+
+ *p = '\0';
+
+ if( (tl == 0) || (d_access( strcpy(p, tmpdir), 0) != 0) )
+ if( (dl == 0) || (d_access( strcpy(p, dir), 0) != 0) )
+ if( d_access( strcpy(p, P_tmpdir), 0) != 0 )
+ if( !prefix )
+ prefix = "tp";
+
+ if(prefix)
+ {
+ *(p+strlen(p)+2) = '\0';
+ (void)strncat(p, prefix, 2);
+ }
+
+ sprintf( buf, "%08x", getpid() );
+ buf[6]='\0';
+ (void)strcat(p, buf );
+ sprintf( buf, "%04d", count++ );
+ q=p+strlen(p)-6;
+ *q++ = buf[0]; *q++ = buf[1];
+ *q++ = buf[2]; *q++ = buf[3];
+
+ if( (q = strrchr(p,'.')) != NULL ) *q = '\0';
+
+ return(p);
+}
+
+
+
+d_access( name, flag )
+char *name;
+int flag;
+{
+ extern char *DirSepStr;
+ char *p;
+ int r;
+
+ if( name == NULL || !*name ) return(1); /* NULL dir means current dir */
+ r = access( name, flag );
+ p = name+strlen(name)-1;
+ if(*p != '/' && *p != '\\') strcat( p, DirSepStr );
+
+ return( r );
+}
diff --git a/dmake/winnt/microsft/vpp40/config.mk b/dmake/winnt/microsft/vpp40/config.mk
new file mode 100644
index 000000000000..14fe952eac00
--- /dev/null
+++ b/dmake/winnt/microsft/vpp40/config.mk
@@ -0,0 +1,14 @@
+# Definition of macros for library, and C startup code.
+osedir = $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)
+
+.IMPORT .IGNORE : MSC_VER
+MSC_VER *= 8.0
+
+CFLAGS += -I$(osedir)
+
+NDB_CFLAGS += -Od -GF -Ge
+NDB_LDFLAGS +=
+NDB_LDLIBS +=
+
+# Redefine rule for making our objects, we don't need mv
+%$O : %.c ;% $(CC) -c $(CFLAGS) -Fo$@ $<
diff --git a/dmake/winnt/microsft/vpp40/lib.rsp b/dmake/winnt/microsft/vpp40/lib.rsp
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/dmake/winnt/microsft/vpp40/lib.rsp
@@ -0,0 +1 @@
+
diff --git a/dmake/winnt/microsft/vpp40/mk.bat b/dmake/winnt/microsft/vpp40/mk.bat
new file mode 100755
index 000000000000..22917df5eaee
--- /dev/null
+++ b/dmake/winnt/microsft/vpp40/mk.bat
@@ -0,0 +1,32 @@
+md objects
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\infer.obj infer.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\make.obj make.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\stat.obj stat.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\expand.obj expand.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\dmstring.obj dmstring.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\hash.obj hash.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\dag.obj dag.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\dmake.obj dmake.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\path.obj path.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\imacs.obj imacs.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\sysintf.obj sysintf.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\parse.obj parse.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\getinp.obj getinp.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\quit.obj quit.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\state.obj state.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\dmdump.obj dmdump.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\macparse.obj macparse.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\rulparse.obj rulparse.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\percent.obj percent.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\function.obj function.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\dchdir.obj win95\dchdir.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\switchar.obj win95\switchar.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\dstrlwr.obj msdos\dstrlwr.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\arlib.obj msdos\arlib.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\dirbrk.obj msdos\dirbrk.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\tempnam.obj tempnam.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\ruletab.obj win95\microsft\ruletab.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\runargv.obj msdos\runargv.c
+cl -c -I. -Iwin95 -Iwin95\microsft -Iwin95\microsft\vpp40 \nologo -Od -GF -Ge -Foobjects\rmprq.obj msdos\rmprq.c
+rem link /nologo @win95\microsft\vpp40\obj.rsp,dmake.exe,NUL.MAP;
+link /out:dmake.exe @.\win95\microsft\vpp40\obj.rsp
diff --git a/dmake/winnt/microsft/vpp40/mk.cmd b/dmake/winnt/microsft/vpp40/mk.cmd
new file mode 100755
index 000000000000..5fcc801fae91
--- /dev/null
+++ b/dmake/winnt/microsft/vpp40/mk.cmd
@@ -0,0 +1,31 @@
+md objects
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\infer.obj infer.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\make.obj make.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\stat.obj stat.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\expand.obj expand.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\dmstring.obj dmstring.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\hash.obj hash.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\dag.obj dag.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\dmake.obj dmake.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\path.obj path.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\imacs.obj imacs.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\sysintf.obj sysintf.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\parse.obj parse.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\getinp.obj getinp.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\quit.obj quit.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\state.obj state.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\dmdump.obj dmdump.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\macparse.obj macparse.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\rulparse.obj rulparse.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\percent.obj percent.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\function.obj function.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\dchdir.obj winnt\dchdir.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\dstrlwr.obj msdos\dstrlwr.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\arlib.obj msdos\arlib.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\dirbrk.obj msdos\dirbrk.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\tempnam.obj winnt\microsft\tempnam.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\ruletab.obj winnt\microsft\ruletab.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\runargv.obj msdos\runargv.c
+cl -c -I. -Iwinnt -Iwinnt\microsft -Iwinnt\microsft\vpp40 /nologo -Od -GF -Ge -Foobjects\rmprq.obj msdos\rmprq.c
+link /nologo /out:dmake.exe @fix95nt\winnt\microsft\vpp40\obj.rsp
+copy winnt\microsft\vpp40\template.mk startup\config.mk
diff --git a/dmake/winnt/microsft/vpp40/obj.rsp b/dmake/winnt/microsft/vpp40/obj.rsp
new file mode 100644
index 000000000000..5c00dab6c29c
--- /dev/null
+++ b/dmake/winnt/microsft/vpp40/obj.rsp
@@ -0,0 +1,28 @@
+objects\infer.obj
+objects\make.obj
+objects\stat.obj
+objects\expand.obj
+objects\dmstring.obj
+objects\hash.obj
+objects\dag.obj
+objects\dmake.obj
+objects\path.obj
+objects\imacs.obj
+objects\sysintf.obj
+objects\parse.obj
+objects\getinp.obj
+objects\quit.obj
+objects\state.obj
+objects\dmdump.obj
+objects\macparse.obj
+objects\rulparse.obj
+objects\percent.obj
+objects\function.obj
+objects\dchdir.obj
+objects\dstrlwr.obj
+objects\arlib.obj
+objects\dirbrk.obj
+objects\tempnam.obj
+objects\ruletab.obj
+objects\runargv.obj
+objects\rmprq.obj
diff --git a/dmake/winnt/microsft/vpp40/public.h b/dmake/winnt/microsft/vpp40/public.h
new file mode 100644
index 000000000000..f867838344c5
--- /dev/null
+++ b/dmake/winnt/microsft/vpp40/public.h
@@ -0,0 +1,166 @@
+/* RCS $Id: public.h,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
+--
+--
+-- SYNOPSIS
+-- Local functions exported to be visible by others.
+--
+-- DESCRIPTION
+-- This file is generated by 'genpub'. Function declarations
+-- that appear in this file are extracted by 'genpub' from
+-- source files. Any function in the source file whose definition
+-- appears like:
+--
+-- PUBLIC return_type
+-- function( arg_list );
+-- type_expr1 arg1;
+-- ...
+--
+-- has its definition extracted and a line of the form:
+--
+-- return_type function ANSI((type_expr1,type_expr2,...));
+--
+-- entered into the output file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#ifndef _DMAKE_PUBLIC_h
+#define _DMAKE_PUBLIC_h
+
+#ifdef EXTERN
+#undef EXTERN
+#endif
+#if defined(DEFINE_DMAKE_VARIABLES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/***** genpub: Begin list of generated function headers */
+void Infer_recipe ANSI((CELLPTR, CELLPTR));
+int Make_targets ANSI(());
+int Make ANSI((CELLPTR, CELLPTR));
+int Exec_commands ANSI((CELLPTR));
+void Print_cmnd ANSI((char *, int, int));
+int Push_dir ANSI((char *, char *, int));
+void Pop_dir ANSI((int));
+void Append_line ANSI((char *, int, FILE *, char *, int, int));
+void Stat_target ANSI((CELLPTR, int, int));
+char *Expand ANSI((char *));
+char *Apply_edit ANSI((char *, char *, char *, int, int));
+void Map_esc ANSI((char *));
+char* Apply_modifiers ANSI((int, char *));
+char* Tokenize ANSI((char *, char *, char, int));
+char* ScanToken ANSI((char *, char **, int));
+char *DmStrJoin ANSI((char *, char *, int, int));
+char *DmStrAdd ANSI((char *, char *, int));
+char *DmStrApp ANSI((char *, char *));
+char *DmStrDup ANSI((char *));
+char *DmStrDup2 ANSI((char *));
+char *DmStrPbrk ANSI((char *, char *));
+char *DmStrSpn ANSI((char *, char *));
+char *DmStrStr ANSI((char *, char *));
+char *DmSubStr ANSI((char *, char *));
+uint16 Hash ANSI((char *, uint32 *));
+HASHPTR Get_name ANSI((char *, HASHPTR *, int));
+HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
+HASHPTR Push_macro ANSI((HASHPTR));
+HASHPTR Pop_macro ANSI((HASHPTR));
+HASHPTR Def_macro ANSI((char *, char *, int));
+CELLPTR Def_cell ANSI((char *));
+LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
+void Clear_prerequisites ANSI((CELLPTR));
+int Test_circle ANSI((CELLPTR, int));
+STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
+t_attr Rcp_attribute ANSI((char *));
+void main ANSI((int, char **));
+FILE *Openfile ANSI((char *, int, int));
+FILE *Closefile ANSI(());
+FILE *Search_file ANSI((char *, char **));
+char *Filename ANSI(());
+int Nestlevel ANSI(());
+FILE *TryFiles ANSI((LINKPTR));
+void Fatal ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Error ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void Warning ANSI((ARG (char *,fmt),ARG (va_alist_type, va_alist)));
+void No_ram ANSI(());
+void Usage ANSI((int));
+void Version ANSI(());
+char *Get_suffix ANSI((char *));
+char *Basename ANSI((char *));
+char *Filedir ANSI((char *));
+char *Build_path ANSI((char *, char *));
+void Make_rules ANSI(());
+void Create_macro_vars ANSI(());
+time_t Do_stat ANSI((char *, char *, char **, int));
+int Do_touch ANSI((char *, char *, char **));
+void Void_lib_cache ANSI((char *, char *));
+time_t Do_time ANSI(());
+int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
+char ** Pack_argv ANSI((int, int, char *));
+char *Read_env_string ANSI((char *));
+int Write_env_string ANSI((char *, char *));
+void ReadEnvironment ANSI(());
+void Catch_signals ANSI((void (*)()));
+void Clear_signals ANSI(());
+void Prolog ANSI((int, char* []));
+void Epilog ANSI((int));
+char *Get_current_dir ANSI(());
+int Set_dir ANSI((char*));
+char Get_switch_char ANSI(());
+FILE* Get_temp ANSI((char **, char *, int));
+FILE *Start_temp ANSI((char *, CELLPTR, char **));
+void Open_temp_error ANSI((char *, char *));
+void Link_temp ANSI((CELLPTR, FILE *, char *));
+void Close_temp ANSI((CELLPTR, FILE *));
+void Unlink_temp_files ANSI((CELLPTR));
+void Handle_result ANSI((int, int, int, CELLPTR));
+void Update_time_stamp ANSI((CELLPTR));
+int Remove_file ANSI((char *));
+void Parse ANSI((FILE *));
+int Get_line ANSI((char *, FILE *));
+char *Do_comment ANSI((char *, char **, int));
+char *Get_token ANSI((TKSTRPTR, char *, int));
+void Quit ANSI(());
+void Read_state ANSI(());
+void Write_state ANSI(());
+int Check_state ANSI((CELLPTR, STRINGPTR *, int));
+void Dump ANSI(());
+void Dump_recipe ANSI((STRINGPTR));
+int Parse_macro ANSI((char *, int));
+int Macro_op ANSI((char *));
+int Parse_rule_def ANSI((int *));
+int Rule_op ANSI((char *));
+void Add_recipe_to_list ANSI((char *, int, int));
+void Bind_rules_to_targets ANSI((int));
+int Set_group_attributes ANSI((char *));
+DFALINKPTR Match_dfa ANSI((char *));
+void Check_circle_dfa ANSI(());
+void Add_nfa ANSI((char *));
+char *Exec_function ANSI((char *));
+int dchdir ANSI((char *));
+void dstrlwr ANSI((char *, char *));
+time_t seek_arch ANSI((char*, char*));
+int touch_arch ANSI((char*, char*));
+int If_root_path ANSI((char *));
+int runargv ANSI((CELLPTR, int, int, int, int, char *));
+void Clean_up_processes ANSI(());
+int Wait_for_child ANSI((int, int));
+void Remove_prq ANSI((CELLPTR));
+
+#endif
diff --git a/dmake/winnt/microsft/vpp40/runargv.c b/dmake/winnt/microsft/vpp40/runargv.c
new file mode 100644
index 000000000000..fd0cbe355109
--- /dev/null
+++ b/dmake/winnt/microsft/vpp40/runargv.c
@@ -0,0 +1,290 @@
+Blake sent me the wrong one.
+
+/* RCS $Id: runargv.c,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- Invoke a sub process.
+--
+-- DESCRIPTION
+-- Use the standard methods of executing a sub process.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+#include <process.h>
+#include <errno.h>
+#include <signal.h>
+#include "extern.h"
+#include "sysintf.h"
+
+extern char **environ;
+
+typedef struct prp {
+ char *prp_cmd;
+ int prp_group;
+ int prp_ignore;
+ int prp_last;
+ int prp_shell;
+ struct prp *prp_next;
+} RCP, *RCPPTR;
+
+typedef struct pr {
+ int pr_valid;
+ int pr_pid;
+ CELLPTR pr_target;
+ int pr_ignore;
+ int pr_last;
+ RCPPTR pr_recipe;
+ RCPPTR pr_recipe_end;
+ char *pr_dir;
+} PR;
+
+static PR *_procs = NIL(PR);
+static int _proc_cnt = 0;
+static int _abort_flg= FALSE;
+static int _use_i = -1;
+static int _do_upd = 0;
+
+static void _add_child ANSI((int, CELLPTR, int, int));
+static void _attach_cmd ANSI((char *, int, int, CELLPTR, int, int));
+static void _finished_child ANSI((int, int));
+static int _running ANSI((CELLPTR));
+
+PUBLIC int
+runargv(target, ignore, group, last, shell, cmd)
+CELLPTR target;
+int ignore;
+int group;
+int last;
+int shell;
+char *cmd;
+{
+ extern int errno;
+ extern char *sys_errlist[];
+ int pid;
+ char **argv;
+
+ if( _running(target) /*&& Max_proc != 1*/ ) {
+ /* The command will be executed when the previous recipe
+ * line completes. */
+ _attach_cmd( cmd, group, ignore, target, last, shell );
+ return(1);
+ }
+
+ while( _proc_cnt == Max_proc )
+ if( Wait_for_child(FALSE, -1) == -1 ) Fatal( "Lost a child %d", errno );
+
+ argv = Pack_argv( group, shell, cmd );
+
+ pid = _spawnvpe(_P_NOWAIT, argv[0], argv, environ);
+ if (pid == -1) { /* failed */
+ Error("%s: %s", argv[0], sys_errlist[errno]);
+ Handle_result(-1, ignore, _abort_flg, target);
+ return(-1);
+ } else
+ _add_child(pid, target, ignore, last);
+
+ return(1);
+}
+
+
+PUBLIC int
+Wait_for_child( abort_flg, pid )
+int abort_flg;
+int pid;
+{
+ int wid;
+ int status;
+ int waitchild;
+
+ waitchild = (pid == -1)? FALSE : Wait_for_completion;
+
+ do {
+ if( (wid = wait(&status)) == -1 ) return(-1);
+
+ _abort_flg = abort_flg;
+ _finished_child(wid, status);
+ _abort_flg = FALSE;
+ } while( waitchild && pid != wid );
+
+ return(0);
+}
+
+
+PUBLIC void
+Clean_up_processes()
+{
+ register int i;
+
+ if( _procs != NIL(PR) ) {
+ for( i=0; i<Max_proc; i++ )
+ if( _procs[i].pr_valid )
+ kill(_procs[i].pr_pid, SIGTERM);
+
+ while( Wait_for_child(TRUE, -1) != -1 );
+ }
+}
+
+
+static void
+_add_child( pid, target, ignore, last )
+int pid;
+CELLPTR target;
+int ignore;
+int last;
+{
+ register int i;
+ register PR *pp;
+
+ if( _procs == NIL(PR) ) {
+ TALLOC( _procs, Max_proc, PR );
+ }
+
+ if( (i = _use_i) == -1 )
+ for( i=0; i<Max_proc; i++ )
+ if( !_procs[i].pr_valid )
+ break;
+
+ pp = _procs+i;
+
+ pp->pr_valid = 1;
+ pp->pr_pid = pid;
+ pp->pr_target = target;
+ pp->pr_ignore = ignore;
+ pp->pr_last = last;
+ pp->pr_dir = DmStrDup(Get_current_dir());
+
+ Current_target = NIL(CELL);
+
+ _proc_cnt++;
+
+ if( Wait_for_completion ) Wait_for_child( FALSE, pid );
+}
+
+
+static void
+_finished_child(pid, status)
+int pid;
+int status;
+{
+ register int i;
+ register PR *pp;
+ char *dir;
+
+ for( i=0; i<Max_proc; i++ )
+ if( _procs[i].pr_valid && _procs[i].pr_pid == pid )
+ break;
+
+ /* Some children we didn't make esp true if using /bin/sh to execute a
+ * a pipe and feed the output as a makefile into dmake. */
+ if( i == Max_proc ) return;
+ _procs[i].pr_valid = 0;
+ _proc_cnt--;
+ dir = DmStrDup(Get_current_dir());
+ Set_dir( _procs[i].pr_dir );
+
+ if( _procs[i].pr_recipe != NIL(RCP) && !_abort_flg ) {
+ RCPPTR rp = _procs[i].pr_recipe;
+
+
+ Current_target = _procs[i].pr_target;
+ Handle_result( status, _procs[i].pr_ignore, FALSE, _procs[i].pr_target );
+ Current_target = NIL(CELL);
+
+ if ( _procs[i].pr_target->ce_attr & A_ERROR ) {
+ Unlink_temp_files( _procs[i].pr_target );
+ _procs[i].pr_last = TRUE;
+ goto ABORT_REMAINDER_OF_RECIPE;
+ }
+
+ _procs[i].pr_recipe = rp->prp_next;
+
+ _use_i = i;
+ runargv( _procs[i].pr_target, rp->prp_ignore, rp->prp_group,
+ rp->prp_last, rp->prp_shell, rp->prp_cmd );
+ _use_i = -1;
+
+ FREE( rp->prp_cmd );
+ FREE( rp );
+
+ if( _proc_cnt == Max_proc ) Wait_for_child( FALSE, -1 );
+ }
+ else {
+ Unlink_temp_files( _procs[i].pr_target );
+ Handle_result(status,_procs[i].pr_ignore,_abort_flg,_procs[i].pr_target);
+
+ ABORT_REMAINDER_OF_RECIPE:
+ if( _procs[i].pr_last ) {
+ FREE(_procs[i].pr_dir );
+
+ if( !Doing_bang ) Update_time_stamp( _procs[i].pr_target );
+ }
+ }
+
+ Set_dir(dir);
+ FREE(dir);
+}
+
+
+static int
+_running( cp )
+CELLPTR cp;
+{
+ register int i;
+
+ if( !_procs ) return(FALSE);
+
+ for( i=0; i<Max_proc; i++ )
+ if( _procs[i].pr_valid &&
+ _procs[i].pr_target == cp )
+ break;
+
+ return( i != Max_proc );
+}
+
+
+static void
+_attach_cmd( cmd, group, ignore, cp, last, shell )
+char *cmd;
+int group;
+int ignore;
+CELLPTR cp;
+int last;
+int shell;
+{
+ register int i;
+ RCPPTR rp;
+
+ for( i=0; i<Max_proc; i++ )
+ if( _procs[i].pr_valid &&
+ _procs[i].pr_target == cp )
+ break;
+
+ TALLOC( rp, 1, RCP );
+ rp->prp_cmd = DmStrDup(cmd);
+ rp->prp_group = group;
+ rp->prp_ignore= ignore;
+ rp->prp_last = last;
+ rp->prp_shell = shell;
+
+ if( _procs[i].pr_recipe == NIL(RCP) )
+ _procs[i].pr_recipe = _procs[i].pr_recipe_end = rp;
+ else {
+ _procs[i].pr_recipe_end->prp_next = rp;
+ _procs[i].pr_recipe_end = rp;
+ }
+}
diff --git a/dmake/winnt/microsft/vpp40/template.mk b/dmake/winnt/microsft/vpp40/template.mk
new file mode 100644
index 000000000000..e53922df68c3
--- /dev/null
+++ b/dmake/winnt/microsft/vpp40/template.mk
@@ -0,0 +1,7 @@
+# ** Default build configuration for dmake.
+# ** DO NOT PLACE LOCAL DEFINITIONS INTO THIS FILE IT IS AUTO GENERATED
+# ** USE "startup/local.mk" for those.
+
+ OS *:= winnt
+ OSRELEASE *:= microsft
+ OSENVIRONMENT *:= vpp40
diff --git a/dmake/winnt/microsft/vpp40/tempnam.c b/dmake/winnt/microsft/vpp40/tempnam.c
new file mode 100644
index 000000000000..c27da47c7602
--- /dev/null
+++ b/dmake/winnt/microsft/vpp40/tempnam.c
@@ -0,0 +1,110 @@
+/* RCS $Id: tempnam.c,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- tempnam
+--
+-- DESCRIPTION
+-- temp file name generation routines.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/*LINTLIBRARY*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dos.h>
+
+#if defined(max)
+# undef max
+#endif
+#define max(A,B) (((A)<(B))?(B):(A))
+
+extern char *mktemp();
+extern int access();
+int d_access();
+
+/* MSC stdio.h defines P_tmpdir, so let's undo it here */
+/* Under DOS leave the default tmpdir pointing here! */
+#ifdef P_tmpdir
+#undef P_tmpdir
+#endif
+static char *P_tmpdir = "";
+
+char *
+tempnam(dir, prefix)
+char *dir; /* use this directory please (if non-NULL) */
+char *prefix; /* use this (if non-NULL) as filename prefix */
+{
+ static int count = 0;
+ register char *p, *q, *tmpdir;
+ int tl=0, dl=0, pl;
+ char buf[30];
+
+ pl = strlen(P_tmpdir);
+
+ if( (tmpdir = getenv("TMPDIR")) != NULL ) tl = strlen(tmpdir);
+ else if( (tmpdir = getenv("TMP")) != NULL ) tl = strlen(tmpdir);
+ if( dir != NULL ) dl = strlen(dir);
+
+ if( (p = malloc((unsigned)(max(max(dl,tl),pl)+13))) == NULL )
+ return(NULL);
+
+ *p = '\0';
+
+ if( (tl == 0) || (d_access( strcpy(p, tmpdir), 0) != 0) )
+ if( (dl == 0) || (d_access( strcpy(p, dir), 0) != 0) )
+ if( d_access( strcpy(p, P_tmpdir), 0) != 0 )
+ if( !prefix )
+ prefix = "tp";
+
+ if(prefix)
+ {
+ *(p+strlen(p)+2) = '\0';
+ (void)strncat(p, prefix, 2);
+ }
+
+ sprintf( buf, "%08x", _psp );
+ buf[6]='\0';
+ (void)strcat(p, buf );
+ sprintf( buf, "%04d", count++ );
+ q=p+strlen(p)-6;
+ *q++ = buf[0]; *q++ = buf[1];
+ *q++ = buf[2]; *q++ = buf[3];
+
+ if( (q = strrchr(p,'.')) != NULL ) *q = '\0';
+
+ return(p);
+}
+
+
+
+d_access( name, flag )
+char *name;
+int flag;
+{
+ extern char *DirSepStr;
+ char *p;
+ int r;
+
+ if( name == NULL || !*name ) return(1); /* NULL dir means current dir */
+ r = access( name, flag );
+ p = name+strlen(name)-1;
+ if(*p != '/' && *p != '\\') strcat( p, DirSepStr );
+
+ return( r );
+}
diff --git a/dmake/winnt/startup.h b/dmake/winnt/startup.h
new file mode 100644
index 000000000000..d1bfdb5688e4
--- /dev/null
+++ b/dmake/winnt/startup.h
@@ -0,0 +1,29 @@
+/* RCS $Id: startup.h,v 1.1.1.1 2000-09-22 15:33:37 hr Exp $
+--
+-- SYNOPSIS
+-- Definition of MAKESTARTUP
+--
+-- DESCRIPTION
+-- Default MAKESTARTUP value defining where dmake locates the
+-- startup file.
+--
+-- AUTHOR
+-- Dennis Vadura, dvadura@dmake.wticorp.com
+--
+-- WWW
+-- http://dmake.wticorp.com/
+--
+-- COPYRIGHT
+-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
+--
+-- This program is NOT free software; you can redistribute it and/or
+-- modify it under the terms of the Software License Agreement Provided
+-- in the file <distribution-root>/readme/license.txt.
+--
+-- LOG
+-- Use cvs log to obtain detailed change logs.
+*/
+
+/*"MAKESTARTUP := $(MAKECMD:d)startup/startup.mk",*/
+"MAKESTARTUP := $(DMAKEROOT)\\startup.mk",
+