From 48f940a1d9d631a98c27b675d5d6dc2c50c50eaf Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Sun, 14 May 2017 19:59:26 -0500 Subject: [PATCH] GNO dmake 1.0.0 sources, converted to LF line endings. --- dmake/LICENSE | 248 +++ dmake/_install | 219 ++ dmake/alloc.h | 71 + dmake/basename.c | 55 + dmake/dag.c | 497 +++++ dmake/db.h | 75 + dmake/dbug/README | 13 + dmake/dbug/dbug.mk | 66 + dmake/dbug/dbug/README | 6 + dmake/dbug/dbug/dbug.c | 1832 +++++++++++++++++ dmake/dbug/dbug/dbug.h | 164 ++ dmake/dbug/dbug/dbug.uue | 368 ++++ dmake/dbug/getwd.c | 6 + dmake/dbug/malloc/Makefile | 77 + dmake/dbug/malloc/_changes | 9 + dmake/dbug/malloc/_readme | 133 ++ dmake/dbug/malloc/calloc.c | 73 + dmake/dbug/malloc/debug.h | 111 ++ dmake/dbug/malloc/dump.c | 124 ++ dmake/dbug/malloc/free.c | 188 ++ dmake/dbug/malloc/m_init.c | 103 + dmake/dbug/malloc/m_perror.c | 93 + dmake/dbug/malloc/malloc.3 | 223 +++ dmake/dbug/malloc/malloc.c | 654 ++++++ dmake/dbug/malloc/malloc.h | 103 + dmake/dbug/malloc/mallopt.c | 125 ++ dmake/dbug/malloc/memory.c | 225 +++ dmake/dbug/malloc/mlc_chk.c | 279 +++ dmake/dbug/malloc/mlc_chn.c | 188 ++ dmake/dbug/malloc/patchlevel | 1 + dmake/dbug/malloc/realloc.c | 215 ++ dmake/dbug/malloc/string.c | 563 ++++++ dmake/dbug/malloc/testmem.c | 646 ++++++ dmake/dbug/malloc/testmlc.c | 176 ++ dmake/dbug/malloc/tostring.c | 151 ++ dmake/dbug/malloc/tostring.h | 25 + dmake/dmake.c | 818 ++++++++ dmake/dmake.h | 183 ++ dmake/dmdump.c | 209 ++ dmake/dmstring.c | 302 +++ dmake/expand.c | 921 +++++++++ dmake/extern.h | 78 + dmake/function.c | 356 ++++ dmake/getinp.c | 531 +++++ dmake/hash.c | 61 + dmake/imacs.c | 172 ++ dmake/infer.c | 822 ++++++++ dmake/itypes.h | 56 + dmake/mac/arlib.c | 58 + dmake/mac/bogus.c | 92 + dmake/mac/config.h | 87 + dmake/mac/config.mk | 44 + dmake/mac/dirbrk.c | 52 + dmake/mac/directry.c | 270 +++ dmake/mac/dompwmak | 54 + dmake/mac/environ.c | 236 +++ dmake/mac/eold.c | 128 ++ dmake/mac/main.c | 52 + dmake/mac/make.sh | 43 + dmake/mac/public.h | 152 ++ dmake/mac/rmprq.c | 47 + dmake/mac/ruletab.c | 52 + dmake/mac/startup.h | 7 + dmake/mac/startup.mk | 126 ++ dmake/mac/sysintf.h | 23 + dmake/mac/tempnam.c | 72 + dmake/mac/tomacfil.c | 114 ++ dmake/macparse.c | 167 ++ dmake/make.bat | 165 ++ dmake/make.c | 1028 ++++++++++ dmake/make.cmd | 53 + dmake/makefile | 73 + dmake/makefile.mk | 342 ++++ dmake/man/README | 9 + dmake/man/dmake.nc | 3200 ++++++++++++++++++++++++++++++ dmake/man/dmake.tf | 2732 +++++++++++++++++++++++++ dmake/man/dmake.uue | 1248 ++++++++++++ dmake/msdos/_chdir.c | 67 + dmake/msdos/arlib.c | 65 + dmake/msdos/bccdos/config.h | 54 + dmake/msdos/bccdos/config.mk | 50 + dmake/msdos/bccdos/lib.rsp | 1 + dmake/msdos/bccdos/libswp.rsp | 1 + dmake/msdos/bccdos/mk.bat | 96 + dmake/msdos/bccdos/mkswp.bat | 101 + dmake/msdos/bccdos/obj.rsp | 32 + dmake/msdos/bccdos/objswp.rsp | 34 + dmake/msdos/bccdos/public.h | 152 ++ dmake/msdos/bccdos/startup.mk | 154 ++ dmake/msdos/bccdos/tempnam.c | 82 + dmake/msdos/bccdos/utime.c | 42 + dmake/msdos/config.mk | 68 + dmake/msdos/dirbrk.c | 51 + dmake/msdos/dirlib.h | 42 + dmake/msdos/exec.asm | 1234 ++++++++++++ dmake/msdos/exec.h | 19 + dmake/msdos/exec.uue | 63 + dmake/msdos/find.c | 130 ++ dmake/msdos/mscdos/config.h | 83 + dmake/msdos/mscdos/config.mk | 93 + dmake/msdos/mscdos/lib.rsp | 1 + dmake/msdos/mscdos/libswp.rsp | 1 + dmake/msdos/mscdos/mk40.bat | 93 + dmake/msdos/mscdos/mk40swp.bat | 98 + dmake/msdos/mscdos/mk50.bat | 93 + dmake/msdos/mscdos/mk50swp.bat | 98 + dmake/msdos/mscdos/mk51.bat | 93 + dmake/msdos/mscdos/mk51swp.bat | 98 + dmake/msdos/mscdos/mk60.bat | 33 + dmake/msdos/mscdos/mk60swp.bat | 36 + dmake/msdos/mscdos/obj.rsp | 30 + dmake/msdos/mscdos/objswp.rsp | 32 + dmake/msdos/mscdos/optoff.h | 3 + dmake/msdos/mscdos/public.h | 152 ++ dmake/msdos/mscdos/startup.mk | 154 ++ dmake/msdos/mscdos/tempnam.c | 83 + dmake/msdos/rmprq.c | 47 + dmake/msdos/ruletab.c | 52 + dmake/msdos/runargv.c | 119 ++ dmake/msdos/spawn.c | 416 ++++ dmake/msdos/startup.h | 7 + dmake/msdos/stdarg.h | 22 + dmake/msdos/switchar.c | 39 + dmake/msdos/sysintf.h | 29 + dmake/msdos/tccdos/config.h | 54 + dmake/msdos/tccdos/config.mk | 50 + dmake/msdos/tccdos/lib.rsp | 1 + dmake/msdos/tccdos/libswp.rsp | 1 + dmake/msdos/tccdos/mk.bat | 96 + dmake/msdos/tccdos/mkswp.bat | 101 + dmake/msdos/tccdos/obj.rsp | 32 + dmake/msdos/tccdos/objswp.rsp | 34 + dmake/msdos/tccdos/public.h | 152 ++ dmake/msdos/tccdos/startup.mk | 154 ++ dmake/msdos/tccdos/tempnam.c | 80 + dmake/msdos/tccdos/utime.c | 42 + dmake/msdos/tee.c | 40 + dmake/msdos/ztcdos/config.h | 59 + dmake/msdos/ztcdos/config.mk | 73 + dmake/msdos/ztcdos/environ.c | 35 + dmake/msdos/ztcdos/lib.rsp | 1 + dmake/msdos/ztcdos/libswp.rsp | 1 + dmake/msdos/ztcdos/mk.bat | 34 + dmake/msdos/ztcdos/mkswp.bat | 34 + dmake/msdos/ztcdos/obj.rsp | 31 + dmake/msdos/ztcdos/objswp.rsp | 32 + dmake/msdos/ztcdos/public.h | 152 ++ dmake/msdos/ztcdos/startup.mk | 155 ++ dmake/msdos/ztcdos/tempnam.c | 80 + dmake/os2/_chdir.c | 59 + dmake/os2/config.mk | 54 + dmake/os2/dmake.bad | 2 + dmake/os2/dmake.cs | 13 + dmake/os2/dmake.def | 5 + dmake/os2/ibm/config.h | 78 + dmake/os2/ibm/config.mk | 83 + dmake/os2/ibm/dmake.ini | 154 ++ dmake/os2/ibm/lib.rsp | 2 + dmake/os2/ibm/mkc2.cmd | 90 + dmake/os2/ibm/obj.rsp | 29 + dmake/os2/ibm/optoff.h | 3 + dmake/os2/ibm/public.h | 152 ++ dmake/os2/ibm/startup.mk | 3 + dmake/os2/ibm/stdarg.h | 18 + dmake/os2/ibm/tempnam.c | 90 + dmake/os2/mscdos/config.h | 78 + dmake/os2/mscdos/config.mk | 83 + dmake/os2/mscdos/dmake.ini | 154 ++ dmake/os2/mscdos/lib.rsp | 2 + dmake/os2/mscdos/mk40.cmd | 90 + dmake/os2/mscdos/mk50.cmd | 90 + dmake/os2/mscdos/mk51.cmd | 90 + dmake/os2/mscdos/mk60.cmd | 32 + dmake/os2/mscdos/obj.rsp | 29 + dmake/os2/mscdos/optoff.h | 3 + dmake/os2/mscdos/public.h | 152 ++ dmake/os2/mscdos/startup.mk | 3 + dmake/os2/mscdos/tempnam.c | 90 + dmake/os2/optoff.h | 3 + dmake/os2/ruletab.c | 55 + dmake/os2/runargv.c | 327 +++ dmake/os2/startup.h | 7 + dmake/os2/switchar.c | 39 + dmake/os2/sysintf.h | 26 + dmake/parse.c | 158 ++ dmake/patchlvl.h | 3 + dmake/path.c | 116 ++ dmake/percent.c | 260 +++ dmake/posix.h | 66 + dmake/quit.c | 78 + dmake/readme/apple.IIgs | 448 +++++ dmake/readme/apple.mac | 42 + dmake/readme/atari.tos | 13 + dmake/readme/cover | 60 + dmake/readme/msdos | 135 ++ dmake/readme/os2 | 141 ++ dmake/readme/patch1 | 70 + dmake/readme/release | 109 + dmake/rulparse.c | 1325 +++++++++++++ dmake/stat.c | 248 +++ dmake/state.c | 230 +++ dmake/stdmacs.h | 65 + dmake/struct.h | 259 +++ dmake/sysintf.c | 690 +++++++ dmake/tos/arlib.c | 504 +++++ dmake/tos/config.h | 53 + dmake/tos/config.mk | 49 + dmake/tos/dirbrk.c | 53 + dmake/tos/make.sh | 59 + dmake/tos/public.h | 150 ++ dmake/tos/putenv.c | 87 + dmake/tos/rmprq.c | 49 + dmake/tos/ruletab.c | 51 + dmake/tos/runargv.c | 115 ++ dmake/tos/startup.h | 7 + dmake/tos/startup.mk | 136 ++ dmake/tos/sysintf.h | 23 + dmake/tos/tempnam.c | 78 + dmake/unix/86ix/ar.h | 2 + dmake/unix/86ix/config.h | 54 + dmake/unix/86ix/config.mk | 27 + dmake/unix/86ix/make.sh | 60 + dmake/unix/86ix/public.h | 149 ++ dmake/unix/86ix/startup.mk | 136 ++ dmake/unix/86ix/stdarg.h | 18 + dmake/unix/86ix/stdlib.h | 19 + dmake/unix/86ix/time.h | 10 + dmake/unix/arlib.c | 558 ++++++ dmake/unix/bsd43/config.h | 58 + dmake/unix/bsd43/config.mk | 27 + dmake/unix/bsd43/limits.h | 7 + dmake/unix/bsd43/make.sh | 69 + dmake/unix/bsd43/public.h | 149 ++ dmake/unix/bsd43/putenv.c | 87 + dmake/unix/bsd43/setvbuf.c | 49 + dmake/unix/bsd43/startup.mk | 136 ++ dmake/unix/bsd43/stdarg.h | 17 + dmake/unix/bsd43/stdlib.h | 19 + dmake/unix/bsd43/string.h | 16 + dmake/unix/bsd43/tempnam.c | 78 + dmake/unix/bsd43/utime.c | 48 + dmake/unix/bsd43/uw/config.mk | 17 + dmake/unix/bsd43/uw/make.sh | 69 + dmake/unix/bsd43/uw/public.h | 149 ++ dmake/unix/bsd43/uw/startup.mk | 136 ++ dmake/unix/bsd43/vf/config.mk | 11 + dmake/unix/bsd43/vf/ctype.h | 28 + dmake/unix/bsd43/vf/make.sh | 73 + dmake/unix/bsd43/vf/memcpy.c | 11 + dmake/unix/bsd43/vf/public.h | 149 ++ dmake/unix/bsd43/vf/startup.mk | 136 ++ dmake/unix/bsd43/vf/vfprintf.c | 48 + dmake/unix/coherent/config.h | 59 + dmake/unix/coherent/config.mk | 27 + dmake/unix/coherent/getcwd.c | 24 + dmake/unix/coherent/make.sh | 64 + dmake/unix/coherent/public.h | 149 ++ dmake/unix/coherent/startup.mk | 136 ++ dmake/unix/coherent/stdarg.h | 22 + dmake/unix/coherent/stdlib.h | 19 + dmake/unix/coherent/time.h | 10 + dmake/unix/coherent/vfprintf.c | 190 ++ dmake/unix/config.mk | 39 + dmake/unix/dirbrk.c | 51 + dmake/unix/gno/GS.startup.mk | 188 ++ dmake/unix/gno/alloc.h | 71 + dmake/unix/gno/arlib.c | 543 +++++ dmake/unix/gno/basename.c | 57 + dmake/unix/gno/config.h | 68 + dmake/unix/gno/dag.c | 490 +++++ dmake/unix/gno/db.h | 74 + dmake/unix/gno/dbug.h | 165 ++ dmake/unix/gno/dirbrk.c | 78 + dmake/unix/gno/dmake.c | 901 +++++++++ dmake/unix/gno/dmake.h | 183 ++ dmake/unix/gno/dmdump.c | 207 ++ dmake/unix/gno/dmstring.c | 298 +++ dmake/unix/gno/expand.c | 926 +++++++++ dmake/unix/gno/extern.h | 131 ++ dmake/unix/gno/function.c | 352 ++++ dmake/unix/gno/getinp.c | 521 +++++ dmake/unix/gno/hash.c | 61 + dmake/unix/gno/imacs.c | 172 ++ dmake/unix/gno/infer.c | 815 ++++++++ dmake/unix/gno/install | 8 + dmake/unix/gno/itypes.h | 55 + dmake/unix/gno/macparse.c | 166 ++ dmake/unix/gno/make.c | 1028 ++++++++++ dmake/unix/gno/make.sh | 34 + dmake/unix/gno/makefile.mk | 225 +++ dmake/unix/gno/parse.c | 157 ++ dmake/unix/gno/patchlvl.h | 3 + dmake/unix/gno/path.c | 116 ++ dmake/unix/gno/percent.c | 257 +++ dmake/unix/gno/posix.h | 66 + dmake/unix/gno/public.h | 153 ++ dmake/unix/gno/quit.c | 89 + dmake/unix/gno/rmprq.c | 109 + dmake/unix/gno/ruletab.c | 57 + dmake/unix/gno/rulparse.c | 1315 ++++++++++++ dmake/unix/gno/runargv.c | 193 ++ dmake/unix/gno/startup.h | 7 + dmake/unix/gno/stat.c | 243 +++ dmake/unix/gno/state.c | 233 +++ dmake/unix/gno/stdmacs.h | 68 + dmake/unix/gno/struct.h | 259 +++ dmake/unix/gno/sysintf.c | 694 +++++++ dmake/unix/gno/sysintf.h | 31 + dmake/unix/gno/tempnam.c | 95 + dmake/unix/gno/utime.c | 60 + dmake/unix/gno/va.c | 119 ++ dmake/unix/gno/version.h | 7 + dmake/unix/gno/vextern.h | 117 ++ dmake/unix/rmprq.c | 105 + dmake/unix/ruletab.c | 50 + dmake/unix/runargv.c | 299 +++ dmake/unix/startup.h | 7 + dmake/unix/sysintf.h | 23 + dmake/unix/sysvr1/config.h | 54 + dmake/unix/sysvr1/config.mk | 28 + dmake/unix/sysvr1/make.sh | 62 + dmake/unix/sysvr1/public.h | 149 ++ dmake/unix/sysvr1/putenv.c | 87 + dmake/unix/sysvr1/startup.mk | 137 ++ dmake/unix/sysvr1/stdarg.h | 21 + dmake/unix/sysvr1/stdlib.h | 19 + dmake/unix/sysvr1/time.h | 10 + dmake/unix/sysvr1/vfprintf.c | 58 + dmake/unix/sysvr3/config.h | 61 + dmake/unix/sysvr3/config.mk | 27 + dmake/unix/sysvr3/make.sh | 60 + dmake/unix/sysvr3/public.h | 149 ++ dmake/unix/sysvr3/pwd/config.mk | 20 + dmake/unix/sysvr3/pwd/getcwd.c | 231 +++ dmake/unix/sysvr3/pwd/make.sh | 62 + dmake/unix/sysvr3/pwd/public.h | 149 ++ dmake/unix/sysvr3/pwd/startup.mk | 136 ++ dmake/unix/sysvr3/startup.mk | 137 ++ dmake/unix/sysvr3/stdarg.h | 22 + dmake/unix/sysvr3/stdlib.h | 30 + dmake/unix/sysvr3/time.h | 10 + dmake/unix/sysvr4/config.h | 55 + dmake/unix/sysvr4/config.mk | 27 + dmake/unix/sysvr4/make.sh | 60 + dmake/unix/sysvr4/public.h | 149 ++ dmake/unix/sysvr4/startup.mk | 137 ++ dmake/unix/sysvr4/stdarg.h | 34 + dmake/unix/xenix/config.h | 60 + dmake/unix/xenix/config.mk | 27 + dmake/unix/xenix/make.sh | 60 + dmake/unix/xenix/public.h | 149 ++ dmake/unix/xenix/pwd/config.mk | 23 + dmake/unix/xenix/pwd/getcwd.c | 231 +++ dmake/unix/xenix/pwd/make.sh | 62 + dmake/unix/xenix/pwd/public.h | 149 ++ dmake/unix/xenix/pwd/startup.mk | 136 ++ dmake/unix/xenix/startup.mk | 137 ++ dmake/unix/xenix/stdarg.h | 22 + dmake/unix/xenix/stdlib.h | 24 + dmake/unix/xenix/time.h | 10 + dmake/version.h | 3 + dmake/vextern.h | 113 ++ rmroot/rmroot.1 | 48 + rmroot/rmroot.c | 40 + 364 files changed, 57159 insertions(+) create mode 100644 dmake/LICENSE create mode 100644 dmake/_install create mode 100644 dmake/alloc.h create mode 100644 dmake/basename.c create mode 100644 dmake/dag.c create mode 100644 dmake/db.h create mode 100644 dmake/dbug/README create mode 100644 dmake/dbug/dbug.mk create mode 100644 dmake/dbug/dbug/README create mode 100644 dmake/dbug/dbug/dbug.c create mode 100644 dmake/dbug/dbug/dbug.h create mode 100644 dmake/dbug/dbug/dbug.uue create mode 100644 dmake/dbug/getwd.c create mode 100644 dmake/dbug/malloc/Makefile create mode 100644 dmake/dbug/malloc/_changes create mode 100644 dmake/dbug/malloc/_readme create mode 100644 dmake/dbug/malloc/calloc.c create mode 100644 dmake/dbug/malloc/debug.h create mode 100644 dmake/dbug/malloc/dump.c create mode 100644 dmake/dbug/malloc/free.c create mode 100644 dmake/dbug/malloc/m_init.c create mode 100644 dmake/dbug/malloc/m_perror.c create mode 100644 dmake/dbug/malloc/malloc.3 create mode 100644 dmake/dbug/malloc/malloc.c create mode 100644 dmake/dbug/malloc/malloc.h create mode 100644 dmake/dbug/malloc/mallopt.c create mode 100644 dmake/dbug/malloc/memory.c create mode 100644 dmake/dbug/malloc/mlc_chk.c create mode 100644 dmake/dbug/malloc/mlc_chn.c create mode 100644 dmake/dbug/malloc/patchlevel create mode 100644 dmake/dbug/malloc/realloc.c create mode 100644 dmake/dbug/malloc/string.c create mode 100644 dmake/dbug/malloc/testmem.c create mode 100644 dmake/dbug/malloc/testmlc.c create mode 100644 dmake/dbug/malloc/tostring.c create mode 100644 dmake/dbug/malloc/tostring.h create mode 100644 dmake/dmake.c create mode 100644 dmake/dmake.h create mode 100644 dmake/dmdump.c create mode 100644 dmake/dmstring.c create mode 100644 dmake/expand.c create mode 100644 dmake/extern.h create mode 100644 dmake/function.c create mode 100644 dmake/getinp.c create mode 100644 dmake/hash.c create mode 100644 dmake/imacs.c create mode 100644 dmake/infer.c create mode 100644 dmake/itypes.h create mode 100644 dmake/mac/arlib.c create mode 100644 dmake/mac/bogus.c create mode 100644 dmake/mac/config.h create mode 100644 dmake/mac/config.mk create mode 100644 dmake/mac/dirbrk.c create mode 100644 dmake/mac/directry.c create mode 100644 dmake/mac/dompwmak create mode 100644 dmake/mac/environ.c create mode 100644 dmake/mac/eold.c create mode 100644 dmake/mac/main.c create mode 100644 dmake/mac/make.sh create mode 100644 dmake/mac/public.h create mode 100644 dmake/mac/rmprq.c create mode 100644 dmake/mac/ruletab.c create mode 100644 dmake/mac/startup.h create mode 100644 dmake/mac/startup.mk create mode 100644 dmake/mac/sysintf.h create mode 100644 dmake/mac/tempnam.c create mode 100644 dmake/mac/tomacfil.c create mode 100644 dmake/macparse.c create mode 100644 dmake/make.bat create mode 100644 dmake/make.c create mode 100644 dmake/make.cmd create mode 100644 dmake/makefile create mode 100644 dmake/makefile.mk create mode 100644 dmake/man/README create mode 100644 dmake/man/dmake.nc create mode 100644 dmake/man/dmake.tf create mode 100644 dmake/man/dmake.uue create mode 100644 dmake/msdos/_chdir.c create mode 100644 dmake/msdos/arlib.c create mode 100644 dmake/msdos/bccdos/config.h create mode 100644 dmake/msdos/bccdos/config.mk create mode 100644 dmake/msdos/bccdos/lib.rsp create mode 100644 dmake/msdos/bccdos/libswp.rsp create mode 100644 dmake/msdos/bccdos/mk.bat create mode 100644 dmake/msdos/bccdos/mkswp.bat create mode 100644 dmake/msdos/bccdos/obj.rsp create mode 100644 dmake/msdos/bccdos/objswp.rsp create mode 100644 dmake/msdos/bccdos/public.h create mode 100644 dmake/msdos/bccdos/startup.mk create mode 100644 dmake/msdos/bccdos/tempnam.c create mode 100644 dmake/msdos/bccdos/utime.c create mode 100644 dmake/msdos/config.mk create mode 100644 dmake/msdos/dirbrk.c create mode 100644 dmake/msdos/dirlib.h create mode 100644 dmake/msdos/exec.asm create mode 100644 dmake/msdos/exec.h create mode 100644 dmake/msdos/exec.uue create mode 100644 dmake/msdos/find.c create mode 100644 dmake/msdos/mscdos/config.h create mode 100644 dmake/msdos/mscdos/config.mk create mode 100644 dmake/msdos/mscdos/lib.rsp create mode 100644 dmake/msdos/mscdos/libswp.rsp create mode 100644 dmake/msdos/mscdos/mk40.bat create mode 100644 dmake/msdos/mscdos/mk40swp.bat create mode 100644 dmake/msdos/mscdos/mk50.bat create mode 100644 dmake/msdos/mscdos/mk50swp.bat create mode 100644 dmake/msdos/mscdos/mk51.bat create mode 100644 dmake/msdos/mscdos/mk51swp.bat create mode 100644 dmake/msdos/mscdos/mk60.bat create mode 100644 dmake/msdos/mscdos/mk60swp.bat create mode 100644 dmake/msdos/mscdos/obj.rsp create mode 100644 dmake/msdos/mscdos/objswp.rsp create mode 100644 dmake/msdos/mscdos/optoff.h create mode 100644 dmake/msdos/mscdos/public.h create mode 100644 dmake/msdos/mscdos/startup.mk create mode 100644 dmake/msdos/mscdos/tempnam.c create mode 100644 dmake/msdos/rmprq.c create mode 100644 dmake/msdos/ruletab.c create mode 100644 dmake/msdos/runargv.c create mode 100644 dmake/msdos/spawn.c create mode 100644 dmake/msdos/startup.h create mode 100644 dmake/msdos/stdarg.h create mode 100644 dmake/msdos/switchar.c create mode 100644 dmake/msdos/sysintf.h create mode 100644 dmake/msdos/tccdos/config.h create mode 100644 dmake/msdos/tccdos/config.mk create mode 100644 dmake/msdos/tccdos/lib.rsp create mode 100644 dmake/msdos/tccdos/libswp.rsp create mode 100644 dmake/msdos/tccdos/mk.bat create mode 100644 dmake/msdos/tccdos/mkswp.bat create mode 100644 dmake/msdos/tccdos/obj.rsp create mode 100644 dmake/msdos/tccdos/objswp.rsp create mode 100644 dmake/msdos/tccdos/public.h create mode 100644 dmake/msdos/tccdos/startup.mk create mode 100644 dmake/msdos/tccdos/tempnam.c create mode 100644 dmake/msdos/tccdos/utime.c create mode 100644 dmake/msdos/tee.c create mode 100644 dmake/msdos/ztcdos/config.h create mode 100644 dmake/msdos/ztcdos/config.mk create mode 100644 dmake/msdos/ztcdos/environ.c create mode 100644 dmake/msdos/ztcdos/lib.rsp create mode 100644 dmake/msdos/ztcdos/libswp.rsp create mode 100644 dmake/msdos/ztcdos/mk.bat create mode 100644 dmake/msdos/ztcdos/mkswp.bat create mode 100644 dmake/msdos/ztcdos/obj.rsp create mode 100644 dmake/msdos/ztcdos/objswp.rsp create mode 100644 dmake/msdos/ztcdos/public.h create mode 100644 dmake/msdos/ztcdos/startup.mk create mode 100644 dmake/msdos/ztcdos/tempnam.c create mode 100644 dmake/os2/_chdir.c create mode 100644 dmake/os2/config.mk create mode 100644 dmake/os2/dmake.bad create mode 100644 dmake/os2/dmake.cs create mode 100644 dmake/os2/dmake.def create mode 100644 dmake/os2/ibm/config.h create mode 100644 dmake/os2/ibm/config.mk create mode 100644 dmake/os2/ibm/dmake.ini create mode 100644 dmake/os2/ibm/lib.rsp create mode 100644 dmake/os2/ibm/mkc2.cmd create mode 100644 dmake/os2/ibm/obj.rsp create mode 100644 dmake/os2/ibm/optoff.h create mode 100644 dmake/os2/ibm/public.h create mode 100644 dmake/os2/ibm/startup.mk create mode 100644 dmake/os2/ibm/stdarg.h create mode 100644 dmake/os2/ibm/tempnam.c create mode 100644 dmake/os2/mscdos/config.h create mode 100644 dmake/os2/mscdos/config.mk create mode 100644 dmake/os2/mscdos/dmake.ini create mode 100644 dmake/os2/mscdos/lib.rsp create mode 100644 dmake/os2/mscdos/mk40.cmd create mode 100644 dmake/os2/mscdos/mk50.cmd create mode 100644 dmake/os2/mscdos/mk51.cmd create mode 100644 dmake/os2/mscdos/mk60.cmd create mode 100644 dmake/os2/mscdos/obj.rsp create mode 100644 dmake/os2/mscdos/optoff.h create mode 100644 dmake/os2/mscdos/public.h create mode 100644 dmake/os2/mscdos/startup.mk create mode 100644 dmake/os2/mscdos/tempnam.c create mode 100644 dmake/os2/optoff.h create mode 100644 dmake/os2/ruletab.c create mode 100644 dmake/os2/runargv.c create mode 100644 dmake/os2/startup.h create mode 100644 dmake/os2/switchar.c create mode 100644 dmake/os2/sysintf.h create mode 100644 dmake/parse.c create mode 100644 dmake/patchlvl.h create mode 100644 dmake/path.c create mode 100644 dmake/percent.c create mode 100644 dmake/posix.h create mode 100644 dmake/quit.c create mode 100644 dmake/readme/apple.IIgs create mode 100644 dmake/readme/apple.mac create mode 100644 dmake/readme/atari.tos create mode 100644 dmake/readme/cover create mode 100644 dmake/readme/msdos create mode 100644 dmake/readme/os2 create mode 100644 dmake/readme/patch1 create mode 100644 dmake/readme/release create mode 100644 dmake/rulparse.c create mode 100644 dmake/stat.c create mode 100644 dmake/state.c create mode 100644 dmake/stdmacs.h create mode 100644 dmake/struct.h create mode 100644 dmake/sysintf.c create mode 100644 dmake/tos/arlib.c create mode 100644 dmake/tos/config.h create mode 100644 dmake/tos/config.mk create mode 100644 dmake/tos/dirbrk.c create mode 100644 dmake/tos/make.sh create mode 100644 dmake/tos/public.h create mode 100644 dmake/tos/putenv.c create mode 100644 dmake/tos/rmprq.c create mode 100644 dmake/tos/ruletab.c create mode 100644 dmake/tos/runargv.c create mode 100644 dmake/tos/startup.h create mode 100644 dmake/tos/startup.mk create mode 100644 dmake/tos/sysintf.h create mode 100644 dmake/tos/tempnam.c create mode 100644 dmake/unix/86ix/ar.h create mode 100644 dmake/unix/86ix/config.h create mode 100644 dmake/unix/86ix/config.mk create mode 100644 dmake/unix/86ix/make.sh create mode 100644 dmake/unix/86ix/public.h create mode 100644 dmake/unix/86ix/startup.mk create mode 100644 dmake/unix/86ix/stdarg.h create mode 100644 dmake/unix/86ix/stdlib.h create mode 100644 dmake/unix/86ix/time.h create mode 100644 dmake/unix/arlib.c create mode 100644 dmake/unix/bsd43/config.h create mode 100644 dmake/unix/bsd43/config.mk create mode 100644 dmake/unix/bsd43/limits.h create mode 100644 dmake/unix/bsd43/make.sh create mode 100644 dmake/unix/bsd43/public.h create mode 100644 dmake/unix/bsd43/putenv.c create mode 100644 dmake/unix/bsd43/setvbuf.c create mode 100644 dmake/unix/bsd43/startup.mk create mode 100644 dmake/unix/bsd43/stdarg.h create mode 100644 dmake/unix/bsd43/stdlib.h create mode 100644 dmake/unix/bsd43/string.h create mode 100644 dmake/unix/bsd43/tempnam.c create mode 100644 dmake/unix/bsd43/utime.c create mode 100644 dmake/unix/bsd43/uw/config.mk create mode 100644 dmake/unix/bsd43/uw/make.sh create mode 100644 dmake/unix/bsd43/uw/public.h create mode 100644 dmake/unix/bsd43/uw/startup.mk create mode 100644 dmake/unix/bsd43/vf/config.mk create mode 100644 dmake/unix/bsd43/vf/ctype.h create mode 100644 dmake/unix/bsd43/vf/make.sh create mode 100644 dmake/unix/bsd43/vf/memcpy.c create mode 100644 dmake/unix/bsd43/vf/public.h create mode 100644 dmake/unix/bsd43/vf/startup.mk create mode 100644 dmake/unix/bsd43/vf/vfprintf.c create mode 100644 dmake/unix/coherent/config.h create mode 100644 dmake/unix/coherent/config.mk create mode 100644 dmake/unix/coherent/getcwd.c create mode 100644 dmake/unix/coherent/make.sh create mode 100644 dmake/unix/coherent/public.h create mode 100644 dmake/unix/coherent/startup.mk create mode 100644 dmake/unix/coherent/stdarg.h create mode 100644 dmake/unix/coherent/stdlib.h create mode 100644 dmake/unix/coherent/time.h create mode 100644 dmake/unix/coherent/vfprintf.c create mode 100644 dmake/unix/config.mk create mode 100644 dmake/unix/dirbrk.c create mode 100644 dmake/unix/gno/GS.startup.mk create mode 100644 dmake/unix/gno/alloc.h create mode 100644 dmake/unix/gno/arlib.c create mode 100644 dmake/unix/gno/basename.c create mode 100644 dmake/unix/gno/config.h create mode 100644 dmake/unix/gno/dag.c create mode 100644 dmake/unix/gno/db.h create mode 100644 dmake/unix/gno/dbug.h create mode 100644 dmake/unix/gno/dirbrk.c create mode 100644 dmake/unix/gno/dmake.c create mode 100644 dmake/unix/gno/dmake.h create mode 100644 dmake/unix/gno/dmdump.c create mode 100644 dmake/unix/gno/dmstring.c create mode 100644 dmake/unix/gno/expand.c create mode 100644 dmake/unix/gno/extern.h create mode 100644 dmake/unix/gno/function.c create mode 100644 dmake/unix/gno/getinp.c create mode 100644 dmake/unix/gno/hash.c create mode 100644 dmake/unix/gno/imacs.c create mode 100644 dmake/unix/gno/infer.c create mode 100644 dmake/unix/gno/install create mode 100644 dmake/unix/gno/itypes.h create mode 100644 dmake/unix/gno/macparse.c create mode 100644 dmake/unix/gno/make.c create mode 100644 dmake/unix/gno/make.sh create mode 100644 dmake/unix/gno/makefile.mk create mode 100644 dmake/unix/gno/parse.c create mode 100644 dmake/unix/gno/patchlvl.h create mode 100644 dmake/unix/gno/path.c create mode 100644 dmake/unix/gno/percent.c create mode 100644 dmake/unix/gno/posix.h create mode 100644 dmake/unix/gno/public.h create mode 100644 dmake/unix/gno/quit.c create mode 100644 dmake/unix/gno/rmprq.c create mode 100644 dmake/unix/gno/ruletab.c create mode 100644 dmake/unix/gno/rulparse.c create mode 100644 dmake/unix/gno/runargv.c create mode 100644 dmake/unix/gno/startup.h create mode 100644 dmake/unix/gno/stat.c create mode 100644 dmake/unix/gno/state.c create mode 100644 dmake/unix/gno/stdmacs.h create mode 100644 dmake/unix/gno/struct.h create mode 100644 dmake/unix/gno/sysintf.c create mode 100644 dmake/unix/gno/sysintf.h create mode 100644 dmake/unix/gno/tempnam.c create mode 100644 dmake/unix/gno/utime.c create mode 100644 dmake/unix/gno/va.c create mode 100644 dmake/unix/gno/version.h create mode 100644 dmake/unix/gno/vextern.h create mode 100644 dmake/unix/rmprq.c create mode 100644 dmake/unix/ruletab.c create mode 100644 dmake/unix/runargv.c create mode 100644 dmake/unix/startup.h create mode 100644 dmake/unix/sysintf.h create mode 100644 dmake/unix/sysvr1/config.h create mode 100644 dmake/unix/sysvr1/config.mk create mode 100644 dmake/unix/sysvr1/make.sh create mode 100644 dmake/unix/sysvr1/public.h create mode 100644 dmake/unix/sysvr1/putenv.c create mode 100644 dmake/unix/sysvr1/startup.mk create mode 100644 dmake/unix/sysvr1/stdarg.h create mode 100644 dmake/unix/sysvr1/stdlib.h create mode 100644 dmake/unix/sysvr1/time.h create mode 100644 dmake/unix/sysvr1/vfprintf.c create mode 100644 dmake/unix/sysvr3/config.h create mode 100644 dmake/unix/sysvr3/config.mk create mode 100644 dmake/unix/sysvr3/make.sh create mode 100644 dmake/unix/sysvr3/public.h create mode 100644 dmake/unix/sysvr3/pwd/config.mk create mode 100644 dmake/unix/sysvr3/pwd/getcwd.c create mode 100644 dmake/unix/sysvr3/pwd/make.sh create mode 100644 dmake/unix/sysvr3/pwd/public.h create mode 100644 dmake/unix/sysvr3/pwd/startup.mk create mode 100644 dmake/unix/sysvr3/startup.mk create mode 100644 dmake/unix/sysvr3/stdarg.h create mode 100644 dmake/unix/sysvr3/stdlib.h create mode 100644 dmake/unix/sysvr3/time.h create mode 100644 dmake/unix/sysvr4/config.h create mode 100644 dmake/unix/sysvr4/config.mk create mode 100644 dmake/unix/sysvr4/make.sh create mode 100644 dmake/unix/sysvr4/public.h create mode 100644 dmake/unix/sysvr4/startup.mk create mode 100644 dmake/unix/sysvr4/stdarg.h create mode 100644 dmake/unix/xenix/config.h create mode 100644 dmake/unix/xenix/config.mk create mode 100644 dmake/unix/xenix/make.sh create mode 100644 dmake/unix/xenix/public.h create mode 100644 dmake/unix/xenix/pwd/config.mk create mode 100644 dmake/unix/xenix/pwd/getcwd.c create mode 100644 dmake/unix/xenix/pwd/make.sh create mode 100644 dmake/unix/xenix/pwd/public.h create mode 100644 dmake/unix/xenix/pwd/startup.mk create mode 100644 dmake/unix/xenix/startup.mk create mode 100644 dmake/unix/xenix/stdarg.h create mode 100644 dmake/unix/xenix/stdlib.h create mode 100644 dmake/unix/xenix/time.h create mode 100644 dmake/version.h create mode 100644 dmake/vextern.h create mode 100644 rmroot/rmroot.1 create mode 100644 rmroot/rmroot.c diff --git a/dmake/LICENSE b/dmake/LICENSE new file mode 100644 index 0000000..3c68f02 --- /dev/null +++ b/dmake/LICENSE @@ -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. + + + Copyright (C) 19yy + + 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. + + , 1 April 1989 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/dmake/_install b/dmake/_install new file mode 100644 index 0000000..f6e7487 --- /dev/null +++ b/dmake/_install @@ -0,0 +1,219 @@ +INSTALLATION INSTRUCTIONS + +This file contains the instructions required to install and create the +appropriate version of dmake. + +NOTE: If you use dmake to bootstrap a NEW DISTRIBUTED version or to remake + it after applying a PATCH, it may be NECESSARY to use the batch + script instead of dmake as a patch may incorporate changes to the + makefile.mk file and associated config.mk files that cannot be + handled by earlier versions of dmake. The use of the batch files + is the ONLY supported method of making a new release or update + version. + +NOTE: If you do not plan to use the MAKESTARTUP variable in your + environment, change the value of the variable in the file + "./unix/startup.h" BEFORE you bootstrap this package. + +NOTE: NAME_MAX is used in sysintf.c to limit the name of a file name + component before performing a stat operation. If you have problems + with file name lengths make certain that NAME_MAX is correctly set. + + NAME_MAX is set either in limits.h or in unistd.h (for POSIX systems) + or in stdio.h. If it is not set anywhere then dmake's own "posix.h" + file will define a reasonable default value, this may or may not be + reasonable for your system. If you have trouble with long file names + then hunt down the NAME_MAX definition. + +NOTE: This file should really be rewritten :-) + + + +MAKING THE PROPER VERSION + +The list of available versions of dmake has grown quite large. The best +method to determine what versions are available for your configuration is to +simply issue the command 'make' in the source root directory. Below is a +partial list of the available versions to give an idea of what is supported. +Note that this copy of the list is not maintained up to date. + + bsd43 - Generic BSD 4.3 (eg, true BSD, apollo, Sun OS4, SGI etc) + bsd43uw - Generic BSD 4.3 at U of Waterloo + bsd43vf - Generic BSD with no vfprintf in its library (use this + target if you are missing the vfprintf function in your + C library) + sysvr3 - Generic SysV R3 UNIX + sysvr1 - Generic SysV R1 UNIX + 386ix - 386/ix (SysV R3), not tested + dynix - Sequent Symmetry dynix + ultrix - Ultrix 3.0 system + mips - Any MIPS box + os2msc60 - OS/2 with MSC 6.0 + tos - Atari-ST using GCC as compiler + tcc - DOS with tcc 2.0 + tccswp - swapping DOS version with tcc 2.0 + msc60 - DOS with MSC 6.0 + msc60swp - swapping DOS version with MSC 6.0 + +The file 'makefile' understands these targets and runs the appropriate script +to create the correct version. + +The source code is organized as follows: + + dmake [source for all common functions] + | + | + ---------------------------- + | | | | + unix tos os2 msdos [source for OS specific functions] + | | | + -------------------- mscdos ------------------- + | | | | | | +386ix bsd43 sysvr[134] tccdos bccdos mscdos [source for OSRELEASE + | specific functions] + -------- + | | + 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) +To make the appropriate versions of dmake, simply type the command + + 'make system' + +where system is one of the supplied possibilities. Note that if you are using +an earlier version of dmake to make a new version from scratch then you must +use the command: + + 'dmake -f makefile system' + +as dmake by default first reads makefile.mk and would thus use the wrong +makefile for bootstrapping purposes. + +The bootstrapping of dmake is accomplished by running a shell script with the +appropriate compile commands hard coded. + +(NOTE: If you are using MSDOS then, you will actually be using the make.bat + scriptfile to make the correct version of dmake for MSDOS. If you + are running a SHELL other than command.com, you may have to perform + some extra work to invoke the batch file. + + Make sure you read the readme/msdos file before attempting to make the + MSDOS version, as it contains important configuration and limitation + information.) + +The making of dmake, echoes the commands being executed, and should proceed +relatively error free. Ignore ANY warnings produced by the compile +They have all be verified and are spurious noise. + +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". + + +STARTUP FILE + +dmake requires the loading of a startup file when it is invoked. The +path for the startup file is set in the file 'startup.h' found in the +appropriate system sub-directories. You may override the value of the +path variable compiled-in by creating a file at the root source directory +called startup.h and inserting into that file a definition that is like +the definition found in the supplied startup.h files. Alternatively you +can modify the MAKESTARTUP environment variable to point at the location +of your startup.mk file. + + +INSTALLATION + +To install dmake you must copy the executable to where your system +locates executables, and you must place a copy of startup.mk (found in the +root source directory after the build is successfuly completed) into a location +corresponding to the value of the MAKESTARTUP macro or environment variable. +You are free to customize the contents of startup.mk. + +To make dmake again, (using itself), you will have to set three environment +variables. See the files in readme/options for their names and their legal +values. Once set you can invoke dmake to make itself. + + +DOCUMENTATION + +All documentation for dmake appears under the man directory. +The file dmake.tf included in this distribution contains the troff +source for the man page. You must typeset it using the -man macros. +If you cannot typeset it, the file dmake.p is a version that has been +typeset for a normal dumb terminal. The file dmake.p contains control +characters. The file dmake.nc is a version of the man page that has +all of the control characters stripped. + + +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/alloc.h b/dmake/alloc.h new file mode 100644 index 0000000..38266a9 --- /dev/null +++ b/dmake/alloc.h @@ -0,0 +1,71 @@ +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/alloc.h,v 1.2 1992/04/07 04:42:46 dvadura 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@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. +-- +-- LOG +-- $Log: alloc.h,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Added a !defined(_SIZE_T_) to satisfy Silicon Graphics IRIX. + * + * Revision 1.1 1992/01/24 03:26:54 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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_) +# 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/basename.c b/dmake/basename.c new file mode 100644 index 0000000..c5c1738 --- /dev/null +++ b/dmake/basename.c @@ -0,0 +1,55 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/basename.c,v 1.1 1992/01/24 03:26:56 dvadura Exp $ +-- SYNOPSIS -- return pointer to last pathname component +-- +-- DESCRIPTION +-- take a file name like /fred/foo/hoe/mary.k, and return the 'mary.k' +-- portion +-- +-- 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. +-- +-- LOG +-- $Log: basename.c,v $ + * Revision 1.1 1992/01/24 03:26:56 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +PUBLIC char* +basename( path ) +char *path; +{ + char *p; + char *q; + + if( *(q = path) ) { + for(; *(p=_strpbrk(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 ); +} diff --git a/dmake/dag.c b/dmake/dag.c new file mode 100644 index 0000000..f2d7186 --- /dev/null +++ b/dmake/dag.c @@ -0,0 +1,497 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/dag.c,v 1.1 1992/01/24 03:26:55 dvadura 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@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. +-- +-- LOG +-- $Log: dag.c,v $ + * Revision 1.1 1992/01/24 03:26:55 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + + +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 = _strdup( 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 +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( (hp->ht_flag & M_PRECIOUS) && !(flags & M_FORCE) ) { + 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( *_strpbrk(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 \ 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 = _strdup( _strspn( 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 = _strdup( value ); /* take string literally */ + + if( !*p ) { /* check if result is "" */ + FREE( p ); + p = NIL(char); + flags |= M_EXPANDED; + } + else if( *_strpbrk( 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)); + + /* 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 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; + } + + 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; + } + 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 = _strspn( 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 : _strspn( rcp, " \t@-+%" ); + + TALLOC( nsp, 1, STRING ); + nsp->st_string = _strdup( 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 0000000..8f1f2bb --- /dev/null +++ b/dmake/db.h @@ -0,0 +1,75 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/db.h,v 1.1 1992/01/24 03:29:35 dvadura 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@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. +-- +-- LOG +-- $Log: db.h,v $ + * Revision 1.1 1992/01/24 03:29:35 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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/README b/dmake/dbug/README new file mode 100644 index 0000000..15efc00 --- /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/dbug/dbug.mk b/dmake/dbug/dbug.mk new file mode 100644 index 0000000..b61ebe1 --- /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/README b/dmake/dbug/dbug/README new file mode 100644 index 0000000..a69f346 --- /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/dbug/dbug.c b/dmake/dbug/dbug/dbug.c new file mode 100644 index 0000000..b9ec13c --- /dev/null +++ b/dmake/dbug/dbug/dbug.c @@ -0,0 +1,1832 @@ +/****************************************************************************** + * * + * 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 +#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: + * + * ::...: + * + * 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_ 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 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, "\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 +# if BSD4_3 || sun + +/* + * Definition of the Clock() routine for 4.3 BSD. + */ + +#include +#include + +/* + * 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 0000000..f69ab2b --- /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 + * + * 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_ 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 0000000..da8743b --- /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:@"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>$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.BG42IC' B0E\X)1]EF:AOG.P\-F!UCI(=M=Q'6/040=/06O9/ZM)4QD4WNL2&20GP2YZ86@,HQP!IDR0L^]IQYMF TT=]FD]?P=N +M&XU]"O5X"8?!D\9UN '<="P7J3##I1U7'F\2 F=Z<)YU+>C/,(\.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!29) #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-,>()#!?WVU7CJ03 A6RU(9F.>&PKDME\SCI44$4P;5 +M5$E:F!-6&\2P-YI4#W#4*8UZK(L0'_&P)W"3GI'TX!>=JKRE#W=YT($A^:SG +MFP\+9XVH/)#=-JJNOXVE<%W"IJ6FY\IH?!A@1CPX[SDH#:S1*F"D^RR?8$YY +ML:WSD?1B':G!QSO:U! GN\2!-/*HA@(4A8\EYKD,,2#(SR?[5T0*2LO%-HB +M9T*-$R,]X3]P^$_Z_/BGXW)G90XDFAO 6 QJ&PWQ!HN +MF\A:W" TK]C'?"2'E,MDY3YJZ=%F]QEPBUO6QJOEJ4PCVRG[1PX\>L$P:ZI=2>2W^B%7'O-]H)Q>-^O +M=QL$4N@)$./&Y7L-R.E):^?1M(._M3O(= ]W*/N;@[MO@D.YYM5*]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(@($:^!%(0G"!8XF(%3@ !-^(3O9Q"@A#$=(E0>ND57&9AW,\REZD7F5SB3 +M]W2#=A IE#6 ^%KF92V,.(;P=!A+HHLU-R)6DAH9(3- 8W0$(606AF))54Y+ +M$C)],3I3YW)>$QR*Q7V.EAC*0WL4 +M)AE+,P0C6-:!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'ME$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# <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[&$12:164:4XMT #6$8R"[DQ$CX34ZEHFH9(J;"#J/ +M%$QIE 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+JI.@\IHQ401F=I.M"57-)">BY$?$,V/E,B]X-K(- +M$ATSIC&V1#=BQ"[X0P9YT'F[! )V("4?RF*4@8(H+F<:[F56[E.E@<; +MMC:I3$UH5;!<:3,%VVF)H^EX;B-V[B2&[F1 +MZ[F7BRF9N[GDNV"?:[F[^FE1!$]3\[6H,H\'4;T[ZT5L5(J\;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

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$6C);\.IG_:IET*; ]* +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,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,@Y8R>%]" +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\B7053@ 2U9P(+[I4-+@/GFM[8_#M;N ;<[5*;V9DMSI?K'>#RS0/T+>,# +M7N 9#G\E]07?G035?]K1=O&4Q% +MDMRXVMSF+>)X4.(KGE&U+ )QN+X)]U24 144 52X 2U!P-D3A'" +MG.,44YV#K!EA0=C!01YF]PGU,J;XB>S"D$4?(=R*[ +MX7-,E"$4(H=ZGM3>($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 4ZUXSRSO9Y$QU%1$P=8AVJVV 4U\"2])X,Q%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==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;6+MR#(0 B>!6RKD40 +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#EL.QJH5CBV1,)T<,)]TQ*_ +M6QI4CM1\0^E96-2.P4HK(SUH@*C0(4#4T3Y3-RB=ANH@( (Q4)<#(0(R4)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=?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&'=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$<%>;JY]U2X.,,A9917I>/&>6J%)=UB;/)H9-.WN4Q@>9JSN9NC@+DII-Q/A%S +M+NP'4?(#?%&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 +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 >5('=AG_3_K +M%.IVQAVF3WT83N?'7>40WU& *JEE7 -(Z1+)1C5%O2R(IVI55?=.S[ @8 .# +MG5&BZ5(.ZU(ZY5(R<.S'7>40WU& *JEE7 .#[IF4'FNS +MUG*GYANOCAYT]AY.XQGL(2V%8S. CDG +M,9)SG50W@(KPHZ0#$>6M9O;P5(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(\D_^6UED -ORJ7_PB +M[X(KF/P\/M$$^,Y/Z(1.^(,^Z(/G@4QZVC][OAQN)AE3\L2N@[E2KRDBB0!;@ !;@ .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=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/@9 +MX3B*ER-5^9TN(RQ]@@:405^!6#*28_F=OR?]V30XYK*0 R+!X5.(5UVP!<&P +M9V>(1Y$:@K0X6RWIS>0EZ3H"(O> +M<0)O<,+_HTB=IKZ9]_!%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�(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;W[.?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[!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.[/=P<0$ 1INMB3R!?P40:/]41_0V6GJ"T_>,?RJ +M7_PB[X(KF/P\/M$%>(!5 8/QS!3-SU"?3_T,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:;GL0*IMG63,W"GLT5(/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 -&(!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<.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._[/:&O7K\S21"#S_9!9W],773'GA-4 +MCM1LX )CH ,&D0,Z<-Q5ON5[K@-.[R ZX/21 JA4CM3#B7]4CM1LX )CH ,&D0,Z<-Q5ON5(/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.<34UZJ5E77SV<_(P(,1@:/^/D)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+ 2[@_XKJ +M./]ZT4HSR:EAH)M/U5FR]L$+>1A^8CI&!>\#P;'E0>_!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^=V&GJ +MJ_>\0VXZ2>< QA-RPR143.DZ7TNBSQ-RPR011.$OC3^<_/3L+XQH6T[[E02'2 +M3=W6C=W2GQ%=BLWJB-)+NXI?X5P18H ,Z#OM6\ 1)0 1?D.9KWN;0 +M+1/>#=[B3=[% 2,'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?/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# 9T +M#@(BT (C\(CDXAT*;VL=%L6[4;O-D\1BC"2^=GV1$G2__DCSKQ?N'^EO@ !O +M@ !O@ !@@@!T@ !T@ !.9.<(C04ZH..P#P4<[N%HN=U KQ#QQ^-/ +M 6#*5_F6-3(R!<["N[H6=/TQJEE)VF%8QV+&#O1L1+62=5ODET)B'']?8 1)P 0'73+P(=U& +MD 1,<-#2;_-)ED/WDS#]2NGMK!\Y49G?->=/E"5=(E#(3.5DY!#6K+([+_$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[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/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=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^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_W,^*A%@ 4ZH..PSP1/X 1'H 1- +M 6U%QDL0&Z96 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:Z^52X3N<$ +MH:0_K"SYE3"O%'Y/1P8<81(R>N)4($ ZY!HE(9NO93"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.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#(!6 +MD<]80=#B'8(:^(1.Z(1/Z(1.*/T9P8R/"@6 +@<'A>O@'GY/%W0,2>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/<PXA/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-$6 +M;=$7;=$6S= "'80&G?)8\41*RZ=/D0@>9D?AF$"19!QG8,T>-^+OE5!V# +MZ%T.ZJ^)YD9G7 +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]EAFA![(%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!" 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/CSYEEQ7)B!U +6JTKA=5]I *"4_\%4D\0&T1CB.!Q$ 1VO + +end diff --git a/dmake/dbug/getwd.c b/dmake/dbug/getwd.c new file mode 100644 index 0000000..56e1a03 --- /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/Makefile b/dmake/dbug/malloc/Makefile new file mode 100644 index 0000000..64647de --- /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.5 90/08/29 22:34:27 cpcahil 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/_changes b/dmake/dbug/malloc/_changes new file mode 100644 index 0000000..888a47a --- /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 0000000..b78b1fd --- /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 0000000..7c4b513 --- /dev/null +++ b/dmake/dbug/malloc/calloc.c @@ -0,0 +1,73 @@ +/* + * (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 + +/* + * 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 1992/01/24 03:28:58 dvadura 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: calloc.c,v $ + * 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 0000000..2892702 --- /dev/null +++ b/dmake/dbug/malloc/debug.h @@ -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. + */ +/************************************************************************/ +/* */ +/* 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 1992/01/24 03:28:59 dvadura Exp $ + */ + +#ifdef DEBUG + +#if DEBUG == 1 /* if default level */ +#undef DEBUG +#define DEBUG 100 /* use level 100 */ +#endif + +#include + +#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: debug.h,v $ + * 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 0000000..8f83c34 --- /dev/null +++ b/dmake/dbug/malloc/dump.c @@ -0,0 +1,124 @@ +/* + * (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 +#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 1992/01/24 03:29:01 dvadura 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: dump.c,v $ + * 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 0000000..597f5f5 --- /dev/null +++ b/dmake/dbug/malloc/free.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 +#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 1992/01/24 03:29:02 dvadura 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: free.c,v $ + * 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 0000000..3c6eb8c --- /dev/null +++ b/dmake/dbug/malloc/m_init.c @@ -0,0 +1,103 @@ +/* + * (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 +#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 1992/01/24 03:29:03 dvadura 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: m_init.c,v $ + * 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 0000000..b90184b --- /dev/null +++ b/dmake/dbug/malloc/m_perror.c @@ -0,0 +1,93 @@ +/* + * (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 1992/01/24 03:29:04 dvadura 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: m_perror.c,v $ + * 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/malloc.3 b/dmake/dbug/malloc/malloc.3 new file mode 100644 index 0000000..82ef1bf --- /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.3 90/08/29 22:24:44 cpcahil Exp $ +.SH NAME +malloc \t- debugging malloc library +.SH SYNOPSIS +.ft B +.nf +#include + +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_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 0000000..8ba9d0f --- /dev/null +++ b/dmake/dbug/malloc/malloc.c @@ -0,0 +1,654 @@ +/* + * (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 +#include +#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 1992/01/24 03:29:05 dvadura 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( IsLess(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: malloc.c,v $ + * 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 0000000..2f3b606 --- /dev/null +++ b/dmake/dbug/malloc/malloc.h @@ -0,0 +1,103 @@ +/* + * (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 1992/01/24 03:29:06 dvadura 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: malloc.h,v $ + * 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 0000000..85e1ce1 --- /dev/null +++ b/dmake/dbug/malloc/mallopt.c @@ -0,0 +1,125 @@ +/* + * (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 +#include +#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 1992/01/24 03:29:07 dvadura 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: mallopt.c,v $ + * 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 0000000..07dace2 --- /dev/null +++ b/dmake/dbug/malloc/memory.c @@ -0,0 +1,225 @@ +/* + * (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 1992/01/24 03:29:08 dvadura 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: memory.c,v $ + * 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 0000000..8193daa --- /dev/null +++ b/dmake/dbug/malloc/mlc_chk.c @@ -0,0 +1,279 @@ +/* + * (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 +#include "malloc.h" +#include "debug.h" + +#ifndef lint +static +char rcs_hdr[] = "$Id: mlc_chk.c,v 1.1 1992/01/24 03:29:09 dvadura 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: mlc_chk.c,v $ + * 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 0000000..864b539 --- /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 +#include +#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 1992/01/24 03:29:10 dvadura 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/patchlevel b/dmake/dbug/malloc/patchlevel new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/dmake/dbug/malloc/patchlevel @@ -0,0 +1 @@ +3 diff --git a/dmake/dbug/malloc/realloc.c b/dmake/dbug/malloc/realloc.c new file mode 100644 index 0000000..cd46e24 --- /dev/null +++ b/dmake/dbug/malloc/realloc.c @@ -0,0 +1,215 @@ +/* + * (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 +#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 1992/01/24 03:29:11 dvadura 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: realloc.c,v $ + * 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 0000000..e79cf1e --- /dev/null +++ b/dmake/dbug/malloc/string.c @@ -0,0 +1,563 @@ +/* + * (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 +#include +#include +#include "malloc.h" + +#ifndef lint +static +char rcs_hdr[] = "$Id: string.c,v 1.1 1992/01/24 03:29:13 dvadura 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: string.c,v $ + * 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 0000000..1d666f8 --- /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 +#include + +char * index(); +char * rindex(); + +#define STREQ(a, b) (strcmp((a), (b)) == 0) + +char *it = ""; /* 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 0000000..5455003 --- /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 +/* +** looptest.c -- intensive allocator tester +** +** Usage: looptest +** +** History: +** 4-Feb-1987 rtech!daveb +*/ + +# ifdef SYS5 +# define random rand +# else +# include +# endif + +# include +# include +# include + +# 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 0000000..2118bf5 --- /dev/null +++ b/dmake/dbug/malloc/tostring.c @@ -0,0 +1,151 @@ +/* + * (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 1992/01/24 03:29:16 dvadura 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: tostring.c,v $ + * 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 0000000..aff9165 --- /dev/null +++ b/dmake/dbug/malloc/tostring.h @@ -0,0 +1,25 @@ +/* + * (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 1992/01/24 03:29:17 dvadura Exp $ + */ +#define B_BIN 2 +#define B_DEC 10 +#define B_HEX 16 +#define B_OCTAL 8 + +/* + * $Log: tostring.h,v $ + * 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/dmake.c b/dmake/dmake.c new file mode 100644 index 0000000..82285e3 --- /dev/null +++ b/dmake/dmake.c @@ -0,0 +1,818 @@ +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/dmake.c,v 1.3 1992/04/07 04:42:46 dvadura 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 +-- -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@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. +-- +-- LOG +-- $Log: dmake.c,v $ + * Revision 1.3 1992/04/07 04:42:46 dvadura + * Gnuiffied the source, and prettied up some of the output for -h. + * + * Revision 1.2 1992/04/01 03:31:03 dvadura + * changed use of #elif to satisfy broken compilers. + * + * Revision 1.1 1992/01/24 03:26:58 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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 "patchlvl.h" +#include "version.h" + +#ifndef MSDOS +#define USAGE \ +"Usage:\n%s [-P#] [-{f|K} file] [-v{dfimt}] [-ABceEhiknpqrsStTuVxX]\n" +#define USAGE2 \ +"%s [macro[*][+][:]=value ...] [target ...]\n" +#else +#define USAGE \ +"Usage:\n%s [-P#] [-{f|C|K} file] [-v{dfimt}] [-ABceEhiknpqrsStTuVxX]\n" +#define USAGE2 \ +"%s [macro[*][+][:]=value ...] [target ...]\n" +#endif + +#if __STDC__ == 1 && !defined(__GNUC__) +void Fatal(char *fmt, ...); +void Warning(char *fmt, ...); +#endif + +static char *sccid = "Copyright (c) 1990,1991 by Dennis Vadura"; +static char _warn = TRUE; /* warnings on by default */ + +static void _do_VPATH(); +static void _do_ReadEnvironment(); +#if !defined(__GNUC__) +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* 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; + + 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 'k': Continue = TRUE; break; + case 'c': Comment = TRUE; break; + case 'p': Listing = TRUE; break; + case 'r': Rules = FALSE; break; + case 'n': Trace = TRUE; 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 'v': + if( p[-1] != '-' ) Usage(TRUE); + while( p[1] ) switch( *++p ) { + case 'd': Verbose |= V_PRINT_DIR; 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; + + 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 = _stradd( cmdmacs, _strdup2(p), TRUE ); + Parse_macro( p, (q[-1]!='+')?M_PRECIOUS:M_DEFAULT ); + } + else { + register CELLPTR cp; + targets = _stradd( targets, _strdup(p), TRUE ); + Add_prerequisite(Root, 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 ); + mkfil = NIL(FILE); + } + 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; + register LINKPTR lp; + + cp = Def_cell( ".MAKEFILES" ); + + if( (lp = cp->CE_PRQ) != 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; + } + } + + if( mkfil != NIL(FILE) ) { + char *f = Filename(); + char *p; + + if( strcmp(f, "stdin") == 0 ) f = "-"; + p = _stradd( "-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(); + } + + Push_dir( Start_dir, ".SETDIR", (int)(Glob_attr & A_IGNORE )); + + if( m_export ) { + int i; + + for( i=0; iht_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(); + + Pop_dir( (Glob_attr & A_IGNORE) != 0 ); + 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. + */ +static void +_set_inc_depth() +{ + char buf[10]; + sprintf( buf, "%d", next_file_slot ); + Def_macro( "INCDEPTH", buf, 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 = _strdup(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) ) 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 ); +} + + +/* +** 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 +*/ +#if __STDC__ == 1 && !defined(__GNUC__) +void +Fatal(char *fmt, ...) +#else +#if defined(_MPW) +Fatal(char *fmt, va_alist) +va_dcl +#else +int +Fatal(fmt, va_alist) +char *fmt; +va_dcl; +#endif +#endif +{ + va_list args; + + va_start(args, fmt); + Continue = FALSE; + errargs(fmt, args); + va_end(args); +} + +/* +** error message and exit (unless -k) +*/ +#if __STDC__ == 1 && !defined(__GNUC__) +void +Error (char *fmt, ...) +#else +#if defined(_MPW) +Error(char *fmt, va_alist) +va_dcl +#else +int +Error(fmt, va_alist) +char* fmt; +va_dcl; +#endif +#endif +{ + va_list args; + + va_start(args, fmt); + errargs(fmt, args); + va_end(args); +} + + +/* +** non-fatal message +*/ +#if __STDC__ == 1 && !defined(__GNUC__) +void +Error(char *fmt, ...) +#else +#if defined(_MPW) +Error(char *fmt, va_alist) +va_dcl +#else +int +Warning(fmt, va_alist) +char *fmt; +va_dcl; +#endif +#endif +{ + 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 + +Usage( eflag ) +int eflag; +{ + register char *p; + char *fill; + + fill = _strdup(Pname); + for(p=fill; *p; p++) *p=' '; + + if( eflag ) { + fprintf(stderr, USAGE, Pname); + fprintf(stderr, USAGE2, fill); + } + else { + printf(USAGE, Pname); + fprintf(stderr, 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(" -v{dfimt} - verbose, indicate what we are doing, (-v => -vdimt)"); + 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\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(" -E - define environment strings as macros"); + puts(" -e - same as -E but done after parsing makefile"); + 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 +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); +} diff --git a/dmake/dmake.h b/dmake/dmake.h new file mode 100644 index 0000000..9e07135 --- /dev/null +++ b/dmake/dmake.h @@ -0,0 +1,183 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/dmake.h,v 1.1 1992/01/24 03:26:50 dvadura Exp $ +-- SYNOPSIS -- global defines for dmake. +-- +-- DESCRIPTION +-- All the interesting bits and flags that dmake uses are defined here. +-- +-- 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. +-- +-- LOG +-- $Log: dmake.h,v $ + * Revision 1.1 1992/01/24 03:26:50 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 \ */ +#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_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 MAX_ATTR A_NOSTATE /* highest valid attribute */ +#define A_LIBRARYM 0x10000 /* target is an archive member */ +#define A_FRINGE 0x20000 /* cell is on the fringe */ +#define A_COMPOSITE 0x40000 /* member of lib(targ) name */ +#define A_FFNAME 0x80000 /* if set, free ce_fname in stat*/ +#define A_UPDATED 0x100000 /* Used to mark cell as updated */ +#define A_ROOT 0x200000 /* True if it is a root prereq */ + + +/* 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 releparse.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 '=' */ +#define M_OP_CL 2 /* macro operation is ':=' */ +#define M_OP_PL 3 /* macro operation is '+=' */ +#define M_OP_PLCL 4 /* macro operation is '+:='*/ +#define M_OP_DF 5 /* macro operation is '*=' */ +#define M_OP_DFCL 6 /* macro operation is '*:='*/ + +/* 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 ':-' */ + +/* 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 + +/* 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 + +/* Flags for controling use of -v switch */ +#define V_NONE 0x00 +#define V_LEAVE_TMP 0x01 +#define V_PRINT_DIR 0x02 +#define V_INFER 0x04 +#define V_MAKE 0x08 +#define V_FILE_IO 0x10 +#define V_ALL (V_LEAVE_TMP | V_PRINT_DIR | V_INFER | V_MAKE |\ + V_FILE_IO) + +/* 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')) + +#endif + diff --git a/dmake/dmdump.c b/dmake/dmdump.c new file mode 100644 index 0000000..e6da089 --- /dev/null +++ b/dmake/dmdump.c @@ -0,0 +1,209 @@ +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/dmdump.c,v 1.2 1992/04/07 04:42:46 dvadura 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@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. +-- +-- LOG +-- $Log: dmdump.c,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Deleted define of unused variable. + * + * Revision 1.1 1992/01/24 03:28:51 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +#define M_TEST (M_PRECIOUS | M_VAR_MASK) + +static void dump_name ANSI((HASHPTR, int)); +static void dump_normal_target ANSI((CELLPTR, int)); +static void dump_prerequisites ANSI((LINKPTR, int, int, 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; iht_next ) { + int flag = hp->ht_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' ); + } + + puts( "\n#====================================" ); + puts( "# Dump of targets:\n" ); + + for( i=0; iht_next ) + if( !(hp->CP_OWNR->ce_flag & F_PERCENT) ) { + if( Root->ce_prq && hp->CP_OWNR == Root->ce_prq->cl_prq ) + puts( "# ******* FIRST TARGET ********" ); + dump_normal_target( hp->CP_OWNR, hp->CP_OWNR->ce_flag ); + } + + puts( "\n#====================================" ); + puts( "# Dump of inference graph\n" ); + + for( i=0; iht_next ) + if( (hp->CP_OWNR->ce_flag & F_PERCENT) && + !(hp->CP_OWNR->ce_flag & F_MAGIC) ) + dump_normal_target( hp->CP_OWNR, 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" }; + +static void +dump_normal_target( cp, flag )/* +================================ + Dump in makefile like format the dag information */ +CELLPTR cp; +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 ) { 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_prerequisites(cp->ce_prq, FALSE, TRUE, tflag); + } + else { + dump_name( cp->ce_name, FALSE ); + + 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, FALSE, FALSE, F_DEFAULT); + dump_prerequisites( cp->ce_indprq, 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' ); + } + + DB_VOID_RETURN; +} + + +static void +dump_prerequisites( lp, quote, recurse, flag ) +LINKPTR lp; +int quote; +int recurse; +int flag; +{ + for( ; lp; lp=lp->cl_next ) + if( recurse ) + dump_normal_target(lp->cl_prq, flag); + else if( lp->cl_prq ) + dump_name(lp->cl_prq->ce_name, quote); +} + + +static void +dump_name( hp, quote )/* +======================== + print out a name */ +HASHPTR hp; +int quote; +{ + if( quote ) putchar('\''); + printf( "%s", hp->ht_name ); + if( quote ) putchar('\''); + putchar(' '); +} diff --git a/dmake/dmstring.c b/dmake/dmstring.c new file mode 100644 index 0000000..b22e2a9 --- /dev/null +++ b/dmake/dmstring.c @@ -0,0 +1,302 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/dmstring.c,v 1.1 1992/01/24 03:29:38 dvadura 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@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. +-- +-- LOG +-- $Log: dmstring.c,v $ + * Revision 1.1 1992/01/24 03:29:38 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +PUBLIC char * +_strjoin( 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( "_strjoin" ); + + 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 * +_stradd( 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( "_stradd" ); + + 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 * +_strapp( 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 = _stradd( src1, src2, FALSE ); + if( src1 != NIL(char) ) FREE( src1 ); + return( src2 ); +} + + + +#ifdef DBUG +#ifdef _strdup +#undef _strdup +#endif +#endif +PUBLIC char * +_strdup( 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 * +_strdup2( 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("_strdup2 invoked without argument of form x=y\n"); + + *dest++ = '"'; + *dest = 0; + + return t; +} + + + +PUBLIC char * +_strpbrk( 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 * +_strspn( 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 * +_strstr( 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 * +_substr( 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 = _strdup( s ); + *e = save; + + return( s ); +} diff --git a/dmake/expand.c b/dmake/expand.c new file mode 100644 index 0000000..eca8cff --- /dev/null +++ b/dmake/expand.c @@ -0,0 +1,921 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/expand.c,v 1.1 1992/01/24 03:27:03 dvadura 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 +-- +-- 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@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. +-- +-- LOG +-- $Log: expand.c,v $ + * Revision 1.1 1992/01/24 03:27:03 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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_token ANSI((char*, char**)); +static char* _scan_macro ANSI((char*, char**)); +static char* _scan_brace ANSI((char*, char**, int*)); +static char* _cross_prod ANSI((char*, char*)); + + +PUBLIC char * +Expand( src )/* +=============== + This is the driver routine for the expansion, it identifies non-white + space tokens and gets the _scan_token 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 = _strdup( "" ); + 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. */ + + start = _strspn( src, " \t\n" ); + res = _strjoin( res, src, start-src, TRUE ); + if( !(*start) ) break; + + /* START <+...+> KLUDGE */ + if( (ks=_strstr(start,"<+")) && (ke=_strstr(ks,"+>")) ){ + char *t1, *t2; + + res = _strjoin( res, t2=Expand(t1=_substr(start,ks)), -1, TRUE); + FREE(t1); FREE(t2); + + t1 = _substr(ks+2, ke+1); t1[ke-ks-2] = ')'; + t2 = _strjoin( "$(mktmp ", t1, -1,FALSE); + FREE(t1); + res = _strjoin( res, t2=Expand(t2), -1, TRUE); + FREE(t2); + src = ke+2; + } + /* END <+...+> KLUDGE */ + else { + res = _strjoin( res, tmp = _scan_token( start, &src ), -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 = _strstr( s, pat )) != NIL(char) ) { + res = _strdup( "" ); + do { + if( anchor ) + if( !*(p+l) || (strchr(" \t", *(p+l)) != NIL(char)) ) + res = _strjoin( _strjoin( res, s, p-s, TRUE ), subst, -1, TRUE ); + else + res = _strjoin( res, s, p+l-s, TRUE ); + else + res = _strjoin( _strjoin( res, s, p-s, TRUE ), subst, -1, TRUE ); + + s = p + l; + } + while( (p = _strstr( s, pat )) != NIL(char) ); + + res = _strjoin( 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 == (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 )/* +============================ + Tokenize the input of src and join each token found together with + the next token separated by the separator string. + + When doing the tokenization, , , , and \ all + constitute white space. */ + +char *src; +char *separator; +{ + TKSTR tokens; + char *tok; + char *res; + int first = TRUE; + + DB_ENTER( "Tokenize" ); + + SET_TOKEN( &tokens, src ); + + + /* map the escape codes in the separator string first */ + + for(tok=separator; (tok = strchr(tok,ESCAPE_CHAR)) != NIL(char); tok++) + Map_esc( tok ); + + DB_PRINT( "exp", ("Separator [%s]", separator) ); + + /* Build the token list */ + res = _strdup( "" ); + while( *(tok = Get_token( &tokens, "", FALSE )) != '\0' ) { + DB_PRINT( "exp", ("Tokenizing [%s]", tok) ); + + if( first ) { + FREE( res ); + res = _strdup( tok ); + first = FALSE; + } + else { + char *x; + res = _strjoin(res, x =_strjoin(separator, tok, -1, FALSE), -1, TRUE); + FREE( x ); + } + } + + FREE( src ); + DB_RETURN( res ); +} + + +static char* +_scan_token( s, ps )/* +====================== + 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 */ +{ + char *res; /* pointer to result */ + char *start; /* pointer to start of prefix */ + int crossproduct = 0; /* if 1 then computing X-prod */ + + start = s; + res = _strdup( "" ); + 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 = _strjoin( res, start, (s-start), TRUE ); + else + { + tmp = _substr( 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 = _substr( start, s ); /* save the prefix */ + + if( *s == '$' ) { + start = _scan_macro( s+1, &s ); + + if( crossproduct ) + res = _cross_prod( res, _strjoin( tmp, start, -1, TRUE ) ); + else { + res = _strjoin(res,tmp = _strjoin(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 ) { + res = _cross_prod( res, _cross_prod(tmp, start) ); + crossproduct = TRUE; + } + else { + res =_strjoin(res,tmp=_strjoin(tmp,start,-1,TRUE),-1,TRUE); + FREE( start ); + FREE( tmp ); + } + } + else { /* handle the {{ case */ + res = _strjoin( 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 = _strjoin( res, start, (s-start+1), TRUE ); + s += 2; + start = s; + } + break; + + default: s++; + } +} + + +static char* +_scan_macro( s, ps )/* +====================== + 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: + + $$ - 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 */ +{ + 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 the simple $ at end of line case */ + if( !*s ) { + *ps = s; + DB_RETURN( _strdup("") ); + } + + if( *s == '$' ) { /* Take care of the simple $$ case. */ + *ps = s+1; + DB_RETURN( _strdup("$") ); + } + + 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 ) { + done = TRUE; + mflag = 1; + } + break; + + case ' ': + case '\t': + case '\n': + fflag = 1; + break; + + case '\0': /* check for null */ + *ps = s; + if( lev ) { + done = TRUE; + bflag = 0; + s = start; + } + break; + + case ')': /* close macro brace */ + case '}': + if( *s == edelim && lev ) --lev; + /*FALLTHROUGH*/ + + 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 = _substr( start+1, s-1 ); + else + macro_name = _substr( start, s ); + + /* 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. */ + if( fflag ) + 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 ); + + /* for M_MULTI macro variable assignments */ + If_multi = hp->ht_flag & M_MULTI; + + 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 = _strdup( hp->ht_value ); + else + result = _strdup( "" ); + + /* + * 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 = _strdup( "" ); + } + + 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 == '=' ) { + pat1 = _substr( s, p ); + for( s=p=p+1; (*p != edelim); p++ ); + + pat2 = _substr( s, p ); + + if( !Augmake ) { + char *tmp = pat2; + pat2 = Expand(pat2); + 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 */ + switch( *s++ ) { + 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 '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 = _substr( s, p ); + for(s=p=p+1; (*p != separator) && (*p != edelim); p++ ); + pat2 = _substr( 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': + if( modifier_list ) { + Warning( "Tokenize modifier must appear alone, ignored"); + modifier_list = 0; + } + else { + char *msg = "Separator string must be quoted"; + + separator = *s++; + + if( separator != '\"' ) + Warning( msg ); + else { + /* 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 = _substr( s, p ); + result = Tokenize( result, pat1 ); + FREE( pat1 ); + } + 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 ':': + 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 = _substr( start, (lev) ? s : s-1 ); + + if( lev ) { + /* Braces were not ballanced so just return the string. + * Do not expand it. */ + + res = _strjoin( "{", start, -1, FALSE ); + *flag = 0; + } + else { + *flag = 1; + res = Expand( start ); + + if( (t = _strspn( res, " \t" )) != res ) strcpy( res, t ); + } + + FREE( start ); /* this is ok! start is assigned a _substr 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; + static int buf_siz = 0; + char *brkx; + char *brky; + char *cy; + char *cx; + char *res; + int i; + + if( *x && *y ) { + res = _strdup( "" ); cx = x; + while( *cx ) { + cy = y; + brkx = _strpbrk( cx, " \t\n" ); + if( (brkx-cx == 2) && *cx == '\"' && *(cx+1) == '\"' ) cx = brkx; + + while( *cy ) { + brky = _strpbrk( 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 = _strjoin( res, buf, -1, TRUE ); + cy = _strspn( brky, " \t\n" ); + } + cx = _strspn( brkx, " \t\n" ); + } + + FREE( x ); + res[ strlen(res)-1 ] = '\0'; + } + else + res = _strjoin( x, y, -1, TRUE ); + + FREE( y ); + return( res ); +} diff --git a/dmake/extern.h b/dmake/extern.h new file mode 100644 index 0000000..cb2ec0a --- /dev/null +++ b/dmake/extern.h @@ -0,0 +1,78 @@ +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/extern.h,v 1.2 1992/04/07 04:42:46 dvadura 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@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. +-- +-- LOG +-- $Log: extern.h,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Changed namemax.h to posix.h. + * + * Revision 1.1 1992/01/24 03:26:52 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 +#include +#include +#include +#include +#include +#if defined (_MPW) +# include +# include +#else +# include +# include +#endif +#include +#include "itypes.h" +#include "stdmacs.h" +#include "alloc.h" +#include "db.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 0000000..4c692a5 --- /dev/null +++ b/dmake/function.c @@ -0,0 +1,356 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/function.c,v 1.1 1992/01/24 03:27:00 dvadura 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@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. +-- +-- LOG +-- $Log: function.c,v $ + * Revision 1.1 1992/01/24 03:27:00 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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_shell 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 functions is called in the first place. */ + fname = _substr(buf, args=_strpbrk(buf," \t\n")); + + if( (mod1 = strchr(fname,',')) != NIL(char) ){ + *mod1 = '\0'; + mod1++; + + if( (mod2 = strchr(mod1,',')) != NIL(char) ){ + *mod2 = '\0'; + mod2++; + } + } + + switch( *fname ) { + case 'e': + if(strncmp(fname,"eq",2) == 0) res = _exec_iseq(mod1,mod2,args,TRUE); + break; + + case 'm': + if( strncmp(fname,"mktmp", 5) == 0 ) res = _exec_mktmp(mod1,mod2,args); + break; + + case 'n': + if( strncmp(fname,"null", 4) == 0 ) + res = _exec_iseq(mod1,NIL(char),args,TRUE); + break; + + case '!': + if(strncmp(fname,"!null",5) == 0) + res = _exec_iseq(mod1,NIL(char),args,FALSE); + if(strncmp(fname,"!eq",3) == 0) res = _exec_iseq(mod1,mod2,args,FALSE); + break; + + case 's': + if(strncmp(fname,"sort",4) == 0) res = _exec_sort(args); + else if(strncmp(fname,"shell",5)==0) res = _exec_shell(args); + else if(strncmp(fname,"strip",5)==0) res = Tokenize(Expand(args)," "); + else if(strncmp(fname,"subst",5)==0) res = _exec_subst(mod1,mod2,args); + break; + + default: + Warning( "Function '%s' not implemented at this time", fname ); + } + + if( res == NIL(char) ) res = _strdup(""); + + FREE(fname); + 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(_strspn(data, " \t\n")); + + for(p=strchr(data,'\n'); p; p=strchr(p,'\n')) { + char *q = _strspn(++p," \t"); + strcpy(p,q); + } + + Append_line( data, FALSE, tmpfile, name, FALSE, TRUE ); + 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 = _strspn(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 = _strspn(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 = NIL(char *); + char *p; + char *white = " \t\n"; + int j; + int i = 0; + + for( i=0,p=_strspn(data,white); *p; p=_strspn(_strpbrk(p,white),white),i++); + + if( i != 0 ) { + TALLOC(tokens, i, char *); + + for( i=0,p=_strspn(data,white); *p; p=_strspn(p,white),i++){ + tokens[i] = p; + p = _strpbrk(p,white); + if( *p ) *p++ = '\0'; + } + + qsort( tokens, i, sizeof(char *), _mystrcmp ); + + for( j=0; j 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 <\>. +-- +-- 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@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. +-- +-- LOG +-- $Log: getinp.c,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Minor clean up and a check for -X flag on the execution of #! lines. + * + * Revision 1.1 1992/01/24 03:27:56 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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; + + DB_ENTER( "Get_line" ); + + 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 ); + + Line_number++; + + /* ignore input if ignore flag set and line ends in a continuation + character. */ + q = p+strlen(p)-2; + if( q

) + * 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" ); + + + /* 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 = _strspn(buf, " \t\r\n")) == CONDSTART ) { + TKSTR token; + + SET_TOKEN( &token, p ); + + p = Get_token( &token, "", FALSE ); + + if( (res = _is_conditional( p )) ) /* 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[10]; + + 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 = _strspn( 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 = _strpbrk(t, space); + + if( anchor && *curp && !IS_WHITE( *curp ) ) + if( ((anchor == 1)?*curp:_strspn(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 ); 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; + int result; + + 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" ); + /* FALLTHROUGH */ + + case ST_IF: + if( opcode == ST_IF && (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 = _strspn( expr, " \t" ); + if( !*lhs ) lhs = NIL(char); + + if( (op = _strstr( lhs, "==" )) == NIL(char) ) + op = _strstr( lhs, "!=" ); + + if( op == NIL(char) ) + result = (lhs != NIL(char)); + else { + op[1] = op[0]; + if( lhs != op ) { + for( tok = op-1; (tok != lhs) && ((*tok == ' ')||(*tok == '\t')); + tok-- ); + tok[1] = '\0'; + } + else + lhs = NIL(char); + + op++; + rhs = _strspn( op+1, " \t" ); + if( !*rhs ) rhs = NIL(char); + + 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 == '!' ) result = !result; + } + + if( expr != NIL(char) ) FREE( expr ); + + if( opcode == ST_IF ) { + Nest_level++; + action[Nest_level] = 1; + } + ifcntl[Nest_level] |= (opcode==ST_IF)?SEEN_IF:SEEN_ELIF; + + if( result ) { + if( !(ifcntl[Nest_level] & (ACCEPT_IF|ACCEPT_ELIF)) ) { + action[ Nest_level ] = action[ Nest_level-1 ]; + ifcntl[Nest_level] |= (opcode==ST_IF)?ACCEPT_IF:ACCEPT_ELIF; + } + 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 ] ); +} diff --git a/dmake/hash.c b/dmake/hash.c new file mode 100644 index 0000000..d86167e --- /dev/null +++ b/dmake/hash.c @@ -0,0 +1,61 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/hash.c,v 1.1 1992/01/24 03:27:06 dvadura 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@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. +-- +-- LOG +-- $Log: hash.c,v $ + * Revision 1.1 1992/01/24 03:27:06 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 0000000..9b1a659 --- /dev/null +++ b/dmake/imacs.c @@ -0,0 +1,172 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/imacs.c,v 1.1 1992/01/24 03:29:55 dvadura 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@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. +-- +-- LOG +-- $Log: imacs.c,v $ + * Revision 1.1 1992/01/24 03:29:55 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.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; + char swchar[2]; + + swchar[0] = Get_switch_char(), swchar[1] = '\0'; + _set_string_var("SWITCHAR", swchar, M_PRECIOUS, &switchar); + _set_string_var("DIRSEPSTR", (*swchar=='/')?"\\":"/",M_PRECIOUS,&DirSepStr); + _set_string_var("DIRBRKSTR", DirBrkStr, M_PRECIOUS, &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 ); + + 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("PREP", "0", M_DEFAULT, &Prep ); + _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(".SETDIR", "", M_DEFAULT|M_NOEXPORT, &Start_dir ); + _set_string_var("MAKEDIR",Get_current_dir(),M_PRECIOUS|M_NOEXPORT,&Makedir); + _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 ); + (void) Def_macro("MAXLINELENGTH", "0", 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 ); +} + + +/* +** 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; + 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; + 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; + hp->MV_MASK = mask; + hp->MV_BVAR = &Glob_attr; +} diff --git a/dmake/infer.c b/dmake/infer.c new file mode 100644 index 0000000..67486c9 --- /dev/null +++ b/dmake/infer.c @@ -0,0 +1,822 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/infer.c,v 1.1 1992/01/24 03:27:21 dvadura 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@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. +-- +-- LOG +-- $Log: infer.c,v $ + * Revision 1.1 1992/01/24 03:27:21 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 * _build_name ANSI((char *, char *, char *)); +static void _free_icells ANSI(()); +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)); + +static int _prep = -1; /* Integer value of Prep variable */ + + +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;} + if( _prep == -1 ) _prep = atoi(Prep); /* _dfa_subset needs _prep */ + + match = NIL(ICELL); + nomatch = _add_iset( NIL(ICELL), NIL(ICELL), NIL(CELL), NIL(DFALINK), + setdirroot, _prep+_count_dots(cp->CE_NAME), 0, + _strdup(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 ambigous 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. + * + * NOTE: May turn this around at some point. + */ + + /* 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; + } + + 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=_strdup(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 = _build_name( 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 + * decuce 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 = _build_name( 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) ) { + 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); + } + + + /* 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 * +_build_name( 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 = _strdup( 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" ); + + 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 ); + + if( subset = (subel != NIL(DFALINK)) ) 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 = _strdup(dir); + icell->ic_name = _strdup(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 = _strjoin(tmp, "(", -1, TRUE); + tmp = _strjoin(tmp, ip->ic_meta->CE_NAME, -1, TRUE); + + if( ip->ic_dir && !*ip->ic_dir ) { + tmp = _strjoin(tmp, "[", -1, TRUE); + if( strncmp(Makedir,ip->ic_dir, strlen(Makedir)) ) + tmp = _strjoin(tmp, ip->ic_dir, -1, TRUE); + else + tmp = _strjoin(tmp, ip->ic_dir+strlen(Makedir)+1, -1, TRUE); + tmp = _strjoin(tmp, "]", -1, TRUE); + } + tmp = _strjoin(tmp, (ip->ic_name)?") -->":")", -1, TRUE); + } + + if( ip->ic_name ) tmp = _strapp( tmp, ip->ic_name ); + + if( flag && ip->ic_meta->ce_prq) { + tmp = _strjoin(tmp, "(", -1, TRUE); + tmp = _strjoin(tmp, ip->ic_meta->ce_prq->cl_prq->CE_NAME, -1, TRUE); + tmp = _strjoin(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 = _strapp( tmp, pdfa->dl_meta->CE_NAME ); + + tmp = _strapp( tmp, ":: {" ); + for( ds = dfa_stack; ds != NIL(DFASET); ds = ds->df_next ) { + tmp = _strapp( tmp, "[" ); + for( pdfa = ds->df_set; pdfa != NIL(DFALINK); pdfa = pdfa->dl_next ) + tmp = _strapp( tmp, pdfa->dl_meta->CE_NAME ); + tmp = _strapp( tmp, "]" ); + } + tmp = _strapp( 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 0000000..d53af66 --- /dev/null +++ b/dmake/itypes.h @@ -0,0 +1,56 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/itypes.h,v 1.1 1992/01/24 03:29:40 dvadura Exp $ +-- SYNOPSIS -- type declarations for common types +-- +-- DESCRIPTION +-- portable type declarations. +-- +-- 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. +-- +-- LOG +-- $Log: itypes.h,v $ + * Revision 1.1 1992/01/24 03:29:40 dvadura + * dmake Version 3.8, Initial revision + * +*/ + + +#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 0000000..dcef823 --- /dev/null +++ b/dmake/mac/arlib.c @@ -0,0 +1,58 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/arlib.c,v 1.1 1992/01/24 03:29:41 dvadura Exp $ +-- SYNOPSIS -- Library access code. +-- +-- DESCRIPTION +-- This implementation uses the library timestamp inplace of the +-- library member timestamp. +-- +-- 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. +-- +-- LOG +-- $Log: arlib.c,v $ + * Revision 1.1 1992/01/24 03:29:41 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +PUBLIC time_t +seek_arch(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)); +} + +PUBLIC int +touch_arch(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 0000000..329c644 --- /dev/null +++ b/dmake/mac/bogus.c @@ -0,0 +1,92 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/bogus.c,v 1.1 1992/01/24 03:29:42 dvadura 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@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. +-- +-- LOG +-- $Log: bogus.c,v $ + * Revision 1.1 1992/01/24 03:29:42 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 /* group */, + 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.h b/dmake/mac/config.h new file mode 100644 index 0000000..609c284 --- /dev/null +++ b/dmake/mac/config.h @@ -0,0 +1,87 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/config.h,v 1.1 1992/01/24 03:29:43 dvadura Exp $ +-- SYNOPSIS -- Configurarion include file for the Macintosh. +-- +-- 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@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. +-- +-- LOG +-- $Log: config.h,v $ + * Revision 1.1 1992/01/24 03:29:43 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* Definitions left out of StdArg.h */ +#define va_alist ... +#define va_dcl + +#define CONST const + +#define FALSE 0 +#define TRUE 1 + +/* signal extensions */ +#define SIGQUIT SIGTERM + + +/* Mac doesn't have a stat function or structure so we have to add one in. */ +typedef long off_t; +struct stat { + unsigned short st_mode; + off_t st_size; + time_t st_mtime; + time_t st_ctime; + /* struct stat has lots of other fields, but we don't need them for dmake */ +}; /* struct stat */ +#define S_IFDIR 0040000 /* directory */ +#define S_IFREG 0100000 /* regular */ +#define S_IFMT (S_IFDIR | S_IFREG) /* Format */ +#define S_IREAD 0000400 /* read owner permission */ +#define S_IWRITE 0000200 /* write owner permission */ +#define S_IEXEC 0000100 /* execute owner permission */ + + +/* Global for environmental variables */ +extern char **environ; + + +/* We really want main to be in the mac directory + so that we get the envp argument */ +#define main(argc, argv) dmakemain(argc, argv) + +/* Directory/file info. and directory moving */ +int stat (char *pPath, struct stat *pStat); +char *getcwd (char *pPath, size_t pathSize); +int chdir (char *pPath); +int utime (char *pPath, time_t *pTimes); + +/* Routines to handle conversion from Unix file names to Mac file names */ +char *Unix2MacFName(char *pUnixName); +FILE *MacFOpen (char *pName, char *pMode); +#define fopen(pFName, pMode) MacFOpen(pFName, pMode) + +/* a small problem with pointer to voids on some unix machines needs this */ +#define PVOID void * diff --git a/dmake/mac/config.mk b/dmake/mac/config.mk new file mode 100644 index 0000000..276becc --- /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 0000000..c0afcf0 --- /dev/null +++ b/dmake/mac/dirbrk.c @@ -0,0 +1,52 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/dirbrk.c,v 1.1 1992/01/24 03:29:44 dvadura 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@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. +-- +-- LOG +-- $Log: dirbrk.c,v $ + * Revision 1.1 1992/01/24 03:29:44 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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; +{ + name = Unix2MacFName (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 0000000..eaa4f1e --- /dev/null +++ b/dmake/mac/directry.c @@ -0,0 +1,270 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/directry.c,v 1.1 1992/01/24 03:29:45 dvadura 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@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. +-- +-- LOG +-- $Log: directry.c,v $ + * Revision 1.1 1992/01/24 03:29:45 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include +#include +#include +#include +#include +#include +#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; + + pPath = Unix2MacFName (pPath); + + 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; + + pPath = Unix2MacFName (pPath); + + /* 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, 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; + + pPath = Unix2MacFName (pPath); + + /* Set up the directory */ + c2pstr (pPath); + WDPB.ioCompletion = NULL; + WDPB.ioNamePtr = 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 (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 (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; + + pPath = Unix2MacFName (pPath); + + 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 0000000..bc72da6 --- /dev/null +++ b/dmake/mac/dompwmak @@ -0,0 +1,54 @@ +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 +link -w -c 'MPS ' -t MPST -sym off -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:basename.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 "Micah:MPW:Libraries:CLibraries:CSANELib.o" "Micah:MPW:Libraries:CLibraries:Math.o" "Micah:MPW:Libraries:CLibraries:StdCLib.o" "Micah:MPW:Libraries:Libraries:Runtime.o" "Micah:MPW:Libraries:Libraries:Interface.o" "Micah:MPW:Libraries:Libraries:Toollibs.o" +duplicate :mac:startup.mk startup.mk diff --git a/dmake/mac/environ.c b/dmake/mac/environ.c new file mode 100644 index 0000000..849385d --- /dev/null +++ b/dmake/mac/environ.c @@ -0,0 +1,236 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/environ.c,v 1.1 1992/01/24 03:29:46 dvadura 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@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. +-- +-- LOG +-- $Log: environ.c,v $ + * Revision 1.1 1992/01/24 03:29:46 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 0000000..658770a --- /dev/null +++ b/dmake/mac/eold.c @@ -0,0 +1,128 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/eold.c,v 1.1 1992/01/24 03:29:47 dvadura 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@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. +-- +-- LOG +-- $Log: eold.c,v $ + * Revision 1.1 1992/01/24 03:29:47 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 0000000..881c084 --- /dev/null +++ b/dmake/mac/main.c @@ -0,0 +1,52 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/main.c,v 1.1 1992/01/24 03:29:48 dvadura 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@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. +-- +-- LOG +-- $Log: main.c,v $ + * Revision 1.1 1992/01/24 03:29:48 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 0000000..3c5ca56 --- /dev/null +++ b/dmake/mac/make.sh @@ -0,0 +1,43 @@ +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 +c -I. -I :mac -d _MPW -s arlib -sym off -o :objects:arlib.c.o :mac:arlib.c +c -I. -I :mac -d _MPW -s bogus -sym off -o :objects:bogus.c.o :mac:bogus.c +c -I. -I :mac -d _MPW -s dirbrk -sym off -o :objects:dirbrk.c.o :mac:dirbrk.c +c -I. -I :mac -d _MPW -s directry -sym off -o :objects:directry.c.o :mac:directry.c +c -I. -I :mac -d _MPW -s environ -sym off -o :objects:environ.c.o :mac:environ.c +c -I. -I :mac -d _MPW -s main -sym off -o :objects:main.c.o :mac:main.c +c -I. -I :mac -d _MPW -s rmprq -sym off -o :objects:rmprq.c.o :mac:rmprq.c +c -I. -I :mac -d _MPW -s ruletab -sym off -o :objects:ruletab.c.o :mac:ruletab.c +c -I. -I :mac -d _MPW -s tempnam -sym off -o :objects:tempnam.c.o :mac:tempnam.c +c -I. -I :mac -d _MPW -s tomacfil -sym off -o :objects:tomacfil.c.o :mac:tomacfil.c +link -w -c 'MPS ' -t MPST -sym off -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:basename.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 "CSANELib.o" \ +"Math.o" "StdCLib.o" "Runtime.o" "Interface.o" "Toollibs.o" +duplicate :mac:startup.mk startup.mk diff --git a/dmake/mac/public.h b/dmake/mac/public.h new file mode 100644 index 0000000..97ad876 --- /dev/null +++ b/dmake/mac/public.h @@ -0,0 +1,152 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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(()); +void tzset () {} PUBLIC int putenv ANSI((PUBLIC int Wait_for_child(int /* abort_flg */, int /* pid */) {return (1))); +int If_root_path ANSI((char *)); +int stat(pPath, pStat) pPath = Unix2MacFName ANSI(()); +void make_env () { if ANSI((environ = MALLOC (1, char *), *environ = NULL)); +void free_env () { while ANSI((//FREE (environ), environ = NULL)); +void Remove_prq ANSI((CELLPTR)); +char *tempnam (char * /* pDir */, char * pPrefix) { pName = tmpnam ANSI(()); +char *Unix2MacFName(char *pUnixName) { if ANSI(()); + +#endif diff --git a/dmake/mac/rmprq.c b/dmake/mac/rmprq.c new file mode 100644 index 0000000..0c499b5 --- /dev/null +++ b/dmake/mac/rmprq.c @@ -0,0 +1,47 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/rmprq.c,v 1.1 1992/01/24 03:29:48 dvadura 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@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. +-- +-- LOG +-- $Log: rmprq.c,v $ + * Revision 1.1 1992/01/24 03:29:48 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +PUBLIC void +Remove_prq( tcp ) +CELLPTR tcp; +{ + tcp->ce_flag &= ~(F_MADE|F_VISITED); + tcp->ce_time = 0L; + + Make( tcp, NIL(LINK), NIL(CELL) ); +} diff --git a/dmake/mac/ruletab.c b/dmake/mac/ruletab.c new file mode 100644 index 0000000..085ac46 --- /dev/null +++ b/dmake/mac/ruletab.c @@ -0,0 +1,52 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/ruletab.c,v 1.1 1992/01/24 03:29:49 dvadura 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@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. +-- +-- LOG +-- $Log: ruletab.c,v $ + * Revision 1.1 1992/01/24 03:29:49 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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: MPW DMSTARTUPDIR", + ".MAKEFILES : makefile.mk 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 0000000..1a55d93 --- /dev/null +++ b/dmake/mac/startup.h @@ -0,0 +1,7 @@ +/* This file contains the default value of the DMMAKESTARTUP variable. + * You must set the quoted string below to the default path to the startup + * variable, so that it gets compiled in. LEAVE DMSTARTUPDIR in + * the path. This allows the user to customize his environment for dmake + * by setting up a new DMSTARTUPDIR environment variable. */ + +"MAKESTARTUP := $(MPW)tools:$(DMSTARTUPDIR)startup.mk", diff --git a/dmake/mac/startup.mk b/dmake/mac/startup.mk new file mode 100644 index 0000000..c2f47b5 --- /dev/null +++ b/dmake/mac/startup.mk @@ -0,0 +1,126 @@ +# MPW Mac startup file. Customize to suit your needs. +# Assumes MPW 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 +C := .c # C +E := # Executables +F := .f # Fortran +O := .c.o # Object files: Assume they are created from C files +P := .p # Pascal +S := .a # Assembler sources +V := v # RCS suffix + +# See if these are defined +TMPDIR := $(MPW)/tmp +.IMPORT .IGNORE : TMPDIR +.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 +SHELLFLAGS := +GROUPFLAGS := +SHELLMETAS := +GROUPSUFFIX := +DIVFILE = $(TMPFILE) + +# Standard C-language command names and flags + CC := c # C-compiler and flags + CFLAGS += + + AS := asm # Assembler and flags + ASFLAGS += + + LD = link # Loader and flags + LDFLAGS += + LDLIBS = "$(CLibraries)CSANELib.o" "$(CLibraries)Math.o" \ + "$(CLibraries)StdCLib.o" "$(Libraries)Runtime.o" \ + "$(Libraries)Interface.o" "$(Libraries)Toollibs.o" + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(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 + + RM := delete # 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 + %$C.o : %$C ; $(CC) $(CFLAGS) -c $< + %$P.o : %$P ; $(PC) $(PFLAGS) -c $< + %$S.o : %$S ; $(AS) $(ASFLAGS) $(<:s,/,\); + %$F.o : %$F ; $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $< + +# Executables rules should go here. However, on the Mac, there is not +# executable suffix (such as ".exe") and thus we end up with rules like +# "% : %.c.o", which cause circular-dependency errors. Thus, it's easier +# just to avoid specifiying any default rule for executables. + +# 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 + +# DMAKE uses this recipe to remove intermediate targets +.REMOVE :; $(RM) $< + +# AUGMAKE extensions for SYSV compatibility +@B = $(@:b) +@D = $(@:d) +@F = $(@:f) +"*B" = $(*:b) +"*D" = $(*:d) +"*F" = $(*:f) + +#include + + + +/* + * 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 0000000..3fab263 --- /dev/null +++ b/dmake/mac/tomacfil.c @@ -0,0 +1,114 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/tomacfil.c,v 1.1 1992/01/24 03:29:53 dvadura 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@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. +-- +-- LOG +-- $Log: tomacfil.c,v $ + * Revision 1.1 1992/01/24 03:29:53 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" +int IsUnixFName (char *pFileName); + + + +/* + * Convert a file that may be in unix format to mac format. + * + * The returned name is either the untouched pUnixName, or a static buffer. + */ +PUBLIC char *Unix2MacFName(char *pUnixName) { + static char MacName[256]; + char *pCurMac; + + if (IsUnixFName (pUnixName)) { + if (strlen (pUnixName) + (*pUnixName == '/' ? -1 : 1) >= sizeof (MacName)) { + Fatal ("File name '%s' is too long and will cause a buffer overflow", pUnixName); + } /* if */ + + /* Set up relative or absolute path */ + pCurMac = MacName; + if (*pUnixName == '/') { + ++pUnixName; + } else { + *(pCurMac++) = ':'; + } /* if ... else */ + + /* Convert the rest of the name */ + while (*pUnixName != '\0') { + if (*pUnixName == '/') { + *(pCurMac++) = ':'; + pUnixName++; + + } else { + *(pCurMac++) = *(pUnixName++); + } /* if ... else */ + } /* while */ + + *pCurMac = '\0'; + return (MacName); + + } else { + return (pUnixName); + } /* if ... else */ +} /* PUBLIC char *Unix2MacFName() */ + + + +/* + * Is this file name in UNIX format? + * (We assume it is if there are any slashes in its name.) + */ +int IsUnixFName (char *pFileName) { + + for ( ; *pFileName != '\0'; ++pFileName) { + if (*pFileName == '/') { + return (TRUE); + } /* if */ + } /* while */ + + return (FALSE); +} /* int IsUnixFName () */ + + + +/* + * Call the real fopen() from this override of the function + * that the rest of the program uses. + */ +#undef fopen +PUBLIC FILE *MacFOpen (char *pFName, char *pMode) { + return (fopen (Unix2MacFName (pFName), pMode)); +} /* PUBLIC FILE *MacFOpen () */ diff --git a/dmake/macparse.c b/dmake/macparse.c new file mode 100644 index 0000000..1b83fff --- /dev/null +++ b/dmake/macparse.c @@ -0,0 +1,167 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/macparse.c,v 1.1 1992/01/24 03:27:52 dvadura 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@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. +-- +-- LOG +-- $Log: macparse.c,v $ + * Revision 1.1 1992/01/24 03:27:52 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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; +{ + register char *tok1; /* temporary place to keep a token */ + register char *tok2; /* temporary place to keep a token */ + 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 */ + + DB_ENTER( "Parse_macro" ); + + SET_TOKEN( &input, buffer ); + tok1 = Get_token( &input, "=+:*", 0 ); + + if( Macro_op( tok1 ) ) { + Error( "No macro name" ); + CLEAR_TOKEN( &input ); + DB_RETURN( 1 ); + } + + tok1 = _strdup( tok1 ); + tok2 = Get_token( &input, "=+:*", 2 ); + if( !(operator = Macro_op(tok2)) || + (!strcmp(tok1, ".SETDIR") && + ((operator != M_OP_CL) || (operator != M_OP_PLCL) || + (operator != M_OP_DFCL))) ) { + CLEAR_TOKEN( &input ); + FREE( tok1 ); + DB_RETURN( 0 ); + } + + tok2 = Expand(tok1); FREE(tok1); tok1 = tok2; + tok2 = Get_token( &input, NIL( char ), FALSE ); + + 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 = _stradd( 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) ) + break; + /* else FALLTHRU */ + + case M_OP_EQ: + Def_macro( tok1, tok2, flag ); + break; + + case M_OP_DFCL: + if( (hv = GET_MACRO(tok1)) != NIL(HASH) ) + break; + /* else FALLTHRU */ + + case M_OP_CL: + /* If the macro we are assigning from is a single control + * macro with nothing else, then we propagate the M_MULTI + * flag to the macro we are assigning the value to so that + * the same macro can be used to do this over and over. */ + If_multi = 0; + tok2 = Expand( tok2 ); + Def_macro( tok1, tok2, M_EXPANDED | flag | If_multi ); + FREE( tok2 ); + break; + } + + FREE( 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" ); + + switch( *op ) { + case '=': ret = M_OP_EQ; break; + case ':': ret = M_OP_CL; op++; break; + + case '+': + ret = M_OP_PL; op++; + if( *op == ':' ) { ret = M_OP_PLCL; op++; } + break; + + case '*': + ret = M_OP_DF; op++; + if( *op == ':' ) { ret = M_OP_DFCL; op++; } + break; + } + + if( *op++ != '=' ) + ret = 0; + else if( *op != '\0' ) + ret = 0; + + DB_RETURN( ret ); +} + diff --git a/dmake/make.bat b/dmake/make.bat new file mode 100644 index 0000000..0d27f00 --- /dev/null +++ b/dmake/make.bat @@ -0,0 +1,165 @@ +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 making the Turbo C version. +rem + +if %0%1 == %0 goto error +if %1 == tcc goto mktcc +if %1 == tccswp goto mktccswp +if %1 == bcc goto mkbcc +if %1 == bccswp goto mkbccswp +if %1 == msc40 goto mkmsc40 +if %1 == msc40swp goto mkmsc40swp +if %1 == msc50 goto mkmsc50 +if %1 == msc50swp goto mkmsc50swp +if %1 == msc51 goto mkmsc51 +if %1 == msc51swp goto mkmsc51swp +if %1 == msc60 goto mkmsc60 +if %1 == msc60swp goto mkmsc60swp +if %1 == ztc goto mkztc +if %1 == ztcswp goto mkztcswp + +rem label the possible DOS variations for dmake here. +:error +echo MSDOS: You must specify 'make target' where target is one of: +echo ------------- +echo tcc - Turbo C 2.0 compile. +echo tccswp - Turbo C 2.0 compile of swapping dmake. +echo bcc - Borland C++ 2.0,3.0 compile. +echo bccswp - Borland C++ 2.0,3.0 compile of swapping dmake. +echo msc40 - Microsoft C 4.0 compile. +echo msc50 - Microsoft C 5.0 compile. +echo msc51 - Microsoft C 5.1 compile. +echo msc60 - Microsoft C 6.0 compile. +echo msc40swp - Microsoft C 4.0, MASM 5.1 compile of swapping dmake. +echo msc50swp - Microsoft C 5.0, MASM 5.1 compile of swapping dmake. +echo msc51swp - Microsoft C 5.1, MASM 5.1 compile of swapping dmake. +echo msc60swp - Microsoft C 6.0, MASM 5.1 compile of swapping dmake. +echo ztc - Zortech C++ 2.1 compile. +echo ztcswp - Zortech C++ 2.1 compile of swapping dmake. +goto end + +rem This is the script that makes dmake using Microsoft C 4.0 +:mkmsc40 +msdos\mscdos\mk40.bat +goto end + +:mkmsc40swp +msdos\mscdos\mk40swp.bat +goto end + +rem This is the script that makes dmake using Microsoft C 5.0 +:mkmsc50 +msdos\mscdos\mk50.bat +goto end + +:mkmsc50swp +msdos\mscdos\mk50swp.bat +goto end + +rem This is the script that makes dmake using Microsoft C 5.1 +:mkmsc51 +msdos\mscdos\mk51.bat +goto end + +:mkmsc51swp +msdos\mscdos\mk51swp.bat +goto end + +rem This is the script that makes dmake using Microsoft C 6.0 +:mkmsc60 +msdos\mscdos\mk60.bat +goto end + +:mkmsc60swp +msdos\mscdos\mk60swp.bat +goto end + +rem This is the script that makes dmake using Zortech C++ 2.1 +:mkztc +msdos\ztcdos\mk.bat +goto end + +:mkztcswp +msdos\ztcdos\mkswp.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\tccdos\obj.rsp +echo msdos\tccdos\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\tccdos\mk.bat +goto end + +:mktccswp +cls +echo WARNING: +echo The default response files: +echo msdos\tccdos\objswp.rsp +echo msdos\tccdos\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\tccdos\mkswp.bat +goto end + +rem This is the script that makes dmake using Turbo C++ 2.0. +:mkbcc +cls +echo WARNING: +echo The default response files: +echo msdos\bccdos\obj.rsp +echo msdos\bccdos\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\bccdos\mk.bat +goto end + +:mkbccswp +cls +echo WARNING: +echo The default response files: +echo msdos\bccdos\objswp.rsp +echo msdos\bccdos\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\bccdos\mkswp.bat +goto end + +rem All done! +:end diff --git a/dmake/make.c b/dmake/make.c new file mode 100644 index 0000000..f0733d4 --- /dev/null +++ b/dmake/make.c @@ -0,0 +1,1028 @@ +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/make.c,v 1.2 1992/04/07 04:42:46 dvadura 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 $< +-- {{ - expands to { +-- }} - expands to } +-- \# - expands to # +-- +-- 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. +-- +-- LOG +-- $Log: make.c,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Minor change to variable name to remove "redefined warning from compiler". + * + * Revision 1.1 1992/01/24 03:26:51 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +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 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 ]; + + +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 ); + + Root->ce_flag |= F_RULES|F_TARGET|F_STAT; + Root->ce_attr |= A_NOSTATE; + Root->ce_time = Do_time(); + TALLOC( Root->ce_recipe, 1, STRING ); + Root->ce_recipe->st_string = ""; + + for( lp = Root->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 = Root->ce_prq; lp != NIL(LINK); lp = lp->cl_next ) { + CELLPTR root = lp->cl_prq; + if( !(root->ce_attr & A_UPDATED) ) + printf( "`%s' is up to date\n", root->CE_NAME ); + } + + DB_RETURN( 0 ); +} + + + +int +Make( cp, setdirroot )/* +======================== Make a specified target */ +CELLPTR cp; +CELLPTR setdirroot; +{ + register LINKPTR dp; + register CELLPTR tcp; + CELLPTR nsetdirroot; + char *name, *lib; + HASHPTR m_at, m_q, m_b, m_g, m_l, m_bb, m_up; + 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()) ); + + m_q = m_b = m_g = m_l = m_bb = m_up = m_at = NIL(HASH); + + /* 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); + + 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)) ) + 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; + } + } + + tcp = cp; + do { + if( push ) { + if( tcp->ce_dir ) FREE( tcp->ce_dir ); + tcp->ce_dir = _pool_lookup(Pwd); + tcp->ce_attr |= A_SETDIR; + } + tcp->ce_setdir = nsetdirroot; + tcp = tcp->ce_all; + } + while( tcp != NIL(CELL) && tcp != cp ); + + 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; + Stat_target( cp, TRUE ); + + if( cp->ce_time == (time_t)0L ) { + if( cp->ce_flag & F_INFER ) + cp->ce_time = itime; + } + else + cp->ce_attr |= A_PRECIOUS; /* File exists so don't remove it later. */ + + if( Verbose & V_MAKE ) + printf("%s: Time stamp of [%s] is %ld\n",Pname,cp->CE_NAME, + cp->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)||(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)"; + + for( dp = cp->ce_prq; dp != NIL(LINK); dp = dp->cl_next ) { + int seq; + + /* 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. */ + + 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; + + if( strchr(tcp->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. */ + + m_at = Def_macro( "@", cp->ce_fname, M_MULTI ); + name = Expand( tcp->CE_NAME ); + if( strcmp(name,cp->CE_NAME) == 0 ) + Fatal( "Circular dynamic dependency generated '%s'", name ); + + tcp = dp->cl_prq = Def_cell( name ); + FREE( name ); + } + + 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 parents F_REMOVE and F_INFER attribute to children. + * Make certain you 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); + + 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 *) ); + if( mtime < tcp->ce_time ) tcp->ce_time = cp->ce_time+1L; + } + + if( tcp->ce_time > otime ) otime = tcp->ce_time; + + all = _strapp( all, name ); + if( tgflg = (dp->cl_flag & F_TARGET) ) inf = _strapp( inf, name ); + + if((cp->ce_timece_time) || ((tcp->ce_flag & F_TARGET) && Force)) { + outall = _strapp( outall, name ); + if( tgflg ) imm = _strapp( imm, name ); + } + } + + 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_EXPANDED ); + 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 ) + 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 ) + if( Do_touch( name, lib, + (cp->ce_attr & A_SYMBOL) ? &name : NIL(char *) ) != 0 ) + printf( " not touched - non-existant" ); + + 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 */ + tcp = cp; + do { + 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 *nname = Build_path(_prefix(dir,tcp->ce_dir), tcp->ce_fname); + + if( (tcp->ce_attr & A_FFNAME) && (tcp->ce_fname != NIL(char)) ) + FREE( tcp->ce_fname ); + + tcp->ce_fname = _strdup(nname); + tcp->ce_attr |= A_FFNAME; + } + + tcp = tcp->ce_all; + } + while( tcp != NIL(CELL) && tcp != cp ); + +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 ); + + while( push-- ) Pop_dir(FALSE); + + if( inf != NIL(char) ) FREE( inf ); + if( all != NIL(char) ) FREE( all ); + if( imm != NIL(char) ) FREE( imm ); + if( outall != NIL(char) ) FREE( outall ); + + DB_PRINT( "mem", ("%s:-< mem %ld", cp->CE_NAME, (long) coreleft()) ); + DB_RETURN( rval ); +} + + +static char * +_prefix( pfx, pat ) +char *pfx; +char *pat; +{ + char *opat = pat; + while( *pfx && *pat && *pfx++ == *pat++ ); + + return( !*pfx ? _strspn(pat,DirBrkStr) : opat ); +} + + +static LINKPTR +_dup_prq( lp ) +LINKPTR lp; +{ + LINKPTR tlp; + + if( lp == NIL(LINK) ) return(lp); + + TALLOC(tlp, 1, LINK); + *tlp = *lp; + tlp->cl_next = _dup_prq( lp->cl_next ); + + return(tlp); +} + + +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; +{ + /* 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( 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 ) { + if( parent == NIL(LINK) ) + Fatal( "Internal Error: NIL parent in Make()" ); + + TALLOC(parent->cl_prq, 1, CELL); + *parent->cl_prq = *cp; + cp = parent->cl_prq; + cp->ce_prq = _dup_prq(cp->ce_prq); + } + 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 ) { + char *ecmnd = cmnd; + cmnd = _strdup(_strspn(cmnd, " \t\n+-@%")); + FREE(ecmnd); + } + + /* 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 && *(p = _strpbrk(cmnd, " \t\n")) ) { + char *cname = cmnd; + + *p = '\0'; + (void) Def_macro("CMNDNAME",cname,M_MULTI|M_EXPANDED); + (void) Def_macro("CMNDARGS",p+1,M_MULTI|M_EXPANDED); + + cmnd = Expand("$(COMMAND)"); + FREE(cname); /* cname == cmnd at this point. */ + } + + Swap_on_exec = ((l_attr & A_SWAP) != 0); /* Swapping for DOS only */ + do_it = !Trace; + + if( !group && Trace && _strstr(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( *_strspn(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 ) { + if( attr & A_EPILOG ) /* emit epilog */ + _append_file( _recipes[RP_GPEPILOG], tmpfile, cp->CE_NAME, trace ); + + if( trace ) fputs("]\n", stdout); + + if( do_it = !Trace ) Close_temp( cp, tmpfile ); + rval = Do_cmnd(groupfile, TRUE, do_it, cp, (attr & A_IGNORE)!=0, + TRUE, TRUE); + } + + Wait_for_completion = FALSE; + _recipes[ RP_RECIPE ] = orp; + 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 = _strpbrk(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); + +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; + + DB_ENTER( "Push_dir" ); + + if( dir == NIL(char) || *dir == '\0' ) dir = Pwd; + if( *dir == '\'' && dir[strlen(dir)-1] == '\'' ) { + dir = _strdup(dir+1); + dir[strlen(dir)-1]='\0'; + } + else + dir = Expand(dir); + + if( Set_dir(dir) ) { + if( !ignore ) + Fatal( "Unable to change to directory `%s', target is [%s]", + dir, name ); + FREE(dir); + DB_RETURN( 0 ); + } + + DB_PRINT( "dir", ("Push: [%s]", dir) ); + if( Verbose & V_PRINT_DIR ) + printf( "%s: Changed to directory [%s]\n", Pname, dir ); + + FREE( dir ); + TALLOC( new_dir, 1, STRING ); + new_dir->st_next = dir_stack; + dir_stack = new_dir; + new_dir->st_string = _strdup( 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_PRINT_DIR ) + 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 = _strdup( "" ); + + 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 = _strdup( 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 = _strdup(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 100644 index 0000000..4b62bd4 --- /dev/null +++ b/dmake/make.cmd @@ -0,0 +1,53 @@ +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 +echo Running make.cmd script to make a %1 copy of dmake. + +if %0%1 == %0 goto error +if %1 == msc40 goto mkmsc40 +if %1 == msc50 goto mkmsc50 +if %1 == msc51 goto mkmsc51 +if %1 == msc60 goto mkmsc60 +if %1 == ibm goto mkibm + +rem label the possible DOS variations for dmake here. +:error +echo OS/2 INDEX: You must specify one of: +echo ------------------ +echo msc40 - Microsoft C 4.0 compile. +echo msc50 - Microsoft C 5.0 compile. +echo msc51 - Microsoft C 5.1 compile. +echo msc60 - Microsoft C 6.0 compile. +3cho ibm - IBM C 2.0 compile. +goto end + +rem This is the script that makes dmake using Microsoft C 4.0 +:mkmsc40 +os2\mscdos\mk40.cmd +goto end + +rem This is the script that makes dmake using Microsoft C 5.0 +:mkmsc50 +os2\mscdos\mk50.cmd +goto end + +rem This is the script that makes dmake using Microsoft C 5.1 +:mkmsc51 +os2\mscdos\mk51.cmd +goto end + +rem This is the script that makes dmake using Microsoft C 6.0 +:mkmsc60 +os2\mscdos\mk60.cmd +goto end + +rem This is the script that makes dmake using Microsoft C 6.0 +:ibm +os2\ibm\mkc2.cmd +goto end + +rem All done! +:end diff --git a/dmake/makefile b/dmake/makefile new file mode 100644 index 0000000..ad03ae5 --- /dev/null +++ b/dmake/makefile @@ -0,0 +1,73 @@ +# Default makefile for the various versions of dmake that we +# have available. This is a bootstrap version and uses /bin/sh to +# execute a script which compiles dmake. +# +# Note the DOS commands actually invoke command.com to run the .bat file +# to make the script. + +all : + @-echo ""; clear; exit 0 + @echo "INDEX: You must specify 'make target' where target is one of:" + @echo "-------------" + @echo " make bsd43 - Generic BSD 4.3 System" + @echo " make bsd43uw - Generic BSD 4.3 at U of Waterloo" + @echo " make bsd43vf - Generic BSD 4.3 that needs vfprintf" + @echo " make sysvr4 - Generic SysV R4 UNIX System" + @echo " make sysvr3 - Generic SysV R3 UNIX System" + @echo " make sysvr3pwd - Generic SysV R3 UNIX System, our PWD, (Any HP System)" + @echo " make sysvr1 - Generic SysV R1 UNIX System" + @echo " make dynix - Sequent DYNIX System" + @echo " make ultrix - Ultrix 3.0 System" + @echo " make mips - Any MIPS System" + @echo " make coherent - Any Coherent System" + @echo " make 386ix - 386/ix (SysV R3) System" + @echo " make xenix - 386 Xenix System" + @echo " make xenixpwd - 386 Xenix System, our PWD" + @echo " make aix - IBM RS6000/AIX System" + @echo " make os2msc40 - OS/2 using MSC 4.0 compiler" + @echo " make os2msc50 - OS/2 using MSC 5.0 compiler" + @echo " make os2msc51 - OS/2 using MSC 5.1 compiler" + @echo " make os2msc60 - OS/2 using MSC 6.0 compiler" + @echo " make os2ibm - OS/2 using IBM C 2.0 compiler" + @echo " make tos - Atari-ST TOS using GCC as compiler" + @echo " make tcc - DOS with Turbo C 2.0" + @echo " make bcc - DOS with Borland C++ 3.0" + @echo " make tccswp - swapping DOS version with Turbo C 2.0" + @echo " make bccswp - swapping DOS version with Borland C++ 3.0" + @echo " make msc40 - DOS with MSC 4.0" + @echo " make msc50 - DOS with MSC 5.0" + @echo " make msc51 - DOS with MSC 5.1" + @echo " make msc60 - DOS with MSC 6.0" + @echo " make msc40swp - swapping DOS version with MSC 4.0" + @echo " make msc50swp - swapping DOS version with MSC 5.0" + @echo " make msc51swp - swapping DOS version with MSC 5.1" + @echo " make msc60swp - swapping DOS version with MSC 6.0" + @echo " make ztc - DOS with Zortech C++ 2.1" + @echo " make ztcswp - swapping DOS version with Zortech C++ 2.1" + @echo " make mpwmac - Macintosh under MPW" + +ultrix aix: sysvr3; + +sysvr1 sysvr3 sysvr4 bsd43 386ix :; /bin/sh -x < unix/$@/make.sh + +bsd43uw :; /bin/sh -x < unix/bsd43/uw/make.sh +bsd43vf dynix mips :; /bin/sh -x < unix/bsd43/vf/make.sh +coherent :; /bin/sh -x < unix/coherent/make.sh +xenix :; /bin/sh -x < unix/xenix/make.sh +xenixpwd :; /bin/sh -x < unix/xenix/pwd/make.sh +sysvr3pwd :; /bin/sh -x < unix/sysvr3/pwd/make.sh +tos :; sh -x tos/make.sh +mpwmac :; :mac:make.sh + +# Various OS/2 targets. +OS2_VER = os2msc40 os2msc50 os2msc51 os2msc60 os2ibm +$(OS2_VER) :; make.cmd $(@:s/os2//) + +# DOS with some form of make and sh +# Note if you do not have a 'make and/or sh' program under MSDOS then +# typing 'make' in the dmake distribution directory will invoke the make.bat +# batch file which will issue the appropriate instructions. +DOS_VER = tcc msc40 msc50 msc51 msc60 \ + tccswp msc40swp msc50swp msc51swp msc60swp \ + bcc bccswp ztc ztcswp +$(DOS_VER) :; make.bat $@ diff --git a/dmake/makefile.mk b/dmake/makefile.mk new file mode 100644 index 0000000..70a2a0b --- /dev/null +++ b/dmake/makefile.mk @@ -0,0 +1,342 @@ +# //// 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 gives the particular release of the OS above. +# OSENVIRONMENT - optionally gives the environment under which the above +# OS is in use. +# +# 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 + +# Pull in the configuration macros, from the environment. OS is required, +# OSRELEASE, and OSENVIRONMENT are optional. +.IF $(OS) == $(NULL) + .IMPORT : OS +.END +.IMPORT .IGNORE : OSRELEASE OSENVIRONMENT TMPDIR + +# Define $(PUBLIC) +_osenv := $(OSENVIRONMENT)$(DIRSEPSTR) +_osre := $(OSRELEASE)$(DIRSEPSTR)$(!null,$(OSENVIRONMENT) $(_osenv)) +ENVDIR = $(OS)$(DIRSEPSTR)$(!null,$(OSRELEASE) $(_osre)) +PUBLIC = $(ENVDIR)public.h +STARTUP := startup.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\ + basename.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 += -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) -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) $(STARTUP); +$(TARGET) : $(OBJDIR) +$(TARGET) : $(OBJECTS);$(LD) $(LDARGS) +.IF $(SHELL) == mpw +$(STARTUP) : $(ENVDIR)$(STARTUP); duplicate :$(<:s,/,:,) $@ +.ELSE +$(STARTUP) : $(ENVDIR)$(STARTUP); $(eq,$(SHELL),$(COMSPEC) +copy cp) $< $@ +.ENDIF + +# how to make public.h +public .PHONY : $(PUBLIC); +$(PUBLIC) .SHELL .NOSTATE: $(SRC) + genpub -n DMAKE $< >$@ + rcsclean $@ > /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 : $(OS)/sysintf.h +ruletab$O : $(OS)/startup.h #khc 01NOV90 - dependency was missing +$(OBJECTS) : $(HDR) + +clean:;+- $(RM) -rf dmake$E dbdmake$E objects* $(STARTUP) _*state*.mk + +# Rules for making the manual pages. +man .SETDIR=man : dmake.nc dmake.uue ; +dmake.nc : dmake.p ; scriptfix < $< > $@ +dmake.p : dmake.tf; typeset -man -Tdumb $< > $@ +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 + +#-------------------------------------------------------------------------- +# Make the various archives for shipping the thing around. +# +archives : zoo tar shar; + +zoo .PHONY : dmake.zoo ; +shar .PHONY : dmake.shar; +tar .PHONY : dmake.tar; + +dmake.zoo : dir-copy +[ + find dmake -type f -print | zoo aI $@ + $(RM) -rf src-list dmake +] + +dmake.shar : dir-copy +[ + find dmake -type f -print >src-list + xshar -vc -o$@ -L40 `cat src-list` + $(RM) -rf src-list dmake +] + +dmake.tar : dir-copy +[ + tar cf $@ dmake + $(RM) -rf src-list 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 man + echo 'ALLSRC = \' >$@ + find . -type f -print |\ + sed -e 's/RCS\///' -e 's/,v//' -e 's/$$/\\/' -e 's/^\.\// /'|\ + sort -u |\ + grep -v tst | grep -v $@ | grep -v LICENSE |\ + grep -v '\.zoo' | grep -v '\.tar'| grep -v '\.shar' >> $@ + echo ' LICENSE' >> $@ + +#-------------------------------------------------------------------------- +# 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. +# +SH_n = $(@:s/swp-/-/:s,-,/,:s/scripts/${SCRIPTFILE}/) +MS_n = MAKESTARTUP=$(@:s/swp-/-/:s,-,/,:s/scripts/startup.mk/) +SH = $(SH_n:s/c40d/cd/:s/c50d/cd/:s/c51d/cd/:s/c60d/cd/:s/ibmc2/ibm/) +MS = $(MS_n:s/c40d/cd/:s/c50d/cd/:s/c51d/cd/:s/c60d/cd/:s/ibmc2/ibm/) +FIX-SH = $(SH:s,fix/,,) + +scripts: unix-scripts atari-tos-scripts msdos-scripts os2-scripts\ + apple-mac-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-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-scripts-flags= OS=unix OSRELEASE=coherent OSENVIRONMENT= +unix-gno-scripts-flags = OS=unix OSRELEASE=gno 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-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-scripts + $(MAKE) SCRIPTFILE=make.sh unix-gno-scripts + +unix-%-scripts .SWAP : + $(MAKECMD) -s $($@-flags) .KEEP_STATE:= public + $(MAKECMD) -ns .KEEP_STATE:= $(MS) $($@-flags) >/tmp/dmscr + dfold $(SH) + +tos-%-scripts .SWAP : + $(MAKECMD) -s $($@-flags) .KEEP_STATE:= public + $(MAKECMD) -ns .KEEP_STATE:= $(MS) $($@-flags) >/tmp/dmscr + dfold $(SH) + +atari-tos-scripts .SWAP : clean + $(MAKE) SCRIPTFILE=make.sh tos--scripts + +apple-mac-scripts .SWAP : clean + $(MAKE) SCRIPTFILE=make.sh mac--scripts + +mac-%-scripts .SWAP : + $(MAKECMD) -s $($@-flags) .KEEP_STATE:= public + $(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 OSENVIRONMENT= +msdos-tccdos-scripts-flags = $(msdos-cf) OSRELEASE=tccdos SWAP=n +msdos-tccdosswp-scripts-flags = $(msdos-cf) OSRELEASE=tccdos +msdos-bccdos-scripts-flags = $(msdos-cf) OSRELEASE=bccdos SWAP=n +msdos-bccdosswp-scripts-flags = $(msdos-cf) OSRELEASE=bccdos +msdos-msc40dos-scripts-flags= $(msdos-cf) OSRELEASE=mscdos SWAP=n MSC_VER=4.0 +msdos-msc40dosswp-scripts-flags = $(msdos-cf) OSRELEASE=mscdos MSC_VER=4.0 +msdos-msc50dos-scripts-flags= $(msdos-cf) OSRELEASE=mscdos SWAP=n MSC_VER=5.0 +msdos-msc50dosswp-scripts-flags = $(msdos-cf) OSRELEASE=mscdos MSC_VER=5.0 +msdos-msc51dos-scripts-flags= $(msdos-cf) OSRELEASE=mscdos SWAP=n MSC_VER=5.1 +msdos-msc51dosswp-scripts-flags = $(msdos-cf) OSRELEASE=mscdos MSC_VER=5.1 +msdos-msc60dos-scripts-flags= $(msdos-cf) OSRELEASE=mscdos SWAP=n MSC_VER=6.0 +msdos-msc60dosswp-scripts-flags = $(msdos-cf) OSRELEASE=mscdos MSC_VER=6.0 +msdos-ztcdos-scripts-flags= $(msdos-cf) OSRELEASE=ztcdos SWAP=n +msdos-ztcdosswp-scripts-flags= $(msdos-cf) OSRELEASE=ztcdos + +msdos-scripts: clean\ + msdos-tcc-scripts msdos-bcc-scripts\ + msdos-msc-scripts msdos-ztc-scripts; + +msdos-tcc-scripts .SWAP : + $(MAKE) SCRIPTFILE=mk.bat msdos-tccdos-scripts + $(MAKE) SCRIPTFILE=mkswp.bat msdos-tccdosswp-scripts + +msdos-bcc-scripts .SWAP : + $(MAKE) SCRIPTFILE=mk.bat msdos-bccdos-scripts + $(MAKE) SCRIPTFILE=mkswp.bat msdos-bccdosswp-scripts + +msdos-msc-scripts .SWAP :! 40 50 51 60 + $(MAKE) SCRIPTFILE=mk$?.bat msdos-msc$?dos-scripts + $(MAKE) SCRIPTFILE=mk$?swp.bat msdos-msc$?dosswp-scripts + +msdos-ztc-scripts .SWAP : + $(MAKE) SCRIPTFILE=mk.bat msdos-ztcdos-scripts + $(MAKE) SCRIPTFILE=mkswp.bat msdos-ztcdosswp-scripts + +msdos-%-scripts .SWAP .SILENT: + $(MAKE) -s $($@-flags) .KEEP_STATE:= public + $(MAKE) -ns SHELL=command.com COMSPEC=command.com .KEEP_STATE:= $(MS) $($@-flags) >$(SH) + $(MAKE) -s $(MAKEMACROS) $(MS) $($@-flags) fix-msdos-$*-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 OSENVIRONMENT= +os2-msc40dos-scripts-flags= $(os2-cf) OSRELEASE=mscdos SWAP=n MSC_VER=4.0 +os2-msc50dos-scripts-flags= $(os2-cf) OSRELEASE=mscdos SWAP=n MSC_VER=5.0 +os2-msc51dos-scripts-flags= $(os2-cf) OSRELEASE=mscdos SWAP=n MSC_VER=5.1 +os2-msc60dos-scripts-flags= $(os2-cf) OSRELEASE=mscdos SWAP=n MSC_VER=6.0 +os2-ibmc2-scripts-flags= $(os2-cf) OSRELEASE=ibm SWAP=n MSC_VER=5.1 + +os2-scripts: clean os2-msc-scripts os2-ibm-scripts; + +os2-msc-scripts .SWAP :! 40 50 51 60 + $(MAKE) SCRIPTFILE=mk$?.cmd os2-msc$?dos-scripts + +os2-ibm-scripts .SWAP :! c2 + $(MAKE) SCRIPTFILE=mk$?.cmd os2-ibm$?-scripts + +os2-%-scripts .SWAP : + $(MAKE) -s $($@-flags) .KEEP_STATE:= public + $(MAKE) -ns SHELL=cmd.exe COMSPEC=cmd.exe .KEEP_STATE:= $(MS) $($@-flags) >$(SH) + $(MAKE) -s $(MAKEMACROS) $(MS) $($@-flags) fix-os2-$*-scripts + +# Signify NULL targets for the various MSC compiler versions. +c2 40 50 51 60:; + +# 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},) +DOSOBJ = $(CSTARTUP) $(OBJDIR)/{$(OBJECTS)} +fix-%-scripts: + tail -r $(FIX-SH) >tmp-sh-r + tail +3 tmp-sh-r | sed -e 's,/,\\,g' >tmp-out + tail -r tmp-out >$(FIX-SH) + head -2 tmp-sh-r |\ + sed -e 's,\\usr\\tmp\\mkA[a-zA-Z]*[0-9]*,$(OBJRSP),'\ + -e 's,\\usr\\tmp\\mkB[a-zA-Z]*[0-9]*,$(LIBRSP),' |\ + sed -e 's,$(OS)/,$(OS)\\,g'\ + -e 's,$(OS)/$(OSRELEASE)/,$(OS)\\$(OSRELEASE)\\,g'\ + -e 's,$(OS)\\$(OSRELEASE)/,$(OS)\\$(OSRELEASE)\\,g'\ + -e 's,$(OS)/$(OSRELEASE)\\,$(OS)\\$(OSRELEASE)\\,g' >>$(FIX-SH) + rm -f tmp-sh-r tmp-out + mv <+$(DOSOBJ:s,/,\\,:t"+\n")\n+> $(OBJRSP) + mv <+$(LDLIBS:s,/,\\,:t"+\n")\n+> $(LIBRSP) diff --git a/dmake/man/README b/dmake/man/README new file mode 100644 index 0000000..27a056b --- /dev/null +++ b/dmake/man/README @@ -0,0 +1,9 @@ +To unpack the DMAKE 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. diff --git a/dmake/man/dmake.nc b/dmake/man/dmake.nc new file mode 100644 index 0000000..6b4e45c --- /dev/null +++ b/dmake/man/dmake.nc @@ -0,0 +1,3200 @@ + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + +NAME + dmake - maintain program groups, or interdependent files + +SYNOPSIS + dmake [-ABceEhiknpqrsStTuVxX] [-v{dfimt}] [-P#] [-{f|C|K} + file] [macro[*][+][:]=value ...] [target ...] + +DESCRIPTION + 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 prerequisites is newer than the target or if + the target itself does not exist, then dmake will attempt to + make the target. + + If no -f command line option is present then dmake searches + for an existing makefile from the list of prerequisites + 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 standard 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 + supersede definitions for macros of the same name found + within the makefile. In general it is impossible for defin- + itions found inside the makefile to redefine a macro defined + on the command line, see the MACROS section for an excep- + tion. + + If no target names are specified on the command line, then + dmake uses the first non-special target found in the + makefile as the default target. See the SPECIAL TARGETS + section for the list of special targets and their function. + dmake is a re-implementation of the UNIX Make utility with + significant enhancements. Makefiles written for most previ- + ous versions of Make will be handled correctly by dmake. + Known differences between dmake and other versions of make + are discussed in the COMPATIBILITY section found at the end + of this document. + +OPTIONS + -A Enable AUGMAKE special inference rule transformations + (see the "PERCENT(%) RULES" section), these are set to + off by default. + + -B Enable the use of spaces instead of to begin + recipe lines. This flag equivalent to the .NOTABS spe- + cial macro and is further described below. + + -c Use non-standard comment stripping. If you specify -c + then dmake will treat any # character as a start of + + + +Version 3.8 PL1 UW 1 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + comment character wherever it may appear unless it is + escaped by a \. + + -C [+]file + This option writes to file a copy of standard output + 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 ver- + sions of dmake. + + -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 definitions in the makefile + to override definitions in the environment. + + -e Same as -E, except that the environment is processed + after the user specified makefile has been processed + (thus definitions in the environment override defini- + tions 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. + + -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 execu- + tion and to make all targets not depending on targets + that could not be made. Ordinarily dmake 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 executed, + but does not actually execute the commands. A special + check is made for the string "$(MAKE)" inside a recipe + line, if found, the line is expanded and invoked, + thereby enabling recursive makes to give a full + + + +Version 3.8 PL1 UW 2 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + description of all that they will do. The check for + "$(MAKE)" 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 makefile, + 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 attri- + bute or macro. + + -S Force sequential execution of recipes on architectures + which support concurrent makes. For backward compati- + bility 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[dfimt] + 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 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: + + d Notify of change directory operations only. + + f Notify of file I/O operations only. + + + + + +Version 3.8 PL1 UW 3 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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. + + -V Print the version of dmake, and values of builtin mac- + ros. + + -x 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. + + -X Inhibit the execution of #! lines found at the begin- + ning of a makefile. The use of this flag prevents + non-termination of recursive make invocations. + +INDEX + Here is a list of the sections that follow and a short + description of each. Perhaps you won't have to read the + whole man page to find what you need. + + STARTUP Describes dmake initialization. + + SYNTAX Describes the syntax of makefile expres- + sions. + + ATTRIBUTES Describes the notion of attributes and + how they are used when making targets. + + MACROS Defining and expanding macros. + + RULES AND TARGETS How to define targets and their prere- + quisites. + + 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. + + RUN-TIME MACROS Discussion of special run-time macros + such as $@ and $<. + + + +Version 3.8 PL1 UW 4 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + FUNCTION MACROS GNU style function macros, only $(mktmp + ...) for now. + + DYNAMIC PREREQUISITES + Processing of prerequisites which contain + macro expansions in their name. + + BINDING TARGETS The rules that dmake uses to bind a tar- + get to an existing file in the file sys- + tem. + + PERCENT(%) RULES Specification of recipes to be used by + the inference algorithm. + + MAKING INFERENCES The rules that dmake uses when inferring + how to make a target which has no expli- + cit recipe. This and the previous sec- + tion 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 + facilities for architectures that support + them. + + CONDITIONALS Conditional expressions which control the + processing of the makefile. + + EXAMPLES Some hopefully useful examples. + + COMPATIBILITY How dmake compares with previous versions + 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. + + + + + +Version 3.8 PL1 UW 5 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + +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 sup- + plied 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 MAK- + ESTARTUP defined on the command line. + + 2. The location given as the value of the environment + variable MAKESTARTUP defined in the current + environment. + + 3. The location given as the value of the macro MAK- + ESTARTUP 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 specified. A user + may substitute a custom startup file by defining the MAKES- + TARTUP 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". + + 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: + + #! command command_args + + then dmake will expand and run the command prior to reading + any addtional input. If the return code of the command is + zero then dmake will continue on to process the remainder of + the user makefile, if the return code is non-zero then dmake + + + +Version 3.8 PL1 UW 6 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + will exit. + +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. Alternative pro- + ductions 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 + -> Rule-Definition + -> Attribute-Definition + + Macro-Definition -> MACRO = LINE + -> MACRO *= LINE + -> MACRO := LINE + -> MACRO *:= LINE + -> MACRO += LINE + -> MACRO +:= LINE + + 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 + + + + + +Version 3.8 PL1 UW 7 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + attrs -> attribute { attrs } + -> "attribute" { attrs } + + op -> : { modifier } + + modifier -> : + -> ^ + -> ! + -> - + + recipe -> { TAB rcp-line } + -> [@][%][-] [ + { LINE } + ] + + rcp-line -> [@][%][-][+] LINE + + + Attribute-Definition -> attrs : targets + + + attribute -> .EPILOG + -> .IGNORE + -> .LIBRARY + -> .MKSARGS + -> .NOINFER + -> .NOSTATE + -> .PHONY + -> .PRECIOUS + -> .PROLOG + -> .SETDIR=path + -> .SILENT + -> .SEQUENTIAL + -> .SWAP + -> .USESHELL + -> .SYMBOL + -> .UPDATEALL + + special-target -> .ERROR + -> .EXPORT + -> .GROUPEPILOG + -> .GROUPPROLOG + -> .IMPORT + -> .INCLUDE + -> .INCLUDEDIRS + -> .MAKEFILES + -> .REMOVE + -> .SOURCE + -> .SOURCE.suffix + -> .suffix1.suffix2 + + + + + +Version 3.8 PL1 UW 8 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + Where, TAB represents a character, STRING represents + 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 + 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 expres- + sion. A LINE can be continued over several physical lines + by terminating it with a single backslash character. Com- + ments 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 exception to + this occurs when a # is seen inside a recipe line that + begins with a 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 single # + 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 , + , and the sequence \ when \ is used to ter- + minate a LINE. When processing macro definition lines, any + amount of white space is allowed on either side of the macro + operator (=, *=, :=, *:=, += or +:=), and white space is + stripped from both before and after the macro value string. + The sequence \ is treated as white space during recipe + expansion and is deleted from the final recipe string. You + must escape the \ with another \ in order to get a \ at + the end of a recipe line. The \ 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 target 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 example: + + a:fred : test + + would be parsed as TARGET = a, PREREQUISITES={fred, :, + + + +Version 3.8 PL1 UW 9 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + test}, which is not what was intended. To fix this you must + write: + + "a:fred" : test + + Which will be parsed as expected. Quoted target and prere- + quisite specifications may also contain white space thereby + allowing the use of complex function macro expressions.. + See the EXAMPLES section for how to apply " quoting 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 modify + dmake actions during target update. The recognized attri- + butes are: + + + .EPILOG Insert shell epilog code when executing a group + recipe associated with any target having this + attribute set. + + .IGNORE Ignore an error when trying to make any target + with this attribute set. + + .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 environments + 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. + (i.e. the inference algorithm will not use any + prerequisite with this attribute set, as a tar- + get) 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 attri- + buted target as a prerequisite will be made each + + + +Version 3.8 PL1 UW 10 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 sys- + tem 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 + target'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 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. + + .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 automatically. + + .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. + + + + + +Version 3.8 PL1 UW 11 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + .UPDATEALL Indicates that all the targets listed in this + rule are updated by the execution of the accom- + panying recipe. A common example is the produc- + tion 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. + + + 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 attri- + bute, 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 com- + mon Make construct of ".IGNORE :" but has been modified to + the notion of an attribute instead of a special target). + Not all of the attributes have global meaning. In particu- + lar, .LIBRARY, .NOSTATE, .PHONY, .SETDIR, .SYMBOL 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 types of macro assignment. + + + MACRO = LINE 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. + + + + + +Version 3.8 PL1 UW 12 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 expansions + 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 expansion + 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 previous value + of MACRO separating the two by a single + space. Future expansions of MACRO recur- + sively 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 the + macro is defined using the '+=' and '+:=' operators. Other + operators will define a macro that cannot be further modi- + fied. + + When dmake 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 -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, environment 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) + 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 + + + +Version 3.8 PL1 UW 13 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 represent- + ing a macro expansion, the expansion is performed. 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 mac- + ros. 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 attri- + buted targets and a collection of small distributed makefile + stubs. + + 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 { D or d, F or f, + B or b, S or s, T or t } and + + d - directory portion of all path names + f - file (including suffix) portion of path names + b - file (not including suffix) portion of path names + s - simple pattern substitution + t - tokenization. + + 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 + + + +Version 3.8 PL1 UW 14 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + $(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 + + 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 modif- + iers 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 fol- + lowing escape codes \a => , \b => , \f => + , \n => , \r => , \t => , \v => + , \" => ", and \xxx => where xxx is the + octal representation of a character. Thus the expansion: + + $(test:f:t"+\n") + produces: + a.out+ + f.out+ + k.out + + The second 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: + + + + +Version 3.8 PL1 UW 15 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + string1{token_list}string2 + + 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 del- + imited 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 charac- + ters of token_list appear immediately after the opening '{' + with no intervening white space. The reason for this res- + triction 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 expan- + sion while the former causes it to be suppressed. See the + SPECIAL MACROS section for a description of the special mac- + ros that dmake defines and understands. + +RULES AND TARGETS + A makefile contains a series of entries that specify depen- + dencies. Such entries are called target/prerequisite or + rule definitions. Each rule definition is optionally fol- + lowed 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 is a non-empty list of targets. If the target is a + special target (see SPECIAL TARGETS section below) then it + + + +Version 3.8 PL1 UW 16 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 + 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 targets + 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 separated 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 prere- + quisites 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 prerequisites. + + - 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 + + + +Version 3.8 PL1 UW 17 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + an example. + + : 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. How- + ever, if a target is multiply defined only one defini- + tion may specify a recipe for making the target. + + 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 dif- + ferent 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. + + 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 invocation corresponds to the + order in which the rule definitions appear in the + makefile. + + 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 tar- + get 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 defini- + tions has a recipe attached, then: + + joe : fred ... (1) + + + +Version 3.8 PL1 UW 18 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 exist- + ing 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 target. + + 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 message 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 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 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 '+' + + + +Version 3.8 PL1 UW 19 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 signi- + ficant, 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 independently of the 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 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 dmake invokes recipes. Here is an example of a group + recipe: + + target : + [ + first recipe line + second recipe line + all of these recipe lines are fed to a + single copy of a shell for execution. + ] + + +TEXT DIVERSIONS + dmake supports the notion of text diversions. If a recipe + line contains the macro expression + + $(mktmp[,[file][,text]] data) + + + +Version 3.8 PL1 UW 20 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 restric- + tion on the data text is that it must contain a balanced + number of parentheses of the same kind as are used to ini- + tiate the $(mktmp ...) expression. For example: + + $(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 containing + the text diversion expression is expanded, diversions may + now 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 multi- + ple lines in the makefile then each line must be continued + via the use of a \. A second more illustrative example gen- + erates a response file to an MSDOS link command: + + OBJ = fred.obj mary.obj joe.obj + all : $(OBJ) + link @$(mktmp $(^:t"+\n")\n) + + The result of making `all' in the second example is the com- + mand: + + + + +Version 3.8 PL1 UW 21 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 create. 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 how- + ever 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 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. + + Previous versions of dmake defined text diversions using <+, + +> strings, where <+ started a text diversion and +> ter- + minated one. dmake is backward compatible with this con- + struct if the <+ and +> appear literally on the same recipe + line or in the same macro value string. In such instances + the expression: + + <+data+> + + is mapped to: + + + +Version 3.8 PL1 UW 22 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + $(mktmp data) + + which is fully output compatible with the earlier construct. + <+, +> constructs whose text spans multiple lines must be + converted by hand to use $(mktmp ...). + + If the environment variable TMPDIR is defined then the tem- + porary 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. + +SPECIAL TARGETS + This section describes the special targets that are recog- + nized by dmake. Some are affected by attributes and others + are not. + + .ERROR If defined then the recipe associated with + this target is executed whenever an error con- + dition 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. + + .EXPORT 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 + + .IMPORT 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 .EVERY- + THING is used as a prerequisite name then all + environment variables defined in the environ- + ment are imported. The functionality of the + -E flag can be forced by placing 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 + + + +Version 3.8 PL1 UW 23 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 MAC- + ROS section for a description of the process- + ing 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 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 try- + ing 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 for the .INCLU- + DEDIRS special target. If the file name is + surrounded by < and >, (ie. + ) 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 start- + ing at the root of the file system then it is + only searched for once, and the .INCLUDEDIRS + list is ignored. .INCLUDE accepts the .IGNORE + and .SETDIR attributes. If .IGNORE attribute + is given and the file cannot be found then + dmake continues processing, otherwise an error + message is generated. The .SETDIR attribute + causes dmake to change directories to the + specified directory prior to attempting the + include operation. + + .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 makefile. By + default this target is defined as: + + + + +Version 3.8 PL1 UW 24 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + .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 try- + ing to locate a file matching the a target + 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 applica- + tion of transitive closure on the dependency + graph. + + 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. + +SPECIAL MACROS + 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 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. + + DIRBRKSTR Contains the string of chars used to terminate + the name of a directory in a pathname. Under + + + +Version 3.8 PL1 UW 25 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + UNIX its value is "/", under MSDOS its value + is "/\:". + + 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 char- + acter. 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 makefile + that was first read. + + MAKEFLAGS Is the same as $(MFLAGS) but has no leading + switch character. (ie. MFLAGS = -$(MAKEFLAGS)) + + MAKEMACROS Contains the complete list of macro expres- + sions 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. + + MAXPROCESSLIMIT + Is a numeric string representing the maximum + 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 + + + +Version 3.8 PL1 UW 26 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + .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 '+' direc- + tives, its value is "no" otherwise. + + + The second group of string valued macros control dmake + behavior and may be set by the user. + + .NOTABS When set to non-NULL enables the use of + spaces as well as 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 character. Enabling this mode modi- + fies the first condition of the above termi- + nation 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 []. + + .SETDIR If this macro is assigned a value then dmake + will change to the directory given by that + value before making any targets. + + AUGMAKE If set to a non NULL value will enable the + transformation of special meta targets to + support special AUGMAKE inferences (See the + COMPATIBILITY section). + + DIRSEPSTR Contains the string that is used to separate + 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 diver- + sion file name when used in $(mktmp ...) + expansions, see the TEXT DIVERSION section + for details. + + .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 + + + +Version 3.8 PL1 UW 27 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + list of flags with a leading switch indica- + tor. (ie. `-' under UNIX) + + GROUPSHELL This macro defines the full path to the exe- + cutable 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. + + 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 GROUPSUFFIX and + GROUPSHELL is done automatically for + command.com in the startup.mk files. + + MAKE Is defined in the startup file by default. + The string $(MAKE) is recognized when using + the -n option for single line recipes. Ini- + tially this macro is defined to have the + value "$(MAKECMD) $(MFLAGS)". + + MAKESTARTUP This macro defines the full path to the ini- + tial startup makefile. Use the -V command + 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 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. + + MAXPROCESS 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 MAX- + PROCESS on the command line or in the + + + +Version 3.8 PL1 UW 28 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + makefile is equivalent to supplying a + corresponding value to the -P flag on the + command line. + + PREP This macro defines the number of iterations + 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 exe- + cutable 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 sin- + gle 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 exe- + cuted 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 inter- + nally 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 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. + + + + + +Version 3.8 PL1 UW 29 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + All boolean macros currently understood by 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: .EPILOG, .IGNORE, .MKSARGS, .NOINFER, .PRECIOUS, .PRO- + LOG, .SEQUENTIAL, .SILENT, .SWAP, and .USESHELL. Assigning + any of these a non NULL value will globally set the + corresponding attribute to on. + +RUN_TIME 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 prerequisites, $> + is the name of the library if the current target is a + library member, and $< is the list of prerequisites speci- + fied in the current rule. If the current target had a + recipe inferred then $< is the name of the inferred prere- + quisite even if the target had a list of prerequisites sup- + plied using an explicit rule that did not provide a recipe. + In such situations $& gives the full list of prerequisites. + + $* is defined as $(@:db) 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 $* is the target name with no suffix, and in the second + case, is the value of the matched % pattern from the associ- + ated %-rule. $^ expands to the set of out of date prere- + quisites 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: + + + + +Version 3.8 PL1 UW 30 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + $@ --> fred.out + $* --> fred + $? --> joe amy my.c # note the difference between $? and $^ + $^ --> joe amy + $< --> joe amy hello + $& --> joe amy hello my.c your.h his.h her.h + + +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. + + + $(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 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. + + $(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 + + $(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) + + + + +Version 3.8 PL1 UW 31 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + will run the command using the current shell. + + $(sort list) + Will take all white-space separated tokens in list + and will return their sorted equivalent 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: + + $(OBJECTS:s/.o/.c/) + + +DYNAMIC PREREQUISITES + 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: + + fred : $$@.c + + causes the $$@ to be expanded when dmake is making fred, and + it resolves to the target fred. This enables dynamic prere- + quisites to be generated. The value of @ may be modified by + any of the valid macro modifiers. So you can say for exam- + ple: + + 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 ini- + tially 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. + +BINDING TARGETS + This operation takes a target name and binds it to an exist- + ing file, if possible. 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 + + + +Version 3.8 PL1 UW 32 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + internal name and its external file name to differ. To per- + form 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 opera- + tion 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 tar- + get 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. + ( is the suffix). If the special target + exists then search each directory given in the + .SOURCE. prerequisite list for the target. + If the target'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 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). (a + default target of '.SOURCE : .NULL' is defined by + dmake at startup, and is user redefinable) + + 3. The search in step 2. failed. Repeat the same + search but this time use the special target + .SOURCE. + + 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.). + + 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 dmake assigns the first + + + +Version 3.8 PL1 UW 33 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 prerequisite files have been modi- + fied as a result of the fix. + + When defining .SOURCE and .SOURCE.x targets the construct + + .SOURCE : + .SOURCE : fred gery + + is equivalent to + + .SOURCE :- fred gery + + dmake correctly handles the UNIX Make variable VPATH. By + definition VPATH contains a list of ':' separated direc- + tories to search when looking for a target. dmake maps + VPATH to the following special rule: + + .SOURCE :^ $(VPATH:s/:/ /) + + 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 prerequisites + (if any) must exist and the target must have a recipe which + dmake can use to make it. If the makefile 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 targets of the form + .. and by using the .SUFFIXES list of suf- + fixes. The exact workings of this mechanism were sometimes + difficult to understand and often limiting in their useful- + ness. Instead, dmake supports the concept of %-meta rules. + The syntax and semantics of these rules differ from standard + + + +Version 3.8 PL1 UW 34 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + rule lines as follows: + + <%-target> [] [<%-prerequisites>] [;] + + 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, %-prere- + quisites , 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 pat- + tern. 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 correspond- + ing 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. + + %.c : %.y yaccsrc/%.y ; recipe... + + is a short form for the construct: + + %.c : %.y ; recipe... + %.c : yaccsrc/%.y ; recipe... + + + + +Version 3.8 PL1 UW 35 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + ie. It is possible to specify the same recipe for two + %-rules by giving more than one prerequisite in the prere- + quisite 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 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 + dmake would generate the dependency 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 target + that has no suffix can be made from a prerequisite that has + at least one suffix. + + dmake supports dynamic prerequisite generation for prere- + quisites 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 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 rule + is the following: + + % : $$(@:d)RCS/$$(@:f),v : co $@ + + This rule uses the dynamic macro $@ to specify the prere- + quisite to try to infer. During inference of this rule the + + + +Version 3.8 PL1 UW 36 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 previous + 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 single + quotes. For example, if you had the explicit dependency: + + 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' ; rule to make 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 + %.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 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 + + + +Version 3.8 PL1 UW 37 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 corresponding path in the inference graph is + rejected. + + dmake also supports the old format special target + .. 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 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 + + .suff :; recipe + + gets mapped into: + + % : %.suff; recipe + + and the construct + + .c~.o :; recipe + + gets mapped into: + + %.o : s.%.c ; recipe + + In general, a special target of the form .~ is replaced + by the %-rule construct s.%., thereby providing support + for the syntax used by SYSV AUGMAKE for providing SCCS sup- + port. When enabled, these mappings allow processing of + existing SYSV makefiles without modifications. + + 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 prere- + quisites by making queries on the inference graph. For this + reason .SUFFIXES is not needed and is completely ignored. + + + + +Version 3.8 PL1 UW 38 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 prere- + quisite can be made. Without transitive closure on the + inference graph the above rule describes precisely when an + inference match terminates the search. If transitive clo- + sure is enabled (the usual case), and a prerequisite does + not exist or cannot be made, then dmake invokes the infer- + ence 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 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 clo- + sure 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 prerequisite + 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 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: + .NOINFER : RCS/%,v + 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 + + + +Version 3.8 PL1 UW 39 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 inter- + mediate files to be removed and makes them prerequisites of + .REMOVE. It then makes .REMOVE thereby removing the prere- + quisites 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 generally per- + sist across recipe lines. (e.g. cd requests in a recipe + line do not carry over to the next recipe line) 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 respec- + tively. 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 com- + mand 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. + + + + +Version 3.8 PL1 UW 40 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 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 ]. + + The recipe flags [+,-,%,@] are recognized at the start of a + recipe line even if they appear in a macro. For example: + + 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 ending + 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) + + 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 + + + +Version 3.8 PL1 UW 41 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + other arguments. As an optimization, if COMMAND is not + defined dmake does not perform the above expansion. On sys- + tems, such as UNIX, that handle long command lines this pro- + vides 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 prere- + quisites. 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. 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 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. + + 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 prere- + quisite of the lib target. If the construct 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 prere- + quisite. 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 + + + +Version 3.8 PL1 UW 42 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + %.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 automat- + ically. + + 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 dis- + abled as there is little standardization among archive for- + mats, 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 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 dmake. + +KEEP STATE + 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 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. + + + + +Version 3.8 PL1 UW 43 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 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. dmake instead provides the tool, cdepend, + to scan C source files and to produce depedency information. + 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 MAXPROCESS (either + directly or via -P option) to a value which is > 1. dmake + 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. If a parallel make is + being performed then the following restrictions on parallel- + ism are enforced. + + 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 definitions + (cf. :: rules) then these are performed sequen- + tially in the order in which the :: rules are + specified within the makefile 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 targets. + + 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 + + + +Version 3.8 PL1 UW 44 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + in parallel with other targets in the makefile. + + Note: If you specify a parallel make then the order of tar- + get 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 por- + tions. 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: + + | == | != + + 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 compared. + White space at the start and end of the text portion is dis- + carded 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 other- + wise 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 + # + + + +Version 3.8 PL1 UW 45 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 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: + + %.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 manufac- + turing a .o from a .c and we can specify our dependencies + 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 + + 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 make to look here for .o's + + An example of building library members would go something + + + +Version 3.8 PL1 UW 46 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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 previ- + ous 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 filename + expansion for prerequisite names. Thus if a direc- + tory contains a.h, b.h and c.h, then a line like + + 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 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 dmake touches the library file + itself, and prints a warning. + + + + + +Version 3.8 PL1 UW 47 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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. The word include appearing at the start of a line + can be used instead of the ".INCLUDE :" construct + understood by dmake. + + 2. 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: + + 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 com- + mand 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 + correctly. + + 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". + + 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 mak- + ing of other targets work as expected if AUGMAKE + 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 special target + handling via the -A flag (or by setting AUGMAKE:=yes + + + +Version 3.8 PL1 UW 48 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + internally). + +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, 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 different 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 systems. 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 capabilities of + the tools on each machine are different. Different macros + will be needed to help handle the smaller differences in the + two environments. + +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 Pro- + grams + +AUTHOR + Dennis Vadura, CS Dept. University of Waterloo. + dvadura@watdragon.uwaterloo.ca + Many thanks to Carl Seger for his helpful suggestions, and + to Trevor John Thompson for his many excellent ideas and + informative bug reports. + +BUGS + Some system commands return non-zero status inappropriately. + 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 + + + +Version 3.8 PL1 UW 49 + + + + +DMAKE(p) Unsupported Free Software DMAKE(p) + + + + 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. + + If multiple MACRO=line arguments appear on the command line, + only the first is used. Beware of this in conjunction with + the MAKEMACROS variable. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Version 3.8 PL1 UW 50 diff --git a/dmake/man/dmake.tf b/dmake/man/dmake.tf new file mode 100644 index 0000000..9e7578e --- /dev/null +++ b/dmake/man/dmake.tf @@ -0,0 +1,2732 @@ +.\" Copyright (c) 1990 Dennis Vadura, All rights reserved. +.\" +.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 +.fi +.nr Ip \w'\\$1 'u +.IP "\\$1" \\n(Ipu +\\$2 +.nf +.. +.de Is +.nr )I \w'\\$1'u +.. +.de Ii +.in \\n()Ru +.nr )E 1 +.ns +.ne 1.1v +.it 1 }N +.di ]B +\&\\$1 +.. +.TH DMAKE p "UW" "Version 3.8 PL1" "Unsupported Free Software" +.SH NAME +\fBdmake\fR \- maintain program groups, or interdependent files +.SH SYNOPSIS +.B dmake +[\-ABceEhiknpqrsStTuVxX] [\-v{dfimt}] [\-P#] [\-{f|C|K} file] +[macro[*][+][:]=\fIvalue\fP ...] [target ...] +.SH DESCRIPTION +.PP +.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 supersede 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 an exception. +.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. +\fBdmake\fR is a re-implementation of the UNIX Make utility with +significant enhancements. 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. +.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 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\-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\-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 found, the line is expanded +and invoked, thereby enabling recursive makes to give a full +description of all that they will do. +The check for "$(MAKE)" 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[dfimt]\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 "\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. +.RE +.IP "\fB\-V\fR" +Print the version of \fBdmake\fR, and values of builtin macros. +.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 whole 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 "\fBRUN-TIME 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 "\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 +addtional 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. +.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 +\(-> Rule-Definition +\(-> Attribute-Definition +.Ip "Macro-Definition" "\(-> \fBMACRO = LINE\fP" +\(-> \fBMACRO *= LINE\fP +\(-> \fBMACRO := LINE\fP +\(-> \fBMACRO *:= LINE\fP +\(-> \fBMACRO += LINE\fP +\(-> \fBMACRO +:= LINE\fP +.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 +.sp +.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 +.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" +.sp +.Ip Attribute-Definition "\(-> attrs \fB:\fR targets" +.sp +.Ip "attribute" "\(-> \fB.EPILOG\fR" +\(-> \fB.IGNORE\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.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 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 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 +, , and the sequence \e +when \e 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 +(=, *=, :=, *:=, += or +:=), and +white space is stripped from both before and after the macro +value string. +The sequence \e is treated as +white space during recipe expansion +and is deleted from the final recipe string. +You must escape the \e with another \e in order to get a \e at the end +of a recipe line. +The \e 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.IGNORE\fP 1.2i +Ignore an error when trying to make any target with this attribute set. +.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 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. +.sp +.PP +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 types 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 +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 { D or d, F or f, B or b, S or s, T or t } and +.RS +.sp +.Is "d " +.Ii "d " +\- directory portion of all path names +.Ii "f" +\- file (including suffix) portion of path names +.Ii "b" +\- file (not including suffix) portion of path names +.Ii "s" +\- simple pattern substitution +.Ii "t" +\- tokenization. +.sp +.RE +Thus if we have the example: +.LP +\ttest = d1/d2/d3/a.out f.out d1/k.out +.LP +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 +.RE +.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 => , +\&\eb => , \ef => , \en => , \er => , +\&\et => , \ev => , \e" => ", and \exxx => 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 second 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 +This last expansion is activated only when the first characters of +.I 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 +.RS +.sp +{ echo hello;} +.sp +.RE +is valid /bin/sh syntax; while +.RS +.sp +{echo hello;} +.sp +.RE +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\fP [\fI\fP] \fI\fP [\fI\fP] [;\fI\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. +.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. +.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\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 independently of the 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 : +[ +\tfirst recipe line +\tsecond recipe line +\tall of these recipe lines are fed to a +\tsingle 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: +.sp +\t$(mktmp $(XXX)) +.sp +is legal and works as expected, but: +.sp +\t$(mktmp text (to dump to file) +.sp +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: +.sp +\t${mktmp text (to dump to file} +.sp +Since the temporary file is opened when the +macro containing the text diversion expression is expanded, diversions may +now 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 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.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 for the +\&.INCLUDEDIRS special target. If the file name is surrounded by < and >, (ie. +) 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. .INCLUDE accepts +the .IGNORE and .SETDIR attributes. If .IGNORE attribute is given and the file +cannot be found then \fBdmake\fP continues processing, +otherwise an error message is generated. +The .SETDIR attribute causes +.B dmake +to change directories to the specified directory prior to attempting the +include operation. +.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 \fBDIRBRKSTR\fP 1.4i +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 \fBINCDEPTH\fP 1.4i +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.4i +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.4i +Is the name with which \fBdmake\fP was invoked. +.IP \fBMAKEDIR\fP 1.4i +Is the full path to the initial directory in which +.B dmake +was invoked. +.IP \fBMAKEFILE\fP 1.4i +Contains the string "\-f \fImakefile\fP" where, \fImakefile\fP is the name +of initial user makefile that was first read. +.IP \fBMAKEFLAGS\fP 1.4i +Is the same as $(MFLAGS) but has no leading switch +character. (ie. MFLAGS = \-$(MAKEFLAGS)) +.IP \fBMAKEMACROS\fP 1.4i +Contains the complete list of macro expressions that were specified on the +command line. +.IP \fBMAKETARGETS\fP 1.4i +Contains the name(s) of the target(s), if any, that were +specified on the command line. +.IP \fBMAXPROCESSLIMIT\fP 1.4i +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.4i +Is permanently defined to be the NULL string. +This is useful when comparing a conditional expression to an NULL value. +.IP \fBPWD\fP 1.4i +Is the full path to the +current directory in which make is executing. +.IP \fBTMPFILE\fP 1.4i +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.4i +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.4i +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.NOTABS\fP 1.6i +When set to non-NULL enables the use of spaces as well as 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 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 \fB.SETDIR\fP 1.6i +If this macro is assigned a value then \fBdmake\fP will +change to the directory given by that value before making any targets. +.IP \fBAUGMAKE\fP 1.6i +If set to a non NULL value will enable the transformation of special +meta targets to support special AUGMAKE inferences (See the COMPATIBILITY +section). +.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 \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. +The string $(MAKE) is recognized when +using the \-n option for single line recipes. Initially this macro is defined +to have the value "$(MAKECMD) $(MFLAGS)". +.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 "RUN_TIME 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 the difference between $? and $^ +.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 "$(\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 "$(\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 "$(\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 "$(\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. +.RS +The expansion +.RS +.sp +$(subst,.o,.c $(OBJECTS)) +.sp +.RE +is equivalent to: +.RS +.sp +$(OBJECTS:s/.o/.c/) +.sp +.RE +.RE +.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. +.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. +( is the suffix). +If the special target exists then search each directory given in +the .SOURCE. 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). +(a default target of '.SOURCE : .NULL' is defined by \fBdmake\fP at startup, +and is user redefinable) +.IP 3. +The search in step 2. failed. Repeat the same search but this time +use the special target .SOURCE. +.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 defining .SOURCE and .SOURCE.x targets the construct +.sp +\t.SOURCE : +.br +\t.SOURCE : fred gery +.sp +is equivalent to +.sp +\t.SOURCE :\- fred gery +.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: +.sp +\t.SOURCE :^ $(VPATH:s/:/ /) +.sp +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 .. 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\fP] \fI\fP [\fI<%-prerequisites>\fP] [;\fI\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' ; rule to make 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 +%.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 .. +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 .~ is replaced by the %-rule +construct s.%., 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: +.sp +\t.REMOVE :; $(RM) $< +.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) +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. 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: +\tar rv $@ $? +\tranlib $@ +\trm \-rf $? +.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 : +\tar rv $@ $? +\tranlib $@ +\trm -rf $? +.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. +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 | == | != +.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 make 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 +The word \fBinclude\fP appearing at the start of a line can be used instead of +the ".INCLUDE :" construct understood by \fBdmake\fP. +.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). +.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, CS Dept. University of Waterloo. dvadura@watdragon.uwaterloo.ca +.br +Many thanks to Carl Seger for his helpful suggestions, +and to Trevor John Thompson for his many excellent ideas and +informative bug reports. +.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. +.PP +If multiple MACRO=line arguments appear on the command line, only the first is +used. Beware of this in conjunction with the MAKEMACROS variable. diff --git a/dmake/man/dmake.uue b/dmake/man/dmake.uue new file mode 100644 index 0000000..7cf222a --- /dev/null +++ b/dmake/man/dmake.uue @@ -0,0 +1,1248 @@ +begin 640 dmake.Z +M'YV,"@(J(-(DR)(B*."D ,&PH<.&5=S,J0,'SALY=,J0 6%$3IDR(*:\,4/G +M3AB/#U."(&@0H4*!"IP@60*0.GC)NU4T&82<.F +MS)R 4Q!,R8(@BTPG3Q \@8( 2MXI21 D.>S3(5"A1(TB5\C,;4.G3^O+4$;<;K''#)\A?);T:=QP +M;MW;1<=DW:*BRY85SG5TZ?$%@9WJ8:JSJ5ZG.D@7X&]3E7.F#!T0X%UT"4@$ +M 9&=10X/03!$"@(IB9,0AD(% 97\@3WQ%W$,/39444& +M=]6945T:VGD' AUO@$ 1&6%D5)8;()G5QD4@C5?>>2:V89<+#!41QAAH_'C2 +MDS$6E0<(:[7EX1L@ZE%&5F7) 1635WGD41QUI#%'&D8Z:=X<5(*0A!DANO'E +M2#'2@4:36YIW H58G5D&G'+2:==9%")YQYD_HB%BI8229UZ:9YD1Z*!::GH> +MG7.4P0:?9+SQJ!MOG.>@G'20):A;8 9UH&0*5@;"'72A6&1&;%&(JX$1M2)2EL&F1"VJ9=;@T[*(@&1I8@ +M90R6>A*6=L7(H9J7OCH''5*=(2-1-2J%H[4[]LB@&5EY-2L(W-Y;%I^)OAGG +MG!/&.$=;8Z0QET9RF77PQ!"F<6*H3^[K0G5-5!=$=4M45T1U1E271'5,J%S= +M%""@4.JQ($U!11!24%$%%!)#B&^X\ZZ)TEI4T35'"GDZ*T(+(HA[<)1)\GFP +M<65(3+'%:6 ,)*;13ELMGV:P$8:^LZ)KJ[J3+0A2':52>*^V)VTD%1P2AGC7 +M0QN')<=F"X-=U%)8_TCBLC$&X2=45Z*YUEQNT FN1#5O68>44U'(JZ -MB&& +M1FMM)$(/4<]YAD0I?%IDB!65<=*18&.;X;;=AH@25F]L-D>I&\U%VGG:2DS1 +MF;R#]+A4DI.YH9*-OT'A2&#/T15(5&=A0Z"4@X5K&+;62!H&J@A[B%)%F=*T;I0E#;= 6W1UTM#;][%IE: +M0$./H2A9UO.05695+,*I2&]@>UP8ZL"&815*60R9PD? =IC]P&<^0\A/38+ +M! 0P 03]V9E-[".%(R#@"/")(V,>@D$-O@]L"3L/])KXL63%T$.S0J)*0%Z8-#73!'%3]"[V!5<$(2L "")AA+2/CB%AV^I#V) +MI>%T7&-17-QB*3=LAI-X8H@IK5@7SEJ2BTWB +MBD3F510-[DTE#+'9& \F B@400I#*((3J(""$BQ$"E5@0GQ*)[3)I<"'Y++= +M##=%+*PR9"1\(B>8OK?%+I)0I]/"J!!\"E3W':R(@9O8E1XEE7NY[H9\X@%5 +MQ# ''_PH2)\[@U1B]!!PIJ$M#T12+N'84KF835^+BI,=3E2NRX+-!8#9F1 N +MV)9D8K5B'TL.FAQ(23/4 2.#@I]=E).&SVWDQ%!K[_7+BN2K:7S*0UB0VC$S?,FYT.6L0])6JWV>TVV[ZM6//+(Z +M$7UI! @8084LQ94,4BH,,13I> 3I*8%8P9GAFH$+< "*# A!G;%:A6N$.$* +MVS4&"F 3%ARD(0LQ,(1F4A%+I*1C71DC"(AB4E04F$.NR1U HFP[%J+I9-< +M*2V["FX9!'J6\WB)=6UYW?5Z2:'SR4F]#1EN&-IRW"\1D O,9@:!#P' +M =!!0!?&E@8$T 4!=6D*DAE"A=*^X5OANL,O)^3:' 4,S#XBH(7@\"<^69=( +M:BF+A/!&AS'[4\!TR_.9LJ(F@EVH3U_"$ETV@CO=Q>W/AFZ#GP]FSG7!M]%V +M*3(=2G4J\() O'4@;PV=#((58+E-X%)37>UZ1/=5C[T'RP@>1A7#UKW%:T$Z +MF#'!!3<_6V@JY8+FOG3D98&ED\QF1C.(*'GC-#3S0Q.< A$LZ.=,;K)<12(I +MF<3Y9TJ^DE4!!(%>626_)DC;@B 0J&U5,B?E!:[20VR*.J,"S8 +MW'+,K+B!DW\68(BN*>!?NN$,PK[:120=X1/ YR]60( 5=AIQ*ZR1CM1I2G6N +M]Z4'*SP^?2<4I+O&+WX[ +M6C;4 224/,&_.)X=."/@XV4X09[*C%(W])M,G*PVHK+B:(QA)=6NQ?3N\@6V +M(JJIB3;TL_?^IV.]MDBY7(]?_8K,/5"-7463#M(;!/I+_JG=JM ^&+^1"/5R +MT7NGN@JCRT]N;[(XZ(/F6IW>G<[W?[>6DEKGG9_#0!)*';947]^:#1G'2Y!8 +MBD*?HU7D->)G% @*;B)''MX=VO2G.SXN2M.R6K;SM(WEX7IB'; +M*0/TD+W+HNP8>D3L$JI#B[YT>)_/J9F>%D.KLH10S393]PC[E>6-=56L?F^> +M&?R[V*PE%VMU^X@=MD +MHGYVM5-C0WQ^Q&S7I%P:(7XM@ 8(D"4, 04&=U+9-3LB=3E%(0=?4C3P)DGI +MQ"R A4E>UA!48"ILX%*0]%ZZ\C7?QB:#=A%C\6>_AB]N\'.1B&IY6RL%1=?4$R[SAH4'P1/PL1_5\06'$4<5Y1_W-C=UTE]KP'4.E!'7 +MA(+N96DK^ 9^AEAN5FQ&-T 4LC&=!!+@ X+--2T*TA!#L$6/UH']Q(*GXX)R +M0&@4PB)%U&05Z$ . B%U<'LB%"YW&"3>,W!/Q(-*=!YADE(XR#T\.&F600>_13D$ +M1&XM8"9H(H=P$T&:EP=2"%^4"&XXTR"7:!8.-(-288-?"O%V"1!U19^QD-E0!864U)P%5I !X1X +M ?:@C&\Y71OL!1D4)$1!E!EH%=N$0;MPW7@]%O/MWO9,MH9/B0@9RHI7=Q)/\ +M Q8484D=TQ9XHHA2-BUP@ !PT! 2B!9Z!CSIAF @PE+&\TIV46*<5WON8Q5H +M<#DBXF?T121!]3YMD")5U< ::=7!D<9$5(B*X*&Y3J!*7=)SB +M-HQ[&&]E &,/L5/[@5_ZU7\@,@=YX%AM4(BS>($CAA%0P47XT@*1QW7@:#S$ +M2)Z7]8?351WZ]6L1.>)E_)D%%&6M?)"ZG^35$ +MDA%Y4@1X0"KQ)2C,R#\PT"E"$ILZ6B1#"0(0EH-RP"NEPH!R@ !J0F8F&)!L +MXX&KZ%K@>3"JYT2 AA&GR7M#Z6<2I#,\XS-0(%)M9:)JLB1'8QY5<8(,. <( +M0"%6FH?M)9 JJ-!XIA RI!RT))S4A=3P6T.M)T0LG*RN"+-J"V:)BX2*2%< +M]S7WDBIY@P(G,@=!(F*)PE#=IQ(K%CD'MS2524F2RB@]UUI%""HN@!AJ-59- +M^(3(9)%2R"FZ]08,>!@-8007 3BE B?E J:3ZDE\\I./0HI_XQD9T9$>$:HI +MH7-I@"7TR9>T2"8'VE0^QGUYXJMJ(@97L@8KMA'8PI3Y:9%T02>2R3EOL*!D +M*I^K Y$M=R]?,B=KT0+?)S1^UC!!"#&T)R9P43%3PIKU1@<(%GSF"4V*BJ'=%P&AS:#XA4YZH<1MJ,@H3UAX2HA2:D'AVB=J"%YX@2M2+'"9*PPH!Q1()7NJ=9.HDXNY%M(0=4 +M-5\B C'.MB+)-1$H@4,5^A!+14^ LQ5+A@8,6 ='UZN_&GQ"8DMD IH:]#%# +MHJ3,V354DBH-(E!Y("B5.HM^QI"VR)TWBR1&NF-G\K;;8['U!3*;THJW=D-N +M,+JNRO'(A4M":3X(B6 %BQ25YG> +M4K;0>5H4\KA;$+GFYV4'4KF7VQJR9+>;R*6]^4L9U*@?0E4KVG8*Z5)RHDEA +MD <+R!!)@'U:62I.!2@19E\&.#D?4S9G$T,$AU -A%2LA%?DTUC"2(HH+;U +MUKAV('4-HJI#6+K]:QW(RX632QL'ZWNDM7NN0ZH(%SA4%&%G)KRF];YRI0,$ +M^Q-!X1 HBR_F%3@U=G"["4Y HH'$=R;9^SS_EP?T]A %V! ?;#%UEB+NDP0O +M\ 0IS!5XMVTN#!,!@9;M!B(*QF .!F%R"0)PF<1N.0-U*1 NAI<@)A%[26)^ +MZ1& J6*#&6%1;)@;[!#GY\&M0L.!4[5-!3@G\KIKA@9><68J[$DM_,(.<2!B +M#,(U#$5G:R1NS,,$Y<-RW!"5ZQ!+\!&QJ;[ PIWF40J8-LI0DAHK41=R@-PGC^%E-^YH//PYA \B3!%:00"RKXNKZDF(!W0"%[,056 +MX&=#550M@9H'^I6_*(0;GHW4KN@]BP?00;TUH;^87,]XQ]5@ _4Q@61@1075P+F\K] +M]*4GD@9ZD+USK1<@]1=N:!,Z[99^K9A0:$0RF0=3$0:Z##W"O,_/>M%R.<2K +MF3@V$4=Q1$<7E5%Y705Q!!^\BE6135R?(Y_4,\;A CV_ H52.+&6[)8K=P>4 +M+%<>37+GLL_:PG713&]TE-H'9>,XJ^A_1!T=$;T +MD1]FQ!/-;5?J[=M%:()"RT_PU=NN!8^ JRP$N]HY'= _>]/Y47'P04>' 2"" +M@5/HS1 ![EJ(M7\)92"D>0YD=STL=R"\=]Z BR&C3%!/4A)A2(SF!4H4MT$>]UZ_1<[55-) +M(%'WIN1!P.0=VN=/3@0*!3>G3.@=\S%R<#TML+M@:4#0>N(72*TG1P) \&^J^L.D1X+433O1&\WO=@SL482E1]4MA_YS1/_7@11@ !1D-KY<>&* +MX>#QH1=G7F$2V*!;-[+0PZ_U[2@J-ZU9,H-54;CPWA I+MTL3CFLITA40V^" +M5=,S(>&*\1?D;>-V3=X[3@7_S71/U4N/R8J"#5\ Z5H&[2$$-!Y<;F$A<^4C +M\J/WPG6%PWHV/$/O&?05!BST!N-TA$8Q-U;^@0((4%8(8%8(<%;W@=UNI-TT +M$T::-ZW9&S@ESO-OCC'DU/!5"2IF[!9HS 9J3"=L?-S9;A!9B/(B>D=ZLO(S +M\>Q&4.'W4?54[]_H3?.A;O-&C?/CJ:4[_[G+Y@9,5;%N;U<(_HZG]/,W*JW4 +M^GE*I.+JH3"S:[MDQL.@:DSVHDA5#T-'-7\_6C_U=<]^"G(7PD89\3=G\OW6UC2HY7QDG@ "'C&LOLJ8097DJ[X\B@2F*[KQ*SLIP$*^<"DO+NX5'^@>$"DN\T[D9^[H]C6S\?P]F91E"> +MG_%D\H3MBBF[KQ*^K"^ZN=$J0F_PH=/ZGA/[D=V(/_9VY>.>Y\;/R6W.R47# +MW!6:I/T/(>=/(%$4-=K^,?X;Y48>Y1\@E1+JG_.Z4JXRI#EV/]*\QDRX>>HG +MKMG&0F_BKQC[GO#)/_85Q@3I0R:,T\MJ#?\-L4:I'4=(@ !($"!TY)8T?P9U\"7/ +MRLOL,^XQ24EP>W FC]IZ3=Y^'F'J#5JX&.L&-NNU?L1,G.O5[Q UT.L#\>MY +M2<7#?L4H=NQ;;%==#&-XH1?$3T=QE-K[$2-7,-SK7]&44ZPD=3Z^HS"C)]LE +MJU(.(93O/=RC=T@?(CD?,S=B"D)DBOKTLSSHS/9.!B+:%RP$G%PL8B0.%'F5 +MY'7T>7N:U#70+.;'UL!A"HVQ63@")-LBUU?GT1Y@US5RS1 G +MZ77%4J]U0%GX HU&(F=P R1>,3=B&IN%0^7/_4ATB4!UD +M,"/3Y"/5T0+58075(0+T=I)SDM)F\W6NLZSB$' +M9!YGDM)X6Y0!&"/VLFEY.LQ= +MH4EE^A!DZ@+LGIT@$K.7B3&(:]L@ E8TD_1@#A*X<[0QLOB/PH&P.[*<"MQI +MKO1S(Z:QF8@QXBQ'E$1"*=1K_Z9BGI1"#9.1K,%^-@(/39(E2P9?L"5W\2FT +MLOXNJ^(.Y$"ACGTDB6H:$R3'F2\'M3AB3086?#<2XFD'\XS1Z$W\HYLE:S?0 +M:HW33"OK[[+>-!7MF"3<4Y!4EVE@XQ%1<6MJ@K[K1 +MQ#^41(W6.,VT(A3&]6?^,Z'2/2 +M_5D'2"'Y"VU+O4JWGSYT\3I?(P1.8 14Z1"?BQ)[ )]<,UC\+1 !RSPNJU. +MUCJO8XUR]Z9L0NIC<5 >L@4@T!IR_[1 !RSP"CQ1JVPGDB=!T$7+G&W/ACNW +M1P;SB'<\:G#^LLD4JW04S^[WUR6-01C +M6S\GLOO-95E2 %4MX->04S^[WUR6%01.B-L9T0)^#3GU\\4-84H&U )^#3GU +M$RV61>F6'B @T ,(T /A[T9\#Q^['V$M8%F4;ND! @(J@ JT ,(T /A[T9\ +M#Q^['V$M8%F4;ND! @(Z@ ZT ,(T /A[T9\#Q^['V$M8%F4;ND! @(J@ J +MH ,(H ,]@ ]$/YNQ/?PL?L1U@*61>F6'B"EAF4]@ ]$/YNQ/?PL?L1U@*6 +M1>F6'B"EAF4Z@ ZT ,(T /A[T9\#Q]?[(AC6S\?TP*6A1[KE!^"K^+/.L2[ +M;V&[!)Q3J^M;@![K!!_BKQB"K^+/.L2[;V&[!)P@L1[5WQ!;@![K!!\<=1CP +ML?L6MDO "1+K4?T-,6]5?]-?G&1+^:RGW *6)?[>#Q^[KU.69?^F[?TMWP,( +MT ,]@ ]$/YNQ/?PL?LZ95GV;]K>W_(-'0(]@ ]$/YNQ/?P<9A8)050U0)^ +M#3GU$RV6M> M<'>3L_M)O 7R_%D@L1X[*"HM<'!8<\ 0)]X!H[@ "/_#<@))3KL8,2&RV6!45[L. 4 +M,APGW@*6)0((( +)(@(($#5[L. 4,AP[*"K18EE"/NI?M/LM8%G$3TM'S,2Y7OT.<0.]/A"_GI=4/.Q7C&+'OL5VU<4P]L4-<=L4T@*6 +M==O%=:M[,*ND 0+#D<0M8%DB@ B<-O%)84B@ !1LP>S2AH@,!Q^=F;18EDZ +M@ Z )[L":@>3%J,AQB]P:@>3%JT@*6I0,(H,&HW@*6Y04(X 6[+V66U= A +ML/M29ED[]<4-@:S18EE[X/(V(5B6- 8@))0@,!Q,W *6M05 @ ! X!PEL/7. +ML5.W866[GQ)[$/YNQ/?W-ARZWKQ?W!!_ T)"&2V6M05 @ ! X!PEL/7.L5/. +M86K0$?YNQ/?P<9A8%01.B-L9T0)^#3GU$RV6==L4H@,(H ,+?A=?W!"W75RW +MV@*6-6_T#P4;Y48!0MZ[WUR6-6_Y0=Y_$2 !O_O-95GS)OZ*(5CE+]Y2 %*[ +MWUR6-6\298:'\?)WE%,GW@*6-6]_$2!\+_B$+P6[WUR6-6]_X>0Z$]Y!H/"[ +MWUR6-6_[@00(@ 36[@0@M?O-95GSYN^%SQ-&G@0!DMHY=>(M8%GSYN_1NQ%%?W!!"/NHW +MV@*6-6^$+P5\_@1TM/M8U0*6-6_PH=/[$2!T%$>[CU4M8%GS1MY\_@2I#>/[ +ML5%N%"#DO?M8U0*6-6_DS>=/D-K[X>_MY2<7#?L4H=NQ; +M;%==#&,$>P4Z1A;$+UBH^:G!5DF2I96656/]E19D8?^F[?TM[Q&?&FP'!2(G +M8=!/F,AL*JSG>RW\=6/$0^;A[T9\?V\>\:G!%B(Q8A%;US[,%RRKQ*;">K[7 +MPE\W1CR&$\DJS?:D1HTQHF1,5C/;F3[UZS%X^"6)LAFAH^8$!*XL.0=FP]0@ +M< )<< (+(2FW)Y3[96/^)0=Y0NF6'B!DX>^%#_"%SQ,#7_!Z??!ZX5%PR!-D +M[O+B;?SE700_.]5H$",>\:FMM=2T*O'7PE\W1CQ;*A5CX'.@.;**!3@:HY5E +MC?&H24/XTDSW-\1Y5-"<'YS[@RI)S8#9,O5\VYE]RD"=#<"&WATO 3=B^J5>ZUB$;H9[[ +M96/^12_1/6LI%:!\ RHI%3A"F2=!0' S1H0D\ID*53<:@7,@< (C$')>$B/9 +MY+V;D3^MZOS V20DHN9*!@=VQ?,Q4M&4 +MHSV5)%E::5EFX6WZPS\$9)JQ>?KB&UYAH37E]24'@U[119)(*5*;0ZVP5EJ? +M Y%8=V0_$9I!]2(>LOXN.U\S:\P%RE\W1CQ8-#?VB;X.,6-Q(16@R2(G+.7_ +MEVF_C5!*QF1J#F4,<9*E0F QPHXU*.C=0B$_%K/-6"X8@[AZY;T5,[*U?W#N +M,P('18%S8Y^ZF2))))1Y48J]5TS\& +MI$!'6R1F@0(]0!8JT -DH0,]0!8JH ,]0!8KT .TVCJ]4S#B-GW<.2_!]R+*V#\&E&XG8H,S>7#LY! T'ZP_YU1

G!YD@5A +MT25PXRJ*N63GR 4\\'^6I3U](OU< &T7L1:J%B0A\V1-^"E-!UD^F9H@(93 +M"P)

;!ZD!\,%@W)!TLJ/(OF_C5 @'SKT=@7#[##(^D"@XCL* +M@@JR, +M\R7;J5@@$N44(H]=]%EG+>93PA"*4\E\HXH.1/$/8_$E!3N<+RJI%SE^))0' +MA1)4L13<@UD=RZPSQ)3 RA8VYIM LA02 ;PU7Z%[7"1F@0+5\0;5$9M6L1=C +M%02DA/MNL! (R*G>I#]K$6[W.T"!$I6T@IVILBH;Z3!(U+',.D-,"3A?DRB; +MP3]F@=3)=0?TPW]3(!6 GQ\\T4O0/$/XRC/XG*4!"MY2<7# +M?L4H=NQ;;%==#&,$.R&UX;F>0:V4M)VU:Q)L%TRALW1!,A>Z#+<4\M;R>"_9 +MLV9EH,&:&08Z0# :$34Z8#CW0K!7X!G4ZK)VRY2DX91*R<_A"P)14 GL7^2@RI,$$.V_T#P4; +MY48!TO(.,;Z8=QY,3>!L01=:X4W\(_G##(HTJ"\$9)IPL/O(JC>2OE6.T!T?Q%V[Q4NNZ6(95^[3_$/XRCB7"G,YH2X;22E$BM8 +MQ/ER\/I?81X+X2Q@US4O0B%*!QA)X 2#+P4Z$'+[>VS:HT2[3_$/8_&<8D@+ +M 6N@DJ\9]'),'(2K2H2=NHW=."T_*[4E2SM(0F_S]A=.KC/A'03XWQ"*\R50 +MI#V5PFQ.B-M&4BJI*U_;*:^[3Y)(><'ZDJ*1?/;WPB3Y@RF[+X>(>$5%Z0(' +M4010P(8[0P5,"/JA-R*%M8 $.V_[@00(@ 36[@0@E1**\R50I#V5PFQ.B-M& +M4BJI*U]@32J[CZS##(J^.=40FS[G"$64])*[K[?+QB<$5#A5I6B_C"PW6CW/ +M^SF[GUPL LH,H3A?XMZ-KTUA\&P$Y )0@ 0"$E*W7:M,?)%>NU?L1,G.O5WQ Q .]/A"_GI=4/.Q7C&+'OL5VU<4P +M]L55F3[GZ )0@ 0"$E*W75Q2R&ANTJ^.XI)B_8$Q,F_^7O@\8>1)$""IW=Q$ +M4+3GX1%+\FSSFSL>XYMX?&OTLC@5(P>O7R&78UVZ,Z&;0N5\A9]_9,@LF\0Z +MQW+>A* 3,[9(O\C##"MY!RJ%XYYS\/J&XQ57IS'3C%()[?]K/I#T-F_^SNT< +M%2 M[Q#CBWGGP=0$CCO)I2\6PC^2/\R@2(/Z0D"F"0>[CZQZPZFXY9O:0[)0 +M!)%Q>V1,?-O%=:NEPN Q,F^' 1\#7_!Z7?60CN1NQ!%?6TG!^G-3 ::GJ)MZ +MPZFX56*[GRS63/$/8_'T-F^'$?,JGP1T]!!#4$OE42&_I:V[XYO)PDY)G 7C)8\* W9?0FE()#07 +MX6042.J8LONW75RW2DE@US5R368'-,V4-"?!PFUCN?O5,3)Z(3/^41U$X#+5 +M(075D7%PT"\I](!8=#"W75Q2F"?5 0?]DD(/**E+V90JE<1W""K/BI\XRCM8 +M=#"M7#68LON@:<(7\25?,\+E<5F>9JY90DE0FQ7X0WI,K%=S +M=-F-1;)@H ,A5V/]E1:RC7W#>GQ,?-O%=:LS.;+RJ##9!"!B-, +M#$40&;?,YH2X;22E CPG&"2@/\%)?(1)^ 1+.*NX;22E1ZK)VVX(!1)5)G*A!\H)OFFEJ'5\$ETUR,A$+2+#S +MAO!)D-T\P=C^\1!$4+2N@B73#!+("M$Y!KI( =V5S,10I#V5PFQ.B-M&4BJQ +M$G!%2VL3,;45IKZCFB_PWQ#S=AA7@ !7L$;[H1(1L19J8F[31C.23]SZPOFB +M(LZ5<'ZDN9*OX1IY%53L/NX[P;T-F^' 5(2)5@!4N,. +M004WRFSMG\A040:>\U]2=$C7_(1?8A%HL?MH\:=K0@90E7>@PBW7G\BH/ZNX +M;21'QL31F^Z2SZ;OTK>5Q"W7G\A_Q/FBPDY)3 71#^8P&^H5=MO%=:NE CR97%5F_Y'T-F^I?1ABCP0(@ 3PP5$USA#>"CA3G27( +MBI0:#47WBU(/\OH5(H4; 3=V*%*#!($UB!7DB5"J='4:)JQ>?I K !"3%*U?L1,G.O5 +MWQ Q@&$:!L6_GI=4/.Q7C&+'OL5VU<4P1K#SEMK[<=-O2 7P@>1N5.-Z\A9F +MSV:-;\P1^R04$D@-U79'QL2+W[IO P<6S< +M78'AXB!=H4E)J?I900;S^/H_XO]@4QUY4!TC<[#](@;5,3+0]6?5D0?5,3(' +MVR]B4!TC\X!+#WI?D@<(D >2\5QC\%QCL/N2WV/B$NJY"2($A+79(@<3NHWY +MLOLN\#-$$ 144 1L]$96,1&J7O,@84S!!C:A[@80O/O0DP=7$ETE,:U+BJTP +MJ6J@XL*3Y0+153C!P\38"I.J!BHN/%DND"6)2+!!$+].B-MLAE!>QZ:3Y3Z> +MZ$%L<1Y%XP(_0P1!0 5%P$9,0)7Q/@5%0 5$D 12\&B&.ZCDJ35 (541$5C/I= ;L +M%.])X 1#P 15\![H 05+F$9/4 53H /H 1X@\%8Y=D5.:GQK_YPUDTYGP$[Q +MG@1., 1,4 7O@1Y(J(1,J ,@( +@P^Y1X[);6JYF8Q5%"3[L'B.R!+,P*=%P +M$[= 9TL^QS^%XR[+6O-V$4%;1=9\1-2P\^(QG@1L!$<\@T2F)RDP:ZO$JJ65#-HS>F\WH,3K"4 +M;ND! @(]@ ]$/YNQ/?W1H*E14G=0TP52(H>8@9=D:ZOD[3HJ^LI/K_?%E/B +M"SQ;=SH4TE%.P(2JI,(?N?L.,7^@TLI54TJ5WJ'=FGPH ?*@O3"[[Q 4U*'R +M[)5-RVT@;S>;EFXG\G.Q;F"S7NM'S,2Y7OT-$0-TJ6%0_.MY2<7#?L4H=NQ; +M;%==#&,$2^F6'B @H ((H (]@ ]$/YNQ/?WAFR]M7#<*:]*>6.(*MLB96T@ +M<0(]< *[[Q!)JSW[YD%LX4>-;Z04U*&[[Q Z^UA? OH$U,HX0[Y;=SH =V3P +MOIU'2U4+2+"4;ND! @(Z@ ZT ,(T /A[T9\?V_(UEL+EU!FP%0;4C#18VT@ +M<0(]$')4M?M@K+VC K(K7I+AGP1.P(17IS%_NG6P='"[#\; (]OI=B(V"#T4 +MU*'=FGPH ?*@O?O*Q"<4U*$WNZ4L_976.(*ML@< (ZT ,A1U6[[Q#:LV\> +MQ!9^U/A&2D$=.G [JTT MOL.04"MC#/DNW6G W">N)1+.SF[[Q (M9U'2U4+ +M2+"4;ND!4FI8U@,(T /A[T9\?V_(UEL+5U#-HS>F\WK @\X4DJN[[Q"M_*!? +MD17+);Y>]/R Y"CEDVXG\G.[KTQ\TE%.P(0.M&0 &ZFM"A*KCWJM/+5R"3T4 +MU*%LRI1\_,O(PI!J7OL'5Q>[[Q"*M1G=FGPH ?*@'3@4U*'R_%NOST=-RVT@ +M;S>;EFXG\G.^K^?UP>VEAF4Z@ ZT ,(T /A[T9\?V^DU5L+)RYSDM)FHVK3 +M#!(GL (]$'))>WALL;JZWOBE?"(V"#T=Y01,2$D@'SJHIC$:J^N?8X=D$#JN +M=3"M7#6E5.D=>MS-H^+/"MHHN7E26[*T@[=G)^!D_1 IWLIKG4T!Y,PD9_=* +M+\SI7K,5FN*4E.9P$[<@<0(KT ,AYT GL (ZT ,AM\=% H-Y\@0 I4!'6R0P +M&%\$)W $E.*-GYUN +.(^%L M2:@>7LV1&]7,-SK+T !1HU[E\VME>+G,Y-9 +M71=BG2\'A4AF9.KTHSY]V3L%LV_8W'=Q +M<4P$5 9V;WFN&NE0\ 0]@Y(G$B@WJE7G^.(QG@1L!$<\@T';??$>E0\ 0] +M@Y(G$B@WRK;;"=;PG6XGXLHJWI0;(?F_C5";F#UV;W(;K2+AXTU3P17W8GC8 +MW'=Q$NQF<"*0@'SHQTLK'IB=\ +M0@7Q007BLIUISEXV207Q004+ ?(EZ5H3[,%I]48S.;*F5UJ4%(2K2H0']-PC +M2T I#F Q<@)4$!]4T ,AQ\ GR=3%G+0_EDW16S1SNU?L1, +MG.O5WQ QX,0:!L6_GI=4/.Q7C&+'OL5VU<4P1K!4 \U1'CZ50DDL,EVZ)D-3 +M,2B/AE 5S+YL0)4.X4 VF00+04E!N*I$&"0DD 1Y8DH&I.)+2U*4Q-)?294. +M<2Z;091@#A*M/$.T.K(:WUA]HN+/>LH>\:GERG(@, 17 +M0 2?Z1=^-@170 0@T /JC@)0< 5$H -BL+B /-P'T\I5H^XH, 170 0+ +M04E3XW*Z62&_I:T)!4ZW=\(NC&R4]+S9%+TZZLREGG(H.1?1U:I']A-()#07 +MD0=D430.TA6:5 8:[&=?8)-#< 5$P#18<1X]\$ * SU88\^DFQX-#BHWYI'/ +MXG*ZF7K/C')!PFSW7**Y">85FJVM!9HF?!$NS! G^6O<-8_G,1&J+I\_&-S/ +MF6-N$2.^K"\$Y!DJO*PU#)HF?!'O[]%<]ZI%0 5$D 12,*N_='L7Z36JZ$!R +MUJYU4:*Y:6>2C"+[3ZL7B3%D*C'02%G'W3SI%HRB^2@_EDUI7G+81Z;HKGLQ +M0I)(B>YJDDE6W#L%LV_8W'=306_K[ZDD)C=Z6S['?&?8]?%+N;3/I ,-+"]( +MI#"4I)O*J<%^5ATD4!TH,"/],@;5L4((\ 9K6!UNT"\THG$(H ,S4AUO4!UD +M\&;$QB,:1Z5K*# \NU?L1,G.O5WQ Q +MP.L:!L6_GI=4/.Q7C&+'OL5VU<4P]L4-89,30@G#T +M1O- LA21<]A^M"2@>3&J%I:.*:U&HEC RA8V5F*!$I5NL2$%TS\&E&XG8H,. +M5"I,R<.4709>H5<' RZW .6 +MQ0-X@ =X8%F?BQ)X@ >Z3$D3K$P9!.IL\:S8IM!RQE\W=B:5B7H(O>)#K,%^ +M9I,30@.LQ=H4D@89-#, 0V^05(8$%4D (V +M^05#\ 03E01J)04IL! NFR))!/(JY1!#, 0V^05(8$%4D (V^05#\ 03E01J +M)04+\34A0T#/BI]_]N'S^:SX>5"R_2PNIYLHEVM! O)RC6P_&-S/^3[9LV9V +MN-%75#1PJK*YB;=0M'?9['<,$030VD%=H4F.JC]KH6J@@M3)Q2LCBP9Y8!&S +M@B^\:FL"BH[MZV*AK>K!%IW""H[M[H.4:XJHB;/RL]-*TY_[(]& +MP 1!< 13\ 46AP5?, 1# (]$"W1U0(Z[!#Z]05(8$%4 (]T ,@( )?8'%8 +M( )D\05#\ 03E01J)04@T ,] (B\ 5#, 0BX&=#8 1,$ 1', 5? 5#\ 7F +M-@0@T /1$ETMT 1OI%]?@ 061 4@T ,] (B\ 50, 0B0!8R,@1/,%%)H%92 +M (]T ,@( )?8&Y#( )?W!#Z%4#.#!)#8 1,$ 1'0#,I#F :[&=#8 1,$ 1' +M0#,ZT /JC@)#8 1,$ 1', 4V^05(8$%4D (V^05#\ 03E01J)04IL+@D6%K] +M22%#8 1,$ 1'0#-%>$JDF&XGXH[S:2$(.C%C*\V?TGJ-!W!6X?GC[/Q)R9U< +M!]-1N8 -#BJ0\S'4>&?8]?%+N;0D14FZJ9P:?):S7NM'S,2Y7OT-$0,UT.L# +M\>MY2<7#?L4H=NQ;;%==#&-?W! S>7 QL = LA1N\ 6!U 7!T6=8^/9,' +M%P,11*L')P/O'95N\05!C5 @'SIY$@3*&",@/\011*L'!V&0YQ$ BVL-7 R\-.V%CJN-=59\JSX&;M+0?W%43"J[Q'' +MQ/J) K!Y,I,'!V$.-),')P/ O9V>?'OIXRB<**U&HEB \[GT)=N7M10BSSU1 +MZ19?$-0RQ$X.<9(U2'! LA23#S9 LA0@$M24!'9=LQ%P0Y,B4)F]]A!P ]W2 +M[R!=H4D=ZWEAT$P:/&F]^0*] 6%F( -]X )!HE,M8%D30@ +M@X=.IHQ@X\89?0)[< +98_>AK\QR<'U<)ZU&HEB; ;RH"6!N6BF4U-F!0KT' +M*-L9@\Y<)Q7EFFT&K4KKFB5"X#=X.P6#8I:=E9I3TM%"^<4-L0<-@B5!,B@) +MN /#03_,5-@;\0(]_P),+5*6315X\,C26A=?W!![L*A!,B@)N /#03\:R7\] +M[50'8S9.:'F_1)W$LV\$+2*; (QG@1L5$J5WJ$71-1_1$")N9@*O3&%/LLQDG(WO^8#F7JB]6?X +M0SQ48;(!P>AI%?:(3S/=G?+?3?QT!//(+_,,_Q G*AY@5TYLX1:W%[#O/Z$/>\VT^B@(QB59LOBT!SGU(RX5S+Z3C-2WEUR3 +MPHE+O2G0(Y3P6DQ9<4S\0T#(^D=YG"\'M3CNG>9Z=3"+?VP@< 7GHK?PD_/R +MYX1E$"R;%J /DRADSUV[Y-0E7H9';%/ +MXD.K@ZPXRCL!^A!Y?([)DBMY2<7#?L4H=NQ;;%==#&,$*X\*LV1!1B_)A;=26_,@ +M(93=:A8.TA6:5 8:[&='.%%/T#/H\54=*@4@H /H 1X$2TDYB\X8,R=.)7V< +M2!8MQD_^FI*+' O9W1J_2_QEWSJ$$*!.;_FE)R +M_R58"P?4U];R!;-@R8L$VR\I=+#5L4*"* ;<@4+_4F0!9A%;US[,%RRK]$ * +M8]M.B-L3DB>*4\F7[(0 =L3DB>*4\F7[(1RTHBI0Z<,"#)ES*1Q4X8,B(4@ +MZ* Q&(0*%2E)A%2A4F0*B#EEQM!)\\8-B#!BWM@QV"9,'A!BRB@ 09/F'#@A +MTRALZ()F$#9L3M*A$W!@P3D@[J0!"M-@&#APV*1I&/%-Q(D@I,ZA ^*-F9DU +M0;@)TX8JG3!RSI2A@Q2B1(-RZK QB%"AFS0C2_8$X<3JF[=R(J)5RS;I4C9@ +M:\8\:<9,R()D7"B8');O$XXZ:@9!NC4,9!!ET$HM(X?%0S,P_Z*Y:O!LVK59 +MTVP]Z89,XLJ5X<@A729.'=EX#6KEBM9@F39PZ+PTREHH48$$RR =?AMW3=EB +M_YI^:_+M1YQC=$YUZ/FY4>F,'8L\";2Z=<&O"[O%VG)-PJ5E)%,.^P6!G/YU +M],=&?V7T]T9_<#R$5!@?E0$'6IZ]$=@=:*0QQFK8U0&20W18E09";HQDQDO> +MN4;8'-69(<<;;32G&V^^ 7?47D\D1])80+V$%WMS6*6;2A^B%T:*880GE7(@ +MF"$A"&V\089.>2QT1G-WN/20211:N!H9")#1!@(M(1#&&@C8AX!!:(11VUQ( +MO55=?5)VA9IW8F3786G/LE81)>'&6!G)L7&7TTU^*"CGXGQ4I8%57=3D0:IR.)#A3&4QAEH +MI!20&U-V:)\;?=*4!%5">(+RX6XR3%D2C'$^.%1"RK+D7UKUI +MY(N=O/1^5E+!"+,7U!L-4TL&Q!*7T8+'-5$?=N61$-FM]^-7F!@!?N +MPEO5E2#)D3-6-^6TDT,QVWR4:3I)RP+--,5TJ%-N3 M8Q+M-_%O%0K*QV[#" +M]OLO54I)A'5S38?W-'PG^FF26@PYR@;57&'W*5<:)B1756_'#24(1+>]FIJ@ +M(8?D< Y'/?;-^E76 @(M%)U'FU:-,1=:+NYF!TD:QC8;M9++B)[6$AK\WK 9 +MYXH50W> #>/D,])$!1H:7OUV92Y,48411B2!14<@H'LP;L$/7_SQ'F7F H,N +MB &T=6,POMAN4;'JD*G7+P]"\\0;C[P.F4\_OO5OH^%L&2L%YMT;;#AT:(M; +M'9:4A&LL&"\>X(',7IQPF2(H[V#D>Q[RL#.K3^WF>R_ADI? % 8QDH4.5/B@^'P)1B$0DX?(8 +M)R^R1.5GU=$! C)3DRM,I#M8B4NE&$6:1RDH.\!RDGB@):P&C:$D#KG4"=Y6 +M$HZ5Q" @X0JUU(B>8(7*<',[%)/&%*Y#YW,192#+F8 +MP''(*K [FJ(.!CG4A:TWN$./1#QS$KK!!B$XJ0U2]$(3)#AK9LN#'VFHAAH& +M0?*-;:!DR#A6EX50I8_38L@E[9(&7![,6(M\"2+K"+)\*1).N&H.)"MW,#.6 +MP22^W!,=3H 40G:E46[$CK7F",%6@N2.M7F;'D& AUD1I%=)%09BLB=JV"G +MF)F\433AV)2WS<\-Q,0D7@2JN%96LU7[PLHVW[8[W@QT,:HA3?(R\TN +C2% +M4F%(F])$A\*!YW ,NI9C=A.B!@D2-:DC&U(:FE*=./,]*_TF5QZ:LB2^;"39 +M+)$X>Q*$KGVD#@N#Y-O4.:P,]M*HU/*.1S69I(4X9$<="A7+7OJVGQJDH;N) +M6\ZLXIW=L"%/4#NEU(14FXXM[XYR""L<\!@GGF[0+%;Q*<2$&A]NON=/S6$6 +M&YP5ITGI$S1X\.)<3*.PU9@S30L" 1CLN<_" @0 @9T)@,AR&Y'71CC +MV$BJ)3T+!-ECBG<4DBVN3/8$;CT8:1^EJ;;J+"1XE"RFJB5';/G5.F%P@57L +M>1(7C $F+D##[VC"VMGP])J,S&9PWQ"^RDQWH\5=3G*7:\?0:+^WA:=MEF=7 6\(P<7UT"S?^["" +MR->Q$[9OA]XFAN2RQB0IF>]#%_3!A=CA#?;YY"+M$V+0CO(]9YU-]D#2' DA +M)##4LK&_/"-0N,H5CYR+[7N,K%&(9"FI:90+711*U:?@!'3S<9UU"JR0N?P6 +M!%00)U( 2A4--1*$N*K4:\_9Q@Y-""^+^R^^Q'Q1N#0$DU0)PQG"8&4\MY)V +M>@Z90:+E9NGJMK)AF:V=3]S*.:_3M[JK4%OB%2,[A&$N+V06U=ZMY?F +M-:S>9*6_A8K-Y!ETH>=;:P ;Q-C(;,YKJR-ITQKZ4X]FTJY) ]H8KV;(JL1* +MX!SFR+!8>MR!&%#HGW5!P\_335=J4>5*5!I5FEB& +M)T9QB@:IHMBQ"/5T+:_H1\],DSZX]+W4! 4RJ/L6XTETHV,WZ0[I>]-G /6[ +M&YZX>S>(XL." AH(/BS%R4H9!AV433$I-&X@8RC+RO.4^RL-:*4TX%-@&@E5 +MI_+\)"O38#-(:R-%D7@W3??"$]2)M"@,9BA(PO @&SK8O*ZV3UEX08#WO504 +MM3@G"E+9,G3'YSU)#QP?TRE?@\8?#._)$S??F8X"&US^=82W?O@1K_V>H. & +MWG\/^/7>NO;3$P?GITGF2;.B;,$99:>5)BL1$7=@%8$T2S!%&NI!!QQS!F_@ +M)(F&$_]6$]"U!G'"5X1Q9@AR603"@9V% '$ (/V1!OTQ!R/8'W30@0BP::TT +M5W8B$!QS',GQ$O@6;"/%2L&T%=6Q&&*P(G5 *X"3(%D57ZSS0 @B#0'VO0'\V( >" +73'VBPC-F( "EHC=$( +M)OT1!M)8A?WA N=XCJ 15^ E'>^B%G@(2$G$B1M2'>9B$A+T)6$R)F52!F<2 +M$0&A2E918-H$C)YG!H3&!KV"9IH&0J!6,-7!5 MQ%L9D/TM"2#=('!\D?"PW +M%J521R#!0)H$. F6(2533PEAW-@&HH$2=-1?,?D!K0H<"S2$FTE +MAS#)<%7E7[_48%>%1GQ&9OA16Q89&&KRB_&!:JHV)1;'<\P!3Q1Y%[A2D@H7 +M.?JF.DB! B#1&E@Q!$_0!%!0$1F1!$R0!%20!78$38=2DB8A+P5C(RF451*! +M'>94-=X1!%5P!'-'3Y?3 D& $%01&9P5E-2)1-H$V0X'OHA!0@@!46 $4P +M! @P!$F $D !0@ !9/9$0@P!=7Q?$0Q+(CX:5K(2@,6+4TR&_�KSB,$TP +M)ELF:XMI+WYH3/YS$G(@!GCA*'(@3<^!*QDY4%1):";1$O)&794A+P_"*VSH +M?!/Q$BI9.[4&B6L(4L9$&P[!27RV*@5#'J/"%=%R1VU0%BVU)&)P5FZP!J.X +MD,]7@P]5'2X9B58I.WXFBMC!D0N1>M'"((BF5)61G6Z@*8NTG/:)B*V7,+71 +M E[1 F4VAR!0!#X7@7SVATV $U0!0A0!5,0FE2 %30%&2M6&8O10*U3I!C6D"VYG2,S+P,' +M&4%G$%UZI0BP1^DB=;"I0BSD0C#$=2"P=90J/C&0 V"7+E8T=D1D1$B4=DSD +M1" 1<$'=S+4J72G10!7&Q:2)\6)A 2GA!8ZBF]TB\9!J-&Q86%A;#HS$4!Q +MJ.'XC A0I8L*IJ\ZIB1U$%VBCQ7$CQADABQ3/Q]1)7 0D6Q1!FR &@^65>^$ +M1V@AG!(B: :! DTP!43P!!Z!3$54A'"Q7O=YD_FI:-S9'%TZI<=J5B*FVS +M,-CA%:@1+751C&S %7+:$R";$")+!XS%COZ7>9-R!G=AY$)%U(1""HX$A +ME!%)E"#@IG#Z7_8HVR(I-^1$ZA9'D51+ZY7&;\T%F6Q25;R:3V2'BHV$406 +MMU*RD$6%6(K%9P]5?<\$C =D0\VU4T_+9\OSK6T5J S!6!5+%5;E(-\$(@PX +M+7."%:$K&5D'!-4FBG](IF_D; G;L]Q%$RW@>4?*NSI'I_['IP\4O"!0 L2K +M3+R;/<9X$ 3IK=;*,&AX0ROPO&#)2H-:,FTV*8X6L$=[9L]GNN315HAV/ZRT +MI/.:+^OI+^X9$R4:FWH($X,U!N[94$C8I%9K*5L 6R@P/[$$ F?@@PE"M396G-!'K7ZPDG$M@C,&<)(;+S9*JP;(DYZ +M$G3[AI6R7E@%2F9XM"E#,H7*4&>D2_(S$=7A9!-&5T$%C)V2L_$(AG#@59'A +M*[-K$&QT-PA\QS*L42<0P&_T(N%)1P-CR$FZ,J@1+B !(!; B\FK\("%1QC +MEUBA4_UE$%J<(&'V$63Q55;"NV\!I-8%RB1B@)3ROL*AFWN1!2PS4(X[AD[S +M$B>P K!E%-CZ1@^T7B_34G7B3L :%)%B-D^<+'$R8%D5%T19'0^U%U/0=LTA +M=DG@!$<0Q5)P!&;K$>_DEDN24M(A;R'CPU]1&>Y3._E(01;4C_^H9/913K:W +M%TA@49$2EXEU6#]LP(F_Q2Y]K'5O O*%;JW+(O.@+T<;$O+#FM=)A +MR^\9QDFRL.UF0^(+AQ_'*+++S&Z,3Q5[([9[,%V0+BOZF5B %BPHB! ! A +M!)F9!%: %;PF9 I!1\Z!3G]! CP!$Z $X0U-4QS_MX0?XHCZ+ZA7\C4%$E +M+USQ)*\9G82\B;F'6K-WLC1?D7DG+"MTC1A!$N23U^$T-:QXFW=XFJ-!3Z> OGW1G/!>?5: +M@'+0/V9WAYLVO0TA"LGA%81H4'N-Z RY)^6R[M,LR=Q +M(5,Q@!3"2GFPRTH1L##Q$F6 9Z2QU KE:&DK>ZSDG)L292> K"EGB]A;'O0 +M!X!XOW7^VNYX(SL0&SQVEW/PY)5! GO XD((W@,LC%=^-!':!^$S!0N!,B4B +M@\!-G?CQ1H?,-G_*$O0-?60LB5>)N!(%WEA]0@(%XX>>0K*]*4Q^$'8KZS@7 +M31/NB(LA4I]1M$85ZU/7Z[R;>?(6&L.^B6C!595Q*3T 6X6.Y]#9ZXTR*;,1 +MDUA!!@3'9"G4X4S]K$Y])MB\7OQM[(]:VL!B)6 --]"]SD\QT@A!MR/U!D16 +M[^P<$T/9S4$P!%*@KFTIXPQ9.DV+J*NMW:TM)K1XX%'V[HA6GZ_,) L>*E)+ +M&I_AJW9<&5P0EW.0/?D"$K[Q306S%S0^?)G;'+3^@B7AZ)@'% LM/F(* E'> +MXHQNA1W/!*6#=)@6XT>;F,#I:DAOYP1XIR0!J;RT0Q%OM'=C-VM]H +MX%2^*K$93"/;3"07A[HYZ&)M'Q'Z8D:\,'\HWJ%"E0L!I[6]M:C7'.LVT%S0 +MB]W5;_5W& M.*KN.N8>%-S979T+R7S>!:KAX14NZYM[5Q]#3Q +M!$*@!"#0 ]C'$V\@!FJP2,$I7+;/?$:G^VKP-A>=&6KM^DH0?S*$^IE<\PFB +MUEZ@ W0@ BO0\2*0 D(?/L\75I3D,,L'!K &6ZD\T39>*E8V.ULSU0+Z_ F_3$KE?^VJP H67 +M'[7_^Z.)%4'&%7U;R-5]JV;OGW5$.VN_G6.?M&W!*QA/%=[>&K)G$!VO+\@L +M%"KO8(4,V' _CJHRG&=P9N959'29B'-=UU6(2,J&'9QH&V8AU@BJUE1 EL7#!$70 +MP)RQ%K3(Q@$*ZEI?W6*QRM)9.D@8?7$A$JQ/\VN]XW# FI-!619/$Q0!$54 +MX$,/??I4$#'8:9]F<%GE;--T@5BAUE1 EL7#!$5@_.?DHYV7%BNG4[WX-QZ$ +M^9;$NP4XL*$2.&8P.&]9&:4O\&$X4[2&9@27$BTP!-"''/@A!VA-$\K/ L;= +MF_YB7&8P)6H]!$; !$%P!%, Y%6O/T7?'%2I4P@( D-@!$P0!$?@$1/)QOF+ +MFH.M69@E!LL8A0B CE XU_UQ!BF"'_P]T7Y;$H.;%BNG4Z8QV$_(U][(2[;3 +MB<0QLB?TP/8=W('U71'5^9D=T9"!PKBU@^E-^U;M^['5O +M);@(-K4_%VT@24M9T^I*BP^HD/\5(U?/2@\R7_8]4Q6R,._^)/=B9QTWXGSF +M'5Q0HR>L44.HK8,2<'11RB(A(1VGS2QR;4F3<[=4'71L&&R>5>OF'2?P K U +MA-HZ*#OR(!)AW_Q6;"!1'=\T.BOB!NA9&,D^I*R1*,)H@&_ WX7NH1T1MF,; +MD9P!&UDE GD@'2)P&LV1A ;780@3GD>S;A]M$\VL^+Z$%2[@H1T1MF,+N,$, +M6T]R+R.Q$B_9%8"QYAG$%M61W&\D I\B NG>K/0,K4_]$:YAW D2H<,F:_.] +MG-6!TU90/$Q0!$GA/D26W&_TYE_C';W Y#!619/$Q0 +M!*!1+ O+/6>%,DMI*2\ 6PKLI"5"Q(A +,>;R-7AAC_K3222^IJN+FWMV9E @.J2#%%G=ZR[3K/0,K4]MGV8!Z[M^[+%I +M;#RP E=3&2M HZY8N>7B00;! ROP$:XQ[%-^U;M^[.#45BM H\)G_B!_B07ZM7]R&<5GE&:(OB! +M%"?+3'2>ZO;M$%1 EC@M!?7JG$LDM-E;$QHO>46 !5#P!%(PHH:#FA.E $'- +MF9Y)F9:)F9K9HDR $R 9B+:HC]]! A SI2YHDI=&;N#'>%.EFP8(; +M%#)Y%:R4>??R!F=@1INTT[O6,0=K,(D[Q0<"W@&@_%(5+;\0+&'3[07]S +M9BZ "[@TY'YTT3]!#_]5_ %QOWDK_EB>FM3I'C&O&%Q\[_TO85JZM]$Q[2Q +MCOVGZC9W0\4B4/^T%DO>3N->SQC4BTQ!N- 1PHT=O=T]XK-&;5#U-;_DG: +M>2FW<@N+QY_/7@=*UO;-;XE_0Q/O>6_17UO[:7 JXLZY1 M[OS?T3:.S(FZ +MGL01+VXP.BOB!NC)%:Y8N4(A95PW5Q/)]ZCN]Z/.2CKJ3VTB3LR+>5 1&MG2 +MBT9%N-!!;X@T'B4\Q(W]2YFGO#S1^@CU$G4^4Q6R,"?)O&'!:N#T@C ;:%O[ +M:5V;RD99*1"[+\QYJ=[AG$NDZ_Y_[#O&&1!["!S& ,7O0] +M4^Y#9,FMZE5YFS>TE-&MP$YZ0B _3V@ RH@ ASMNP"T1#S!O #'&?.X&^'C +M @C@ CF=H639F43]!#]-T[@!!5M)-F*QRIS1F%3![?LI3LR+>1\$$FAQ(52A +M2*G\3:.S(FZ GL013XT]C,M,6?%>_BI +MZJXX?4MC'+71>E";BW*Q5Z/<&/;EOLP;%H'YU-!WGGR[G8H/J58WJ5P'__%?&3(P _5__V4G/FSZP4**\1HC,P;%N->S]%:XC!;?W22$@.(O-K, +MS=[Q0T-@OV*%7,UD='M M\\!$Q0!410!'Q/NC:4A 9GE,/-D+=\.OEV +M.US)O&%1HBOQA35HE&PB2L%=S4^\TI1J7LT!.5U/\7=O24;))IW6?3 +M[U1VM2O2(G,1?$<3$$"XTI3Z?-596*$A!PN#D1P]8/<(D'E@Z7R"!%A="%8H$$8W%O)%6R+I^+W;6 +M<8$K-^.1,M[A M\\!$Q0!39W0T10!#@-U(&+)T&Q36U/NZ-NWPK"O.XRJRQ3 +M&Y+, _7J Z91LLP;%CS0!GGP!3>A$R/R!;3S!48Y%SX0BZVF8 V"%A?2$,P; +M%HK$M 1>RB(A(1UGP+L.8Q=&NC;D M\\!$Q0!410!#@-U(&+)T&Q3;X"8ZI! +MC"#1%N]\J:LUZO9MA4G"BB_A&Y_&3F(!W9VA-#9W0XVT-'#Q@#V_6J,^!YM3 +M$.G=:K/8V-D&$FAQ(52A2"=3!AWL'2[PS4/ !%5 !$6 TT#-O&$!.0P$LWVZ +M%R[PS4/ !%5 !$4PYG-9&-[A DEP! 0DF6T5/&:+TU+@'(6;.R!@7N.3 +M!$= 0)+I'(6;*HV-'26Z$N!D6[0[ZC3K;(LAE)WS]%J^*N('C]2,"^( +M*ZT'&&O.->O8?\P;%HO[CJ1HP-_$^8/,D)(W!6:+TU+@'(6;*HTMO2"Q9LU* +MS]#ZU$=#M;A"%Z4L$A+2<:*T\9>*2..AZ_=B9R\!L?L"2KOM.!>X\9?:Z6^* +M$'1F^7H1/BZ "Z0TT?M!)8Y!$R $S H55@TT3PF3:-TYKYTT%-W#58ST?H;=Y +M0W89W-7\Q$DN52B;_48YW" @!+!\J2&;_3?_2_\$QG6"_H:M_I!J=9/*=? ? +M_Y4A S10__=?=N)S=O.X1/S/S?Z/JI[MJ87-O @T=\7#!.>S8_=A9FP- K/I +M]_C!O&%AE'-A=V'A @@0/*%)U$_ H57PTY8Y!)]I'<]7:OQ S:J?V]_:MS=R<80/.O&$A!-^, +MT^#\>\ FH)=*(?B.DO$N2WPO +MCXV1!G@P/BK7&&?F @C@ C_]F1G:!$3]!#O=TY1I'=?/3Y8&]J,5*LADYZ?_>C='%XF%=EC1$BMA&B 1/ZB947) Q&V @#;(T??R +M!C";!FF:ON3Q0? T*4=&%8;S:5?CZF^.\NMQ/_6Z;O\$QM__&']+IHPXI/H1 +MU)SIF91IF9BIF2W*! C !""0H3]$F)8)\)%)U.H:FDO=K/0,K4]MGYU/X1;N +M,(:#FG4.G]/)T5@=)(D_D;)'JIZ3S]'J;S88WE;221P4+=X1AED[*0AAH?!)N^LE$@)5YYNX(J.#$!TT +M*QZD>2N!M&%A!NLE$G^+$)\6)PU5[0"D)H_J>4"?0A%*Z(GUB_;3;B#,G7A]T +MT1WNBG&2W-U)W_ YQ)4!.?]DMT$RE';Y]:<,G[3+AUQQR@:\Z\=8&:X8)\G= +MG?1=G)DWC!-)&L6TT?M +M!)8Y!#9-!)_)F5"PHDB $B &[O#5,M)3EO[:5T;*1\QG%/B,K,2*,S[,0X2 +M5J3<>Q\WJP8'2_-%+48Y%\S;JI[C9K0$ H"U6GS8[GX_ZG.Q$D'!Z,P;%LG] +M1FFZ(F>6H4U@! A@!$R $S0HD> $<0U'_UA35XF()6G,_R026Z$B91EQM_ +MJ:KO$'_8Z6\*Q4#\Q(6UL>=FHS9W0TY*;L0-H4F"F+T+*IW^IK3-][+!O&$Q +M'&>6H3]$F$N $%$F98Y!!G:!#9-!-:1!%(-W0VEH\PZ04UMSZS<%FYP8SEV +M9AGZ0X2Y! @01)1ITSBMF3]M'4GPA6; BA'C&:LARAD44*CY)/=B9SIBDXVM +MH\PZ04UMSZS<%FYP8SEV9AGZ0X2Y! @01)1I! A0/)K)! C !)^)&T/0X,CY +MA:X8)R( H>'8!JP]C1](UPA @IM%("*0%!Y4!E?3V/W1!JP]C1](UPA @IM5 +MA>,O%M"=9 &%FF&X8_ $<0U)61!%^X,TZ!%&K=!$; !$%P!%/0K@VC<^#V.;'#O.ZRL>>V +MR+U&3ZD( DU@!$P0!$?@$;+? FH]=T; !$%P!%, Y.&3H3]$F$N $%$F1GZ +M0X1IF0 ?F42MKJ$9%D/0X,CYA>;Y1296@]4.0&%EZA.?,'4!LP;%A1N +MX5KI+^[(KU?=K/0,K4]-C":Q;O?(O&%QA&HVXG$R*K"FK1MGW6%QU$[ H57 +M! @PM@C !,N3!)O8L&JB4[%6D7_L'4Y0!6/[$<-Y!BM-J;M#Q2,N.$%QC]"' +M'&CQ9AIVFDA[J2N_[J!D$DY0!6.[M9\&IV?&F5!P!0AP!39-!.*3!%]H!JP8 +M,9ZQ&J+\<;-J<$]R+W:F(S;9V#JZ8Z2(6"4C)>8KHAE*EIUI! A0/)K)! C +M!)]I'4G &; ARB@)W1W>FJ);,*%V'#9W0],=W']?ZNTT[O6,08W ZCUE!P!40 Y**T +M\9?Z)/=B9Q?&2N->S]&JF!_A&AF/RB:! LG-O)&&&FH]=S@M!4 ^Q8S;W)LT +M;G[Z35&G_I!J=9/*=? ?_Y4A S90__=?=N)S=O.X1/S/S?Z/JI[MJ87-O&$1 +M/&:+TU+@'(5+;YGW(P5C)SP1/ASJH:'YF4&-! @0MI3)! @PM@C !+CQ?,GM +MM4S5W)P!&UDE GD@'2)P&E+&=4EHSQ@4I (8L>%M)8L12&W.^$ES9BZ "YPU 14 +MU"O:HB\J!$'=3?L52$=SPTY0!6,+&F.QGNEV;43F%_Q7< CL,N/]IJ\Y&O_4;)XK#O+C!(#QP%F) HPKLI.1VL6.QGA?8D-;" +M$G)DSQC$ +MO+BA%$Q!M;C2&K)'%Z4L$A+R$B6Z$C!V89[!O+B1W$VQ-3O62$8EDV?6HAS: +MEPC@EQK:HDN $%$F0=C7BYU7]EA$DY0!6.[M9_6M4K!%-^$$I5ROUQ7FKS" +MOO)M.*A9%F=A@X03_T24[_6E=L,EJ2;=6))EF8I!&BI +MEFQYSC>RMN%CTSBMF3\=U)_)F5 0U"OZT]8Q! V.G%_HBA>XK$I[-" Q*GG" +MO+CQ)/=B9R]AGG/%$"$R4_OU(/-EWSK+O+@!3ZXX?3Q!AV\TC#2U3"G+O+B1 +MW$+Q$:YAW'!P9C:-TYJYTU9@! A0/)K)! C !)]Y,$DP;++6[SKC&L:=('_O +M>26Z$L<8_V(!W;P;L-/Z/7YFW'+ $$G9',9N3W( +M,D (R$=#A!=&NEE78&=V! AP!#]-U$_ H57 F5!@! A@!$R $S0HD> $<0 +MU+BQ.TR%H"6Z$E\82 YSF((690]B)X03_W#3S$DABVYP8R ^)6N,6.![$LR+ +M&Z=LH?R=W-%=Z.,?=>H/J58WJ5P'__%?&3*@0SS$J7-'V?EOV4O$_]SL_ZCJ +MV9Y:V,R+&S5XF((V4[2F>::937.PL1CBJMEC3+%/?(O+CQ(P7S@METRA8*GPU9 +MZ.+-O+BQ&,-8-:=LH2+N27XB;,R+&RG70(&V3"F[M9_6M=_O&L9]K?&_8_ $?PTT3]!!Q:!9P)!4'-H<.# +M ,2# ,6CF3&-!95A7O:9ZS=?Z"6Z$E_HBA?(G/&_;LLL*770&&F !TFQ7\O. +M9-ETRA;*O+@1H5&V&&E2&PN+A#GI>1-)&C;'=2\B?"9?XP']1;P$*V\TC'7" +MO,P3L(<*3JH%ZEI?W4BQ[/X)R_$_[O4!QQM;*H?&>:9Y&E.<,R+&T<0\%4 !6 KMDQPJ&B$'2K7&&F +M!Q0_&XL12(03_^OCO29!95>[)*=LH5%F!NLE$F<=_]!7<"*!+/Q-N=E$+4<0 +M\%4 !<)3/EC G6 +MH3]$F$N $%$F4&]HBWZTRO*H57 F5!0&;O#5 C*9E]H!JP8,9ZQ&J*<03'+ +MO+@Q$G#K&L:=($8YW)5*9-X1F#MM!=!WGIO"O+C1MW39'<(H&W<4/[#2%@&% +MFLE]9AGZ0X09TUC ! B0EIIYU$[PF4R $SPF4<-S@AP!"N*! B !#6Q.TR% +MH&SVA2U!?,&$/VF0INS&O+@1TGJO3-1BE.+O!G BE:]ILR+&]X1F#MM!>=D+) _ +M$(VA44N*'9.2IA'SID@A \R+&\^R^IT[T +M/0E1?TMI@QS=$@AQ-?'/&KOQGT,:)Q&*%& =)YDX)0L!!P3!O+@A\>W%PRM2 +M,'8R:Q+Q8/"D(%4Y:!ZA98%/,N,O)O+@AYMG6222^ +MIJ;]NLWQAZ!V!FX3_TV1YK<]3L.&D-G?D8.R&ZL073"U"X1;N,&1>/\R+&S]2,'8BD"/^5?MU +MA&JVIE_[.N?V)/*=? ?_Y4A U_'0YPZ=Y2=_Y:]1/S/S?Z/JI[MJ87-O+AA +ME.+/:;_AI@;GK?.(+(W$O+B!QY_OJMF4W**$%2T !4F"F ,C99>J^@X1Q.'# +MF5#PTY_)F5 @0[O#5 C*9E*]_YRLAESVMQU^/ZPO0YR<&27@ BK7&&AM0]L,EN0M$G^;0IXI!4-0 +M!$Y !2A0 D4D!57 !,CSEO%_212ID /308X(!9()!6_D26<6U$B &%+F4R +M &.+ $P@/KO#5 C*9E]H!JP8,9ZQ&J*3+ +M%/?(O+CQ(P7S@MD4TGJO3#,VQ8R[G,R+&X2_&,-8-3/V7S'RBE)VJ>3+%"A= +M,@*%I^UU;1]&APK"O+B1<@T4:,N4LEO[:5W[_:YAW-<:_SMV'\-=J;6A457@ +M!,;C3TB1W&_T K[I!B\0L&<6U$B &%+F4R &.+ $Q@! A@!$R $S0HD> +M $<0U+BQ.TR%H"6Z$E\82 YSF((690]B)X03_W#3S$DABVYP8R ^)6N,6.#K +M3@MA::937.PLS]$*Q]$162%=*?,9_[:* L[&(*=LH;%XR\HD&\R+&R"!%A="%8JTE%TQ +M!DE(\LK=2@KLI'$>__:9VMZ1W X#MF)+MF8;!%, 8BJ7L?'?2@KLI%5V>RQC +M6TZKNX)ZFUPWC-6,2J5LTJJUIDA48VS!O+B!Q^L!QP1!\("E#SV"IT6P/ N;%O+@!;BU!!QQ[>RQC6TZKNX+Z/S+#O+A1J+,F +M$=VJ;D0VT.0+%/HQFAY$BOV=3!^WR(&1W-V9ZL,(LLU*S]#ZU#$?U%> %>0 +MTRMJF4. ! B !"WZTZI>E5\X!QM[;HL<&-3L(2&R(MX.D1)'52FD^@[ADB:_ +M)%7@!,8#*TB1W&\$!BV0*=Q)Q"!0^@(?*%O[:5WKG9+U GT>&� B? WX7. +M0"%"&C9W+!$$QI['Y8"3-"Z%$L/-D 91^@*?U>'^SF$Q[O44A@X6150]M +MU0M@ED. !$$@!=CW*ESD!J.S(FZ GME;$YX6$"BQ1H7LX2BYRI2XK BY +M%&VQ-*U6'C+(%K285T3F'@>Z(DB1A#K% +M,SPL.J0S![%6DJI>+ *%'8%T-+0$ N8E9321W%;(%U4PMA\QG/BIM1JFP=@12$?CL2M= +M$Q7U09FG$ .H88@X;+*6OAPRG=!7<)\?3P-:RB(1RK+G%$-1N/36X3N#DJN\ +MI?WU>6I2N61?FQ7)]Q1A$1BA$1QASH\A4"BA$A+Z?'5.M[LA/0C@ I_)F5"0 +MTTR $Q U$]P! AP!*;A @C@ CE]! AP!$=-0$7]TY]I&BZ "Z0H4VP! BP +M!$'=HC]]! AP!$%M&BZ "YPU 14U#E]U$Y@! A@!#X=F:;A @C@ IP)!3_] +MF9:)F9I)U$_ H1X:FJ;A @C@ IP)!3]-U$\0F)B#.=7!! C !$3]!$> $=@ +M&BZ ,$3FI\9!0@0!1Q:!9]YU$ZPHCG=HDR $Q@&BZ ,$3FCG-! C !)]Y +MU$ZPHJ;A @@0/*%Y!0AP!2W*F5#0P2Z "[ H1X:FI\9U$B &%+F4R &.+ +M $S0BR\(LU("ER7]%D0&H"GD!%4PMEO[:5VK%$P!A[7_HRXE932!QY_OJM(U +M%(6;XG[A!H\9F1Q:!4?M!/WQ!2N:TQE:MI0) AGZ0X1IF0 ?F42MKJ$YFAM^ +MH"LBXL-XC\PZ04UMSZ2X8Q>H9DC);+_(8RFD4KS14LE]>S5>H=M$$R2 "0 +M! B@R?]$;+387F#9*JP8;&*QRJ9! @A C^ #]PJUA1@Q?]8%ZQU#"SE3)E +M&B2 "1@ @A@ K>*%35XT24W-32/ "0@HSX0D5(-W1TN%3U(W0>/6K-J<+\4 +M*5[=@]1=%A6^2_5* @A BC* [>*%358,QXHT$T%%A(3MB3KS[)$O,%3\R.@C!U8JVTC4!6"JW,!53 +M!^ >FR2 "1@ @A@ @:\ZU]H!JR8E:9T.UQY9B2 "2@ @B@ F\TC,M, @B@ +MU@B D" $ @1CH@06* &*0 @A01/>X8Q>H9I3FG%(1'ME;$S-6K_\$QLOL +M'A&-5^8W-'=$G1P(53!R0^RVW)@ +M$NC='*87'C:7>B70 H2T%R2 "0@-$1C[7XLRN3=\P_F,C!S2C:W5FU"FR:! +MWLV1A :7W Y# @A BC* Z %.QJ??R!C";!FE*'OHL5KN.+*KB&G);K_SID6_&[KJ>U2ET +MCZSQR5\F!UXM?#]:%83A07P/2-"]$'#0,$%L_=VN$SGU:TTA16UG$B3P _5* +M D0CYC$Q&WL*%)7OG[",>0"=N3:+$D&C-7 \D7 VC=WE@7""0Y@3G8IKF8A[D8C0Q N+'PULI4^&S&2K',[EW +M$FV0!QW,(% +MBEB1W CXP-49)W4^4_H3$^AOV.H/J58WJ5P'__%?&3, V3S$J7-'V?EOV4O$ +M_]SL_ZCJV9Y:V&]# IK< BU HX@G7 3Q-B2@ B#0 BU HXCW-B3P R#0 BU +MH^!'%B_1!GE@7#0Q G $EG2A$SGU:TTA16UG$B3P _5* E[P-B1 -"W0 C0* +M?F0!RP=# CP BW0 C0*?F3Q$LW,G =# B8 BW0 C0*?F3Q$LT\D'E@7""0 +MY@3G8IKF8AZT79-A! A@!!Q:!4?M!)8Y!"LZU$5]U$X AGZ0X1IF0 ?F42M +MKJ&YU,U*S]#ZU$<5U:UD!JSH4@YC!NLE$C>"FG6^D$^@3%XAKR AK,KOX@>Z +M(E2S9K(Q<':2V@A!D5S.X/%#%1X$1F^C +MUF[ C'6066RP66RP62PPV$_(U]X8$=XH!_Y1!YGUU$F" @I)FRP67.P@D]M +M_.)C[7[L'[/(6^&\8M!V%M$,D=W=;^ +MJ%'EC7+@'W6064]MT;8UR@"D)H]*+6: @I)FRP67.P@D_=%8"QYA)*F@U[ +MFX_DC7+@'W6064_=P6: @I)FRP67.P@D]-\;.Q&*Y8N:I>E7'R*A\@"D)H_J%/( H/]A'R]\%_0'V(0$=XH!_Y1!YGUU$F" @I)FRP67.P +M@D]M_.)C[7X\V$_(UPO_!:[M>8/]A'R]\%_0'V)0K^8Y*NGVYG+ O-@_L@MI +M7J#A&ZBY([MAW'(0UGZFH"QYADD +MNL8M![RR\Z,,0&KRJ!UN!@B D&+"!ILU!ROXU!Z,*&?VZ"BP+B'PU'$ @BPP +MV$_(UPO_!>/( H/]A'R]\%_0'V(0$=XH!_Y1!YGUU$F" @I)FRP67.P@D]M +M_.(C!&5PDFT!NZ^:(Z*$%2\R.BS#N @JEPZ2O3;DRA+EC7+@'W6064_]$<,Y +M)=C!LYUX&BH/0&H"F[>Y/!TN108XG'/+T;[K&Y^&UC2AUG.P@FB !-Q)FRP +M66RP6:@%A6]@C?KHK&+B!LPH0<8O/E*P7E *A31%@G&%<_R +M0>.YP1<73UFW&\8M![QB&B Q*OX)DK7\':RB*:JU\3=TPQ7\':SBP8@R4[I= +M$-UA@'1 !@\6+??[5CFY*29?XP%]XV@M0VI-ODRAD""@ L85Y,NC%$RQ&\8M +M!R;1'R+ VN@(A>$H!ND(A>$8A0B CE (V.D(A?TA J?!7VR"6,7'O*F>[C +M0*Q;R)_\94IYC%GWT KLI"?$]^2/LR9?XP%]XV@M0VI-ODRQ @H) BI@7(5M +MV.H/J58WJ5P'__%?&3- _SS$J7-'V?EOV4O$_]SL_ZCJV9Y:V,RK%$QAS%,A?MBI4K +M]OG= CL,B 7>YA:-QA;,*F?VZ%ZY@G6066* &(P!RM(!][( ANH\"KKA!NX +M6:P=A1_8!BI8C5?=)<]*!][XK,8O/E>@/R"!%@NC2!NH\'V#CUWRK'3@C<]: +MY/K#/6>%,DO)O/Z2A"2OW.%(A0K/%?R+%4ZX@9O%VE'X@6V@@M7(%:XH)2MM +M0\]G[;")UC*DUBHG!EO! L+% L9%\RA _)5)!5, Y&AM'2/3:9]F +MY]5A[;"Y9@1W@<#X(P7S@KC2BT:E<@M3VQX6 +M:,>8&UM)-F*QRKW(;YAO2=XAAZP_^PXA_"0 !,85/M(+$E]( B2@R;A:UKCN +MIZTV[O4$A9S&%%/RL191@(&W/MA-@]Q?$R%NN)'F20!XIK(0S4YG!9TM[AIA]RH&2=;">DS5:1YG5 +MC";Q+M19XP%M.ULSU0,+5,,*OUD"@ V*PMOEECQX$E@9! FH-!#H@!B\. +M0'E^-'/MA-@]0'\!EM=&9-1" B20M5OQQ Y# D>CKV(*EG21!XIK(66M)K 9 +M=%1\$'!*B[+7*F7LREFF]\ITZ[5AZJVF8*YVXC\:,6BQ(1U, B0 ^+MAW'(0 +MFR20%!4B^'DB/P%Q!FJ1+0],!GF@N!9R<*B4<-8.FR"6YG7P7S^:%&I"'#1/ +MB^W%P\^^P25G8O8- FE>!Q0/$"5G8O8- FE>!W/H@*@SIPP($@A)N% HF%# +M(GG.&'=&]099I01 &7GQS[)9<&4@!.5$9UB:%!T$D"A08' +M=-)AZ-).!;[&U0ES*."B E:P-%)[,[B PA0,!%#A#SR6,45/08I9(0SR* +M R\J0$0302Q1! IPI#"D0U6(5 <<(\J1WTQ&R"$?"%,,2,<=61DTY9)-/AEE +MDA$"-6&% 2((8DH>O6F5<@;%V1MZ9IC!$H=4<$0:<1&>V(9]!MU6VW%+/660 +M2S>]<<=Q(!0DT(!%'<5:: 3)M%"$0417QVQ/F09"?$QY>94<>5"ZIZ(SI>B? +M0'>@ 5V>&IZ4TH#U.9K<2X=^@0 6PKH@[!S"UB&L&,@I+!;7^AI0&6W4ER5[)J&0QH;VF0J2EJ>"-@8:((Q1$E9 I>0K +M&6EXN=Y+>%UVVX71W7?A&:0::T^%9N!_<:)%FJ'FU:?3 +MNKLZ5U!6\XI&FFFHZ8N&J72P>A5'/]76VAQU[!;&='G4%^!,>-*$;9WZW7EA +M5'F,VP:@]XTL1\FCL10&H42A>VVG.]GK1LMOW"03"'94A:VEI[EQ1LC8VI$5 +M2035]U588Q7AVJQSV#5D#!R"D(1S%PNTLLH&?95%$T(\P013=+24E'&QD)/%]_4$]94,'QCGI +M4]AF+L;F &,2'_=?G&/B@2R-K&0Q04\ +MH%F??%! 'J$@@^7S0;C(MRT\),QNR8L*!*V2MPY&R"/"X9M)E%:R,F2$7OSR +M5V]<=H8TV&$^EX.*"XE2P;9A4(-F$"$NZD@+ Q(&^! ASQ(J7$J88FA +ML'6S-_QP<22C%^($TBGYQ5$J97"0!&>5%K!8L @N<$(5F#"X?.4G#&3PGZE" +MDK,XCLA-K<$('4H6&NC)#(\3HHA$%"]3%KEVNY)3W6>;@:ODO5IU0?6% )T]\$H:C +M\&:"HG'."8I(%A#H("WR=&9H>A*SK8FADUE=F3 +MAH+T9L7TE8;9%/*!B8S@VV"C3X)",J5"HD'=/A,5E_HLIBNEJ4W]9T5&[DV? +MF--<5FI'+MP1SG"#- @*7,"$) BA"44 7!&D("5+(8IZ66Q9P/84,^E)#*"Y +M#.OLQAJOBM"+3'#,(DBBLS6;E 0YPL,66]T*5[E*X:QR.%SBU%J0W\715TQ: +MPEH0TU8A2.$Q22C"%!:W'M34/T+(04?68L.FDX0U"&!R6H)B"0'>U&&)5ZW=K* +M_ K(5R:GIDB9"0HZ"X(:N"!A4 V2>UE:U4">=ZL-*0(W6;)%@"(60,[3IRF? +M2YN Y:^E]J7G#D$FFMR]09]AP%+FFCN=OCFR;95:X2)A0Z?@! 1Y$)9P14QJ +M8;85U)A*S5N'A;.401HRK_X-XP _%[J[\@0[$W5812/VW9'HEF\6DD- DA0C +M(:>O1C?*T8[B"((?,;EZ,YC!D9*$)B=!24JKJQ+-L/22+8&@2U\*DQG&5*;5 +M55E-*'U1'.,$U,8"60RRE5G/ N2_YH68=".N<"--[#84LW""*PY(HZ;WXNHA +M%R978,:P@71Q@*E!(_T@7=\C.CNW(J;E;*5EKRF%6#:1Z9(24, +M?W3J=W_=Y66/"+<51IIGB0)4IK#A#(E^RJ'VABU(O8]2G4)NI=+0DX[TR98< +MNL+TZB.K ZVL:_'SU63?&ELNS?O$2YX"WXR^F\NVR?K) +M2$JCYSU!&@Y#LS:B4WBHGPA9(&C9T\@?5.B&<#Q@/#5(.'UVGI&(#4.H1EE) +M_%<2 :6P/AX7,D_>P)H9OSSF:)%HPQYF48P&9#1*L;&OJ':1,"BW(>;[F1PV +M@B*9D<<@83A#3=V@,!QO?<<7-PF3 W@/$K00EU1 B2A@?-\Z4-"\H 454O[[)RR?^DO$I<;Q[Y&.2 +M-KR!7ZI#^[IB91Z1THP-I>XVMS!-<4+3V@V44C9:G(IKW_+:5U8+B%'6$]\> +M*5L''7Q^KY?H +MD T!6UEMD +D*C@A">!J@G<,8K;,DA@$5@ %04 %2, A0G!V^Q0SNY$^ 3B +M2-!^5S-WM1=,H7<".N!,!?$NSE5.B11[+Y-9%,,1U?8LC@,Y:T IHF9\=<

40#4B +]-M[B,IE*)KF8(4T!=]%U90.N %!X$",X@$.C '+Z # +M+P "+Y!F$:)NP34Q0,9]OA-Z12@GEN(5/^@V>R(N/A4A=H4I"I9HK!%&*/83 +M6Y-+16@74( 4% 9@$85?I=4U%A-RW@@>.2*7,=CG9(2NE8? +M1D%_-:A7-0@4?H(B(D45U AS14KC$'L?90]4$0E/*/%(-=J6(0O^=0>U5X!_8HP*(V(%1"/G!$ +M (0'(H06#Y43KG(?7U$%1F $^*=:T24 +M"&"9[TF>PI(&PB(&U!*?XC$MZMD%(-">"%">:B0L;(">"/ &P@('PK*>_NF8 +M" "9"("@_TF@ $J9"! ']TF?:#2?Z4FA:>0#_+D%.^"?$RHL8Z"A#TJ@'HI] +MSZ(JX-F@Z1D&\HD YYF?[WDM[?8?O#-WE.(1X@-_,W,<& (&)7 "'I-;;K 4 +M[@F?\ F@&&J? 8J?'&JC23E%4$(BA^.CY$)'Q(@I_I99::44]1&C:S2@-&J@ +M#TI=&B6;J@$#JB$4JC'B@L%OJD&)I&& J?4L 2',%PKJ3!SF-&X)]L#6G+QJC,TJA O&2M0<2A:,?3"%W +MEE2-]'*CM&(K!>&/\F@0H?$>E$*0+$%](,!A93=*4'%3'6(0O/HFTVJ-$8)M +M99@2V7D'V]D0-H$36BEU929*\[(U/+H>/NJ:81E=/L$;#Q8AF74&:$!(#L01 +M+C9CZL$&=2!.R.$K)3!NNA5$V.IO^K$4)3!X0*2NIQD[CY44 J%\*/B:?+0> +M=?!GC!0@.H..X=2LJ4%":==#/U038\9?!&NP)F&7"3L# 1I),4W"DD)> "%L$C$,L:KNDI%M&OZ*@&5">T+J %'91#+Q"T0[NM +M$2NU1YM)2>M-,T8&9/ "62NT'92U4TL410NNU/<"3+LA6QL;Z&@&:MNT8]!! +M!1LD9UM@%2,VV)<$)F%#)=-0!84=X!^.A5.N9L''!(JM!&5 +MJ2&!*!AS]UN7^1LP#>E= +M \9[/.(2;Q"T''%0?E(&01MKZ"N-ZLN^]0%2BCMK2?&^!F$K=S"_$>G >'#" +M>. ",(.Q$XS"*;P&#!PA07L>.G#!R;J^#.R^7MIX\KLG],MXAH>:2!1 H>$" +MYR$\LD5 ;>(&!9E9XS2,I,>+H_N4X$<4XWM001LP>9 18S '2S.UY@L"-HR0 +M&Z+!;5)[)PD,"(C1V8CNKED<=2;OBDD,U #PNDBQ!DEQFDE7*8ERNDES"DF9/*<0S+) +M:89]960W!_=L)?*0Z4@5Z_@UN2+(;3PF]6K%+:"2*?&3)DLIEWHZ#@=ZB]I+ +M4*2L(XNMH>N!OGQZP;2\%_$2P#PA%*NS/(LA*"''>DR^8S$%4\L"=B#&[7<0 +M/*"B\H)#'[S#\3O"71B1Y+0_:+&NL&8Y22QX$>(KU;B L +M>9">:&"B-2VCTQ>OU7S-=N!1,T'3-HW3.FV>U@:6&^P&8P"P*@<"/QVV8X#- +M@,(1;9D;;5RPX'0:Z')/!YB _81[96,357A@L!LA=/U_ +MH0$#SO+-E0+3[>*V(K42@ITRH7<>J*N2[*8JKV(0E@>GGM(0GG-RH6%7>P*6 +M8@D:\>/5-C0A[8)7#B'98L>2HQDP@;V '-G94&S2P* T%;[0X] H",5"+MFT=V-C6/-;01U%]\V':V-(3[]033!TP +M7AUA:!#15@P"+= "(O33)8#-\"W?4*W0+T#?V(S-V%=QJN*W],*JL18:!M.Y +MBMM3L^'*812]_3)D$4+@''+7>&C,*5A]6(P2;$41J>[NP%U +M9F=[:9E+HZ8B-*$1-H2:S(UQ9J6H5EIAH%MZ4ZPO%*O-%:9? +UAN9MT:O=RHE_V,!L-N G%L4]1T3+Y[[=O=^']DRH *S/ +M\=PS&T[/_34K&XS&117=U'!E&=#>FL +M.Q'I?(4;_1D9PC($PC(%PO("U7*G%$H&9P2J+" LV6S6#FM\P=Y&=LKL"& L +M"##5[N%-V^BOC][K/0PSN!&F&7JGH(KM& J@R"[L=%CLQY[LU][LPO+L"!#M +M&*N? )KN)LKN\DZ@V*[M2;O21W4???1#_FC<>V>N+.V28$Z8J+Q L58Y/^W' +M6$M]0HO-Z*N0:(!^YMAWP*&4*'#@0U[E%C]ZW*8@HG$')@'0_6)+YQ0A860Q +M]P%IKF<2@%L&\%4?09#,JJ*1#E&P!W40)( "0* #9) "/XT06J\#9I "]GU0]G(00*#1CFO<^UC>9DX1 +M%A'7&X'V-7B&>[71PUP?Q\+K'$($MHN_N,O43FS(-A#)2A*=Q9EEEGPNF1QFG%QFT)DF5S:=#B'W'$$"0"!.JVI0KP X"0="RX4Y]O0)0#0F-4YI[OO_+YN&U"6XJ"]]W'A/I5X*P7*/8AX_1 +MW4XK%X(3B3["5X*P7*/83EU^&7PE!:$A@(;'4A:^[ +MU?F33N0\YI_F>Z]WOF9T9U!;$>)$G+9J7\9PT+T<^PL">2!;5DY>[CAA)V?> +MR)O>5(]V&!_!Y*>UVER=/ES"&!_+01*V$1Q=#6(3+M#Q#CNRH>'D--'$!,=P +M8;O"\1J]-_B]2UWXNJN25-\0$$R^XWL"S&43+H &SG3!QNW#YIP6*QROYR&V +M]9$%LE5VKEZ0-*%@:;[W1(YSJG+IH--:[<$K2,Y_BGWX)S"D"%LOV>,EWJ>2 +M4*FZLZPI5-\0$$R^XWL"6;\60Y "8(P&SG3!QNW#YIP6*QROYR&V2UV0Q483 +M"I;F>T^3L\7<:S$$\GQ+]5$KA[<\0!;TL]'@!/T1(7&;H9?U:S$$U'_[-R[% +M:QXGYAU.NQ+,[@'BR'3TOIL]7G(UO7)% UU5N8<;+[\>:;[WFV(>A4/_O#7M +MU?NZ)L'QB )T7PE!:!@K;JEIX4Y]]1'J^^NZQLW!O$43!=D:KIR">9/'5!4P +MY0CRI'/BOR$^/I3K60/,/)%9\#:P]\'KN7O^Y'IMV88&1S/0OLN1P+L>5-\0 +M$$R^XQNT L5<-N$":' "8PRKHDPGVV<3!]T;5-\0$$R^XWL"S&43+H &SG10 +M@DRW*DR^02M0S&43+H &SG10@JQF1#%+4.RJ7:I9OMA(ER$74K 4+I#72< $ +M3W $2^$"=RTX3W $2_$529"(>,@":E,%4Z!:2% $E+047W$%00 %2^$"%#X$ +M21 64[ 4\W9:4I %2Q%)3S %C$$%;C-\27 $3O $>!W:I.U#0)2"Q:WX0-2Z +MB/NZM3QI-9A/[PQ0#7X?^H_87-JRX9Z[96#K7,2/L6\&6/YOOFBC=7 &,7$U +M,,E'A>.EFX6V\>HK!U]52APU+%EF9SA["!M;LU72SX3FS A:^[Y/05ER$7E]6EFN6+KWP?O$Y]-R[%:UYFMM(\&#_0+OGR]<1@ +MS3A%_-S&^23#J6OG;CK:BR.[7A9&YV'*5PK,A:^[O I+J&T&TQ[0#%:.(,_/ +M -81:V>IQA5WRJH;HB(3++#4XX));NQ^_YO/E,*K+Q7,-%'XNKO>8(URU%D& +MBC>[F?3E;!WF&&438)DMEWQ\]Y$UF2M*J9QB$V230\R3.HF3PW\2Z'T:ZT@I +MY*36C VNT=04)HXEYG\H76CPN3\:_D?1P+L>5-\03AO!Z$M<\&T1& W?IY_VU\C681Z+,(CXNG$UK-^]WS:] +MLZPI5-\0$$R^5(N^Q 7?%H'1\'WZ:5\?1I ]C@(3RBR8_>_6:WES3<&/9:"1 +M5C$%63 %5@ "05 %1Q"=J1Q!O5)X:($1<, WA^(F'+'I_YO/E#+[=ZZ9$4)5 +M@5L:(F$H1M^,4^1=\T%B@?Y-?D1NY@_?05 ?9E ZR-$>R!>6HSD3K"H@._&3 +M8&/^7*/8AQ\$57 $T=DK'/%Y+2!/4/G&P4M T8=$!C7&L(I]THH1UO]W1$+>,#?G MHU,ZQ<5=$?*3!#O+QOW&P5NQ +M+A"T&=0R/E"+7O*32^1'Y):#R!ELA<)PXN*98= MG1+H8)(%4V %(! $57 $ +MT=G&2^1'Y$8I4Y#0J[5E'G@NZ49H\T%B@8DHJ(D16'()(22.Q-KK>:(Z9J_,_688Y1!5,0YL%WF*+RO)Z[K-$> +MOL+KN4O:7]WQ$?+&P>ME44ZPLYR9"5AK!.8KXS@TG:/$1+$&S2.N4>FN OL+KN4O:7PU+#6$$##=4R&HP +M[3&417F4J\4\Z!@4(Q4KDMM^(9T?'*Y;RIQ)A&R;AYQDN\EDC#SY/#(#.&#Y +MH%S)8YZ<7*+)8/+YGBPDH$SZ#6$$#.?9J6OG;CK:--'$;N:Z"F^LN9ZL];'P +M&-XIO%5V'TFLMLY%GI1\A>]_H)N%=&-$3Z<9-[9R> JC"+#3 +M?IJ>&&H'DQGLH$JF9II&:S2AHA',2UWXNKO>8,U'25^=.KR]*;%+5%$0/MJZ +M(;'4A:^[$'L5+*%*#P)D0,55I2$2"_A'3?T&'D@SFD8G$E%AZC5V-&,5.4_] +M:'$>OK_FY9@4'WN,'G8I51,2,^9=&-$3VKW6.1;F& 44=A Y*PG,!>F!N?MX +MV)99VG:0V3,2/^2C[2&XH;OWJ,Q>S>&PFL:/8:EW)RZXH;OWC6X2WC6:VB(^ +MV>,I]6$$+U&J@ANZ>]_H)N%=&%%NJ%3SV>,EWG?D1-&0-@&6&(X1Y8:2R.^[ +MV>,EWC?[=XXTH1$3(7&]B.LHFG:.T36Q!AD4]6^R<.>FE4,>E))/X;?"\7H> +M8=P<() 'LF7E?V03D4<&ZNU#%N>FE4,>E))/X;?"\7H>^HL6YZ&_F9X6RHO: +M,X36'UX0*='CVA@22UV0SSCN9?>1\K;"\2IO =,U!7(?;L(2,<$OA"6V,B\S +M"R]2KO='\F81K2MO'!$:&-$3@%(:(K& ?]34;^"!-*,J3HX>05]A@1ZM/F3^ +M\$T%E?(Z3!/,[=<&H\E=$5YK#-SS#;VFH==V>JK$+MLS:%+G$::5N'[OUP?7@EW %(&Y'Q% +M UU5N4?+5-\0$$R^5WS!QETYY!%\*QRO8CLD=)S%!G7!QETYY!%\%A'EYDNW +MU*S?]9W--5PO4+'.[8PIGUYI];'P+18P&P,LKE(:(K& ?]34T)$]97 6WKO6 +M.1;F&/7WX5X?O@Z1'WD>*MS3AW(>88R2XY06%A%&CIY*,L'[Y]\0^3%'+Q%Q +M0[.\7NO;^\'AM'(A..%=__?WX?Z,DM(K$/F1YQ'&F=[R"LUX9Y$2G(<<#@0LM/OV(Y9<;2S@O0)0B%N.58>.T'C'2!,:W#8B^4&:+!3+#N%=]A(0'&ZZ +MLW_GYJ$J5E0Q;D?0$:R&*E]6EFJ4X',Q;92<'L>;9J6OG %9N +M5QXAS#I.%E(A^U.[3FS A5]?)Z!L'?V1P:&"$'JT%[K1$S5M$\/5&DAG\J!K$&S4/. +M+-D.50>R'C8^T+*J:; :''Z.HN$H.T$F>P61'PF. _TAXM+7L^DQ +M&W4E9;<:/?.HGMN.5^,R(T$1I5-%;P!]0Q))3[ 6HGA9!\7?=K"9H%8&/XD; +M(T:750[/"@W$-"]T,C.32UWXNJN50,' K%@&&HDMO)Z[CX=MF:5M^Y1*M:8R +MFV1\]>'D90?E&)O+M2T:O!RZ>P]W\/0[C+^1N/GXN\EDC#SY/#(#.6#YH%S) +M8YZ<7*+)8/+YGBPDH$SZQA'NN>N[*Y,OKXPZ#7T17&$K?EUF7C@;W7<&L&-- +MFG=MV88&AS(Z759L3'$[N54S=20GNW\U0#81MW$&=8"12UWXNJN5^<+_;!WF +M&&4X(2A2KO=';L(2,<$O/(Q8>EJ(0%%/N2[CT,SFF:Z/<,\Z(@1 +MR!>6HSD3 +MK%H&0KW!ILOKT.HF+!$3_,)S_#(3,\;1^(^E'D8'>_6B7[A0:&1(N5Z?Y2W8]/3A^+@&-*91G/9&YRKY ;RF&2MGH-4Q[0_+H#7 +M3? $5N V"S72F><0:,%MT9BL-M;CVLB1P"N\K4&!KNHF+.&!,<$O/(-T$3V %D(3:X_.P^^<5>-T$3V %7 AJ9?"3 +M?^='YI_F-T$3V %;K-0 +M(YV&P9RF6G(E0&PP5-\0+H#73? $5N V-3R$4M $4H+1+C*)E=@DF+@7?>$$ +MDY$8B]&(@S@9<(@9BU@??-M@/5%%'+%SBD.L:YUC81Z+SN@1B01PT7C#JTAH +MT9BL "(??CW:P)%(F&LYI?3@Q_@13;$U2HWD15X[&;$1NA',=WP5==*2P $2 +MM2$30FTYC1TUA%8&^[43'I%(F"O/=."C#+=8!<%;,P,5-[&".1;FXN$QR*DE +M^M+05Y$'*T$V@KQJURI29U#T.R'(Q<9=W;H15W+'FKF*A!:-97 &1;\3KJSG +M;F 'D4.[_>_6'I%(FT4G-V2=3C?MKIR!6?$@/HJ2XP0@93#"]@('!L:_:5P& +M?-<<,P,5-U'J(%*X^&W(&U3$&,\&+%*L;T"7(JUIK4P?RS;5V!J:1 :D\=7+'UJGSU[I/5'&; +M]=$>S^(H!IG&9,E +MWN?*#+<_G-Z!O>)#90!_F@3%YRH^_,7F!HYD@'99(F N4X_1K97 32^$\H#8I@5OS83F: +M"7*]'I%(F"O/= !_4)G&9^.32$37R#(7V#S3>&$1.$$L)Y<:YUC88Y1=Y!9ONC&83F:,\&J +MNAPB!]='0A7+#@$4=A YJ!R;M3&;34\'<) XX6AA29"(>(A9FJ4XJ\T5]4&/ +MMG@@#$>/N9ZLUJE677,>0$#]J"1$]IJLUJFLYWB,\T)UF43(MGG(2;:;3,;( +MD\\C- #E@_*E3SFRNX&=A Y:9@2)@M$/^DKKG_T+RC7(' $4A 64."!4X $14!)0CTGR5$Z8].2 +MKK$:)A'EON+Z1_^"_6[A1.^L+Z40$5?)>]F;68OL+@#.(@6U(?D854Q[0_+G $4A 6 +M4'#7@O,$1R#4^\M'A>.EFZ4V>9T$3/ $B+':_Q%&\7$3VNVZR=IC#<+[6Q-9 +MUD1M'KX_+G $4A 6;P@%2< $3X 8!F[]M5'_XJ*]BREQFPD:X)H1[U]'_X_A +MG<);UD8F14-ZY]T:-M\>4(%)+"'],V'S[1$^0U-%'.'5LE4\@KQJ(' $&W$E +M=VP>7E(?B60K]1^;M3&;34\'<.!-:N",F?.1L5D;LWG'83=(H2UT3/TX!1'H +MULD:[]%#;@!\\1-96R G7<# L.7*9E Z8P,"6[ "+- "+%#?0,"?9>8O;Z!; +M6MU8XQ,5&]79R$K&UBET)[N_B )TUI\51%=VP04_" /0 " +M*]!!Y0I]<93U4X $*9!(MO*,:2#**?%R2)$?6+I]-G'0>W('F4675>P04_" +M/0 "*]!!Y0I]<;0"B60KSY@&:D84L%4Z"9V(4 +M;@!\XW3'I5[WC"..&3'W0] $?^$$00!7 :D\N>*J-I]SL>P0'I%( (<"/9%* +MM1;H%K(HR/\H#UZLO]0"4F$Z';$H>OO.D0-$S&WS:,&J.M\YXP-$68@MI@\" +M0] $?_$81\ 9[\ROW"M2&($;&F>ZK,HN:YUC88Y1>.2.33%,$6+Z(# $3] $ +M3/(7PCK\AIWB_+CZ5>P00_ $3< D?P$"/3"$0] $?^$$00!74I+U0] $?_$8 +M1S %3D@4L*7_B,W8X+IHP $2(I$^-.^[83F:TF,J"T\P0H<'B82Y4!EY8&D2 +M]!@:[A@2MREK,B>_)\)N?%+X(7(U>F0Z 6GP6C'DWK=81H<<-$45F7,:2;'7 +M_UL=:[D31/ $4W!'\E?E2^1'-AOH:YUC82X>U9$%LO7_5%0?T(TA+PD"0_ $ +M3< D?U&#[U'%#C$$3] $3/(7(- #0S@$3? 73A $<"4E0)#U;; &=#!'0S@$ +M3? 7CW$$4Y "3D@4',\3HP('0/8:0WXUNG$UO94?<_02$8=U,F,4GFM-1&'S +M35'%#I'U0] $?^$$00!74@($+T '<_0"03 %04 $,C #,$ #4E8?'&_EM=>, +M)9/HF(PB6C'DWG?,J'UPS3/"5Q*00A0A-I]S'%'P46&8F=-86C'DWM?@22-; +M2T.3*'(31-;XN/GXN\EDC#SY/$(#,6#YH%S)8YZ<7*+)8/+YGBPDH$SZ#>$\ +M0?X:0WXUJP8"S.MP=%146AWKI3H$3] $3/(7 A1@*3?2M-O_;EV.58>.&Q-- +MOG+P0O<1(7&;'/($,U0T'I@?;1!VPS6L*6%_^#=HIB)_9( AG(<<-H\6K+J2 +M(K(1'M@U3UUTF8.O+PUO!OQ-#6)]$73C 9(, $ +MB+@7;I47@]B(@[@7J649BU@?3"!6(&@> 6XP>P61;C)W0!D_/1XQR/QS-EH? +M/?.HP#=.[:F/(&B;=X>+)J'?(A/KQ_[):4@^4R>2!;X_:\ 6/WEA-& +MQ-IKL&--1%1:IR4%68!9FJ4X=A6:$+3**D^!BIKW$;+W>'ZM:;[WK)'H%^Y= +MOO(&B;=X47>]B%MF>X)M^,'ZP"16 @T"K+C6.1;FL;A_PQ3A8N4R^W-R;2]O +MI75:4I %F*59?*\2!QZ00A0AOO_+0#9OE65OE]6EFJ4XMX],1W_^/B=6 MTA +MH3$?) 9D/0,KN)Q(\L>5-2CQ]4&/XU%6_,7_S4O^NN]_BO,&B;=X>%(? +MWXZ."CQIU='S+GRO<@*H,2,6RV>2 [1IP6I75:4I %Y&L[ +M=..-Y'(\WD@N-1++U:/6E4,>E/)S.*Q/(R!245>#?X?K:?$&7=2ZLG,M&-$3 +M5>P0(] 1VV<3!]T;5W\"$$R^XXN^.$RD0^*T$7S!F=G&Y!%\*QRO^AOTYY=R +M_>_6"^^0DC4&*NRFE4,>YI^4@]5Q924C&TP@N3\:_J'D-#83*(G\ +M]65>M)S'3O $5% $5R^2S(..9XCF*@[%9+)7'#$$W_0&Z]T&8>]HK%=23E8+O/&P;O&HD1TPB825ZIW9@>5 +M;QR\ B&@)NJD*!"9!"J9"."D% J@VFZF4K+:.I45&]@4TRZ@)BH&RR\U"Y5( +MI0.M831J8N4R>0.5Q-LK@)42+SD3D25OI75:4I %F*59BF-7MV_NDDFCDHD +M3DJA *KM@M)ES5_/' F\ZW$M/='494)[4I[W$;+WKW\?LC.16H1\' F\ZQ'L +M9-JDPH("D4F@DHD 3DJA *KM9HI2,F_]6;$@4AZZ>W_XQ(JP9;<:>#)HM/[. +M ,5MOD*\R'3TP'0X/6:D;C8G:2[G4XPT'Q*]-_B]A,Z#5>P08:#"WG10;< & +M1CSR*BPE;< &1HP"8J#"*8"^69_04M("IY_ZW%S%#N&T$8R^69_04M("%I'U +M0V $3! $1S %4M("IY_ZW$RW1@Q]<90519'-J'\0/Z!/I>$&LH/V^L3&L^P< +M)/ #V/?&P7M\.'N#W[M/YYV\T?K5L%3%#A$&*NQ-!]4&;&#$Z)OU"2TE+7#Z +MJ<_-'=0&;&#$:5%:IR4%64"^8:#"[J'"1-;XN/GXN\EDC#SY/$(#1H(DPXGY +ME*SY8YZ<7*+)8/+YGBPDH$SZE!(& +M*BQ4A-;0(GII$]P#QX01?L%+K32VK3U,YM\C8% +M?Q,X@].EFJ4X=M5/O2%* MQ\8RGW0UNC&Y +ME^QE/VE-FO=*/@1W,O.3/^"];'PY54ROA)( +M/D2354305^,RG^1]:'$]V6,2 U0?H8XMKK>:(R8U8_GZXEA6_,7Q"5AKP_1" +M5^,R+F838(DM<>*J4<=X2,,\JGXA;."P)C$ZI:.[!+K32VK3_(;@>1#XU%6-VMA?Q,X@].EFI4?I2Y2KO=# +M/(.QL$\'2%-*LYT]RIH2NU2H/LHO<^"!)$9[B*)I*9$YA8,AL5D;LZG51C\1 +MCY4J\^)#-"D''BA*G"HSJ*)Z>;#Z%N*69;<:/9,X[Z\'0=G81.$GII$]:F7* +M5QHPM8O*T2N5B*O:*0$ZIXX4,7$UF><0N>1Z4P3TG(TI]H=_DKA_.Q\A1K!H +M\#?90-3C/";QX,IPHR96'5=6_'5RS3A%-@?A1,%,EWJ?\:-$"3Q*>$EI7,: +M?]2%-9\]7N)]KN_.1)'U5- $1/!:H&$>WIL2-A_J&9Z4@P6"^L*O!K$:BQD4 +M63'M&X&.7%HILK4T$J/) L.O0F=G&)3F(9<-B&U+V( +MF-&(F &'U\C685Z8EWQ\][$:.D4IF!*;BD.0L"XUU01H@V+\3+>&HDM +MII\63I+77S %C$$%;F/@X+5;3%$?K@^5KG_T+RC7%KY=&.XK<<*E:9H?]=$S +MB+OP$(@OP9RFBD.0L(XN_A.;^5$?JZ%3S4HG$E%A?M6W-T3MB%N.58>.S[:2 +MY]\0D?0$4\ 85. V7:I9BK/P5OY'T9A(#WPYN!6&MK @">2!;9?>1(HG.P-JRPHB C*T;KPX31E^.58>.$&O_9=#1_,@5 +M=%ELW(7DMG@@S(..[4QR7G9R"Z]1%X(3WN4EJ8M)['*M["8J<0RF@JJ#(I:5R#?Q>1L$\''&($# ?=RY&F^5$?JZ%3 +MS9H2G4)@OH(1;C(?(:&[8MC_;MV%?'YUM95R9@DMW@?TG.VJ8)D]NHN2\;.: +MA<^080ES2"%D>3P$\M=#R.^[80ES2%$U#8^880ESI2,U9E Z8U.#[P%UK]<< +MLR=L'X&XF;C[^;3,;(D\\C-"!E2#*]/Q$;(:17/T<)?T! GKZ,+ +ML#4%H".)%;$1G6DT7>21OLN1P,M\T>?T%4\ 85. VTNRXB?0&NJ75D9L@ +M*8$1UL];:9'ME^@DE@&';0@%PO(%BX@9C8@9<*@#"* #/8 /2 L7S ':$0' +M[ZEC=/">>><"V3Y1$"-MU\C688Y10-_\(H,5BK,:.D4IY5AUZ/BO 1L5WTXI +M0^ QLK4TCS(TX,IPYHV\3,U@F?.14P ZDKA_2*/GUWN&:+XG0_!-;[#>;5!L +M"4(K8>0GB(VX)U>.51=@$?(>G&? 9;<:*YAC88Y1EF1#,[%$?F2S0-8;6;,4 +M8[#M"Y-W><&"% ;V,$"O2*"#3D$E2);2_,H0U-LO/5-KQ>\(KT2Z#T& +MKFXHL9['5: 3YA%JFCR_K]<<"&S>0[+)JZN,$ +M3T %16#VV[XP>0<'#YIW;H M8$=4U=UZ AI>N=K^R(<7IHXJ('EB$]4,=%B +MWK3P&(YLZ 79T,6KI!3, .)*]8%-V.,E:3:)35"(A\@$F+$728 C;CB(3X +M3W"*BK@9B[@7?>$$DU$?GN,K@?1+&ON5R*DENC$^0-3C/!8:S042>L8K$4(> +ME$*L7>3[OZP;)J&!6L,&*YAC88Y1"V_B'QE&S4A*)J&!6H,3,\^0OX$6A71Q +MHS+CSC$O%\)=$;)$#6)]7$&&UL:5R,?*K-)?&?>R,O4#&:&$(2&!&9-9KM_/5-FMM(\&-\0 +M/;\_"P_RWH41Y08ZIX$3Y5H?F*+ROO_+J8=LB<)Z9=<3FJ0265&N98 3WWB] +MS!H_&P,L"0Y$T7N#WVM[AM-:O]T>&J@U;"# %$\^&! +M0^)IR86P %$\^&!0^)IR86P(-[((5-&#H@T;D#<09-F#!H0=-"4 :%#!P@Y +M==B4F0,BC)PR"D"('$FRY!PX9<:D,9.F#!F%:2(BA"@11)LP:\JPU-C1S5*#F^,1.PJ4$Z'L^4H3/'A8*D2T',<#$R"=4P +M$+-NO9AQXI@W;K BY-@4!)@0)VR^(;.RI1P6-,NX 1N69-VG:5 >Y(A2CAF! +M;5R"F%,F3AW!=-(,99,'Q..K-=FDF4.'<&&14P/6H4,F#!W)<#Y^M#PZYL:> +M/Q,&E;.YC-$[,1\V-7T:<=2 5-]832M'*U>OQ$G2("O2;$?FSD&@"4.WIHLI +M1:)4*>*$2I(@3#K2H2,GC9C5$RG3"3SX=,G-R ]R!1&[8.4ZM;W&D4<3W430 +M9/]AIAE1>407UD=LN):&'1/1\49 ;DP4AAO*2600"MP=1%4306 !A11/#%'$ +M%%/T$$,*@+U7VE<*6%'0'&G )98+.( !1,QV*=4%5<(::1T-"C (T*$$'B +M$D6@ $<*1E;AQAQUP &'0*^]9,1'$TTQ%1UW$"BDDT% *64*3!YYD&Y"$>7; +M40]U6!!V6W$T4UTWY;13&="5Y(1R95@$@G5YO%''9"BI9$9G:.W6FU%]5BA1 +M0G4)1)!!J6$E1PNF99=E:Z_A%EA ]TYTT(-"5<3=W.\H9)KDAEW&X&F(63' +M&SF]!!Q1(' XWUMR?'027"]92)-K(/!U4H1Y2"9&9W6U4!])9D1X!G1#(##$ +M$P@\X00"3A"! !%)() $%0B8IRZXXI(;! +H(<#$% A,81H9")#1!@(W(8 3 +M CDA$%^66\JQ'UJ5_@G"6U>R5\<8P_;V$EI?(#!&QF]D[$;&9&2<1L9TB,RQ +MQQF'D3$;7I64Q'R;O7%'=Q/50=E5%T+,5V9P;=8991I1S!^7.5Z)G&D-I\'3 +M:WC,]]F;<*S&GQRR;H2C&V>8JJRS8WCTDIT&)0QJ23Q?21T5#'$D1DIO1,:1 +MS3IEY)E "K67&=8VX:23TK=%Q"RN)2'TFD^2*6M&'6Y07/3F/4:4 +MS'/H\-5I+B1AA$@9EY$Q'AG#D;$9!H^Z>U/,9(:6JYV!I[0L(.H4YVQ6I<0%@9+.:8Y +M2>3:D)',P($G2=-(5P@XDO(1#P'&0P#RPH>^.H[,>1Y[6.1"")>)=*HFMF.# +MS!"2M8B B7%MR!T;E\(#%?H !'P 02.O]\@>]$"2CH0D)BD)@A!<*AB9#,C21;#.J"95]8M+D,NT2@(0O@?6B7K0FA9:4LG,UBL-?%2!"6G?B 2T9J$U8_U +MK$DL9TD"%&B6"3<42184I_2A(;@(!D0)L)!K40$E,0I.: +MIE2E*R&,2Y+Y4AG"-*8R0= ^"H[2E-I4F-B./EV,0,8E' +M#((67,C#;%MH.#%)QI!B&[?X0B0 OY*?"&+E/C&+LBQFW@\ +M61>DV,4@"/(H<4G3CW!.41QAKWNG]F%5?B29&.),]6:,69^\0""F(;(J%36? +MU)!J(L")2%I/DI)VOK@Y;:AF_PB"$L(EKB5SF.$>XX,5$AY7IW\&&@@[8[.V +MU@4A9O!/XIS2ED"7A" LR5!N3O5.GWB-L_#,DF?XAE9,AZ&,;.')9Y"&D[:. +M^ 0<,0/50.QD6(- D+SB2*PB(Q.\B28G-!F-[O!7 AJ#H-ACV,'#GISBU@[! +M"$P(PA&F0"4H!SG*/!CE%!!"4JM,)'6C65BJ)X("3"-$,GNJR3L5)NH_46G5 +M)>F3J]]@:UFW+7YCL#6__ 6P, AL#00K@\%@ BS<2G3<,[V)&^I@AI%N%2)U +M: _>T,)B>X.8XCW^X1W<$CDZ.ZHSBC((G^)3G/30(M)(AWOPF#-2ZT!R0?JHPS)5"]75T +M33)TA\7.G*+2O)(V%:(H-@"T4*,LR12D, 007!(M8L#?$X2@!+.#8 ^M'?L0 +M4M '$^,/QB%N[=J5P*8EVSS*0,!VV$FB=[93R>=)GC)5-JZ0#=D9!#DI QQ. +M]08QJ*'.>H(A@B15*KX\Q4)RR ,+!"VGKUG>\\L$+>/?FA%?V2T^;=M*1[/V +M:TN-IN5AD;O;T:YVMKL=[BB0.]WM?AJ\6Z3P?*>Y2)B<\Q\#?O C0?[AAY[X +MTQ2[R,=VLO*CC((AS+W%S>X^M*5-;>>W%@@Z, .5791JQL1<3%.0,Q]& +MY!#YX4XA1U)_DGE55E$:9!I8ED7M)8':$087-!%@H -YX1!"03&J E1ET#EX +M,A]N((6()1(&E!"KUW6N%U)UX71O '41R!/<,6QI2'9PZ!DZ@!9FH -I=QIN +M^(UR:(Z5Z'8B@(=Q1W94PHXMQ0Q0!97F95;V95?&98N,)9E"6RGR"4<\2LOX4\O\2?+ +M&!DTUTP,M3A/TQ^S 2 X4BI]N1&B8S-CUBR=DQ(/%Q:@UT)P\4(#DF0QDF2F +M,@:821_7(1H9J$=P8VE"8IQ("7!* +M25^4X1&L6!?HZ1&=\31\TH%WDIB98R3*,BIWI9_ND9X0D5Z$EHL)I2=2X0:< +M07/I)8&@0T+I-A'@*94H"!?4T018^0138"HR9"13R47(Q'16M1U0MY_MP5#+ +M,A^1-WD.DQE^:23O1$QS4$$#,F>H)I_^EI0"5R'D*1$T(YH9R)^CIA$4RA6^ +M808^]!*Q(3@]:F%N0$C0<8)4J2,JZ",L&& N^(*%00,W,(-?48,,)B16\IPD +M)&$4YH,6-A%!F"9#R&$C :3(69]5I1RA)2%BP!-Q]A!'L%)D:98_Q1_PU! 9 +M<40QL2_,R1%6A3B;TFDO,:A54*@Y86O 14N!.5PQ"@*641"[9!A!Q1-SD >D +MH59GV2S]TF:*!9I%%9R#5E_H%C%&1$^G0IQ)X 1#P 150 1% +M0!'S:%(20S$T)ZDW8B%[,5F=@:=":C"K6A+TE%0ZTEK +MI0/$U0-8(@94 DU&HK#[Q; 7\T.O\Q\3,A2805_,I$5Z!1MQ*=T0+GE;0Z +MU0:1N10*]Q+RZIDEJTI6!;KEA#]C8;%6=VRJ9&Z:1E\A=&UK2Q8D4 *5$:PA%!=D.*.!W&VZS 2J=?5#:4FZ &=1NOLQT^H1%D0'/$\GF< +M,;$D40-D<4Y%N3=7BC>Q>SJ>XARQ1C>/Y@8_67+S:A\8087A5!?B^ZS]:Q3_ +MNQ;L2P:@F34H*R2"L9.% UKNU"@+DHSQTY4O2QLP-;,68KTU40(MD, 3(0+2 +M:Q'%A@7$J8@V0!9$\)@4(Q" UA$VR09E@JJK.Q&N2UNQ^R@MA@"T2R\/2J$< +M85+A-K-$"S8"UI8 -DD<6Q^*FI*QIZ,!&YJQ1ME1I2','[H:T(&"+-5&?H1A4-3*=\Z\%GW!P2;$$5_+G+>*MD0!U& +M(+EXD(L:P;5N8@1DISLOV ;3237;@GV4_(7;$GZ0_'W*)C\T=P4"L08#DF6J +M@\<_016ONQA8,E##M+MIJQ0G +&P.G"T2U9DUP.=? *Q_%$-IS1W&1S7,)*Q]WPZS.2JJP MZ3WJ(I(OV2[XHB\N +MDQ"[5K=E#!<7>J0:@35R%E@PU!QU<*%MVU87/!)&VQ[$>,AJ"RC;0I8A.J*O +M'$Z]FQ4MC1E-O"%6M3:F(4A8TTKL"P(Q( ,],BUC-<2+8B:-AC?N])2M,1 S +MU#:[ZV3WUM,N&Q<%T1^%6X4@\+H&L5N^P0: 0'!=DQ AY#@4LI=EV$>HXP8C_3DF?'4D$4/+49B/J6NQQSBRIRAG@ 9T<$MP +MDDUC@+5G35M..U$DH;S;:W4# BP1<3FVAS4-M4),%T(]6,5)*4SI]H[0)R :3=\(F0:SS,=FE@S<-I,&5'8N +M\101AR-0!UP#XA-;[1.ETS-&H;5][8PU(=]46=\[NZ,=H:R20UK[HK\BW3DD +M/;,0PQ)7RQL.]*DQ4W7++6F\/1*;X^"D'11MPW!@2PK^H +M^AJ)A,C03!+9.%!+%QF5/1FRE!@5H]DU0QE[23>ZRJNFLI9I)C5$F^% B=P0 +MU2SZN]]F,TJ173?^CKM?:N3-903EA ;&DX@2@0B:AJJ;2R3U2'0 +MZAK3JFO<)L0PQ :.@SGX050BF +MP9I34WD["4(301N=MQ+,O;1M+DSIZG3?G1DH;@:?1:3)&J&HTX\/U5$: D%( +MCAG4<<,^J>' ?>A9N.4BY!*%S#> D4:,NV[2"@^BEQ&GOVFY6/AI$V-'A%5[F12\7W='P$D9H@ (O AACL%OT#B.D-3'S7N^> +M<0,WD.^ 0=C(/#+EN^F,06]0Q9&X!O:GA":NUTIDS%K$#P1WP(1?UX9 P7D +M@T<(< 8=KS( $_%F<#)R%/%-,/'=BC((4#("TSP?L_+0DS%9DS%#8/)M,#Z< +MV_+E8Q ;W_'/\W T'_(9D_/F\Q78504(4 4FB00(@ 2"3=BF002"<:4<806\ +M&'%A !A#,*)4+T'=>:4G&A,@1Q570"MR@&O-V"P6109:#P1EPAJ\<08>6@=Q +M7Q!JWS7,OB'4PKZD3%]#X!%&,05EH!4&\31I,]YP,*O#>@9:<;K#%:5-="%4 +M8&5THP1O@ 8)@3;CU%,SE?@*UQFILTYRTMQI0! A8D&Y0L"0(2%0]QY9\Q$- +MM$8*@-A"H/2_B@#3-EYBU]JGFJH@!M9DP!$?(:URD! !FJ'OS3=4HBS76!##-%#+K:AL8.*K +M*B8V_OLNKD\Y63EA@(U_)68CQ>LXHN4VVJ ZRCA'C;X;N)X>R!$H$.8B"AC9 +ME01'$ 2 L15C\&X";*03X=;U^9ZD2S8,"FK$U(JA@;X;.!>OP8NF,J4@?AU6 +M*G4@02/XG((\XJ4 YB9AZL]*00,Y$- .?8/HG= 3!@(]^(,7UM #O6%%B"U" +MU4X,.EK+>1NQ\J!^"^>7 S,^C'12L0: ,?J2M^%E>%3$;PNNCA>67T_]+BNV3]?>*N)U)AC\#4J;KXQ+1*-\1F1 +MT;(OT0)^9! M,+!O($&JRX6K>OTP+=;'?SKV/:RL&"+?T@0D4B[/SG23;40( +MR**R(B*F8ED +L2: +#include "extern.h" + +PUBLIC int +_chdir(path) +char *path; +{ + int res; + + res = chdir(path); + +#if defined(OS2) + if (res != -1 && path[1] == ':') { + unsigned new_drive; + unsigned max_drives; + + /* for OS2 we must change drive without using intdos() */ + new_drive = (*path & ~0x20) - 'A' + 1; + _dos_setdrive(new_drive, &max_drives); + } +#else + 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'; + intdos(®, ®); + } +#endif /* OS2 */ + return (res); +} + diff --git a/dmake/msdos/arlib.c b/dmake/msdos/arlib.c new file mode 100644 index 0000000..76aa523 --- /dev/null +++ b/dmake/msdos/arlib.c @@ -0,0 +1,65 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/arlib.c,v 1.1 1992/01/24 03:27:23 dvadura Exp $ +-- SYNOPSIS -- Library access code. +-- +-- DESCRIPTION +-- This implementation uses the library timestamp inplace of the +-- library member timestamp. +-- +-- 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. +-- +-- LOG +-- $Log: arlib.c,v $ + * Revision 1.1 1992/01/24 03:27:23 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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)); +} + +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/bccdos/config.h b/dmake/msdos/bccdos/config.h new file mode 100644 index 0000000..ea7e630 --- /dev/null +++ b/dmake/msdos/bccdos/config.h @@ -0,0 +1,54 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/bccdos/config.h,v 1.1 1992/01/24 03:27:46 dvadura 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@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. +-- +-- LOG +-- $Log: config.h,v $ + * Revision 1.1 1992/01/24 03:27:46 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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 * diff --git a/dmake/msdos/bccdos/config.mk b/dmake/msdos/bccdos/config.mk new file mode 100644 index 0000000..e33a290 --- /dev/null +++ b/dmake/msdos/bccdos/config.mk @@ -0,0 +1,50 @@ +# 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) + +# Definition of macros for library, and C startup code. +LDLIBS = d:/cc/bcc/lib/c$(MODEL) +CSTARTUP = d:/cc/bcc/lib/c0$(MODEL).obj + +# 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/bccdos/lib.rsp b/dmake/msdos/bccdos/lib.rsp new file mode 100644 index 0000000..9e9e950 --- /dev/null +++ b/dmake/msdos/bccdos/lib.rsp @@ -0,0 +1 @@ +d:\cc\bcc\lib\cl diff --git a/dmake/msdos/bccdos/libswp.rsp b/dmake/msdos/bccdos/libswp.rsp new file mode 100644 index 0000000..9e9e950 --- /dev/null +++ b/dmake/msdos/bccdos/libswp.rsp @@ -0,0 +1 @@ +d:\cc\bcc\lib\cl diff --git a/dmake/msdos/bccdos/mk.bat b/dmake/msdos/bccdos/mk.bat new file mode 100644 index 0000000..52836a4 --- /dev/null +++ b/dmake/msdos/bccdos/mk.bat @@ -0,0 +1,96 @@ +md objects +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml infer.c +copy infer.obj objects +del infer.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml make.c +copy make.obj objects +del make.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml stat.c +copy stat.obj objects +del stat.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml expand.c +copy expand.obj objects +del expand.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml dmstring.c +copy dmstring.obj objects +del dmstring.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml hash.c +copy hash.obj objects +del hash.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml dag.c +copy dag.obj objects +del dag.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml dmake.c +copy dmake.obj objects +del dmake.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml path.c +copy path.obj objects +del path.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml imacs.c +copy imacs.obj objects +del imacs.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml sysintf.c +copy sysintf.obj objects +del sysintf.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml parse.c +copy parse.obj objects +del parse.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml getinp.c +copy getinp.obj objects +del getinp.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml quit.c +copy quit.obj objects +del quit.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml state.c +copy state.obj objects +del state.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml basename.c +copy basename.obj objects +del basename.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml dmdump.c +copy dmdump.obj objects +del dmdump.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml macparse.c +copy macparse.obj objects +del macparse.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml rulparse.c +copy rulparse.obj objects +del rulparse.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml percent.c +copy percent.obj objects +del percent.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml function.c +copy function.obj objects +del function.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\ruletab.c +copy ruletab.obj objects +del ruletab.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\dirbrk.c +copy dirbrk.obj objects +del dirbrk.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\runargv.c +copy runargv.obj objects +del runargv.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\arlib.c +copy arlib.obj objects +del arlib.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\_chdir.c +copy _chdir.obj objects +del _chdir.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\switchar.c +copy switchar.obj objects +del switchar.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\rmprq.c +copy rmprq.obj objects +del rmprq.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\tee.c +copy tee.obj objects +del tee.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\bccdos\tempnam.c +copy tempnam.obj objects +del tempnam.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\bccdos\utime.c +copy utime.obj objects +del utime.obj +copy msdos\bccdos\startup.mk startup.mk +tlink @msdos\bccdos\obj.rsp,dmake.exe,NUL.MAP,@msdos\bccdos\lib.rsp diff --git a/dmake/msdos/bccdos/mkswp.bat b/dmake/msdos/bccdos/mkswp.bat new file mode 100644 index 0000000..5b7460f --- /dev/null +++ b/dmake/msdos/bccdos/mkswp.bat @@ -0,0 +1,101 @@ +md objects +tasm -t -mx -dmlarge msdos\exec.asm; +mv exec.obj objects +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml infer.c +copy infer.obj objects +del infer.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml make.c +copy make.obj objects +del make.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml stat.c +copy stat.obj objects +del stat.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml expand.c +copy expand.obj objects +del expand.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml dmstring.c +copy dmstring.obj objects +del dmstring.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml hash.c +copy hash.obj objects +del hash.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml dag.c +copy dag.obj objects +del dag.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml dmake.c +copy dmake.obj objects +del dmake.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml path.c +copy path.obj objects +del path.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml imacs.c +copy imacs.obj objects +del imacs.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml sysintf.c +copy sysintf.obj objects +del sysintf.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml parse.c +copy parse.obj objects +del parse.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml getinp.c +copy getinp.obj objects +del getinp.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml quit.c +copy quit.obj objects +del quit.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml state.c +copy state.obj objects +del state.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml basename.c +copy basename.obj objects +del basename.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml dmdump.c +copy dmdump.obj objects +del dmdump.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml macparse.c +copy macparse.obj objects +del macparse.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml rulparse.c +copy rulparse.obj objects +del rulparse.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml percent.c +copy percent.obj objects +del percent.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml function.c +copy function.obj objects +del function.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\ruletab.c +copy ruletab.obj objects +del ruletab.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\dirbrk.c +copy dirbrk.obj objects +del dirbrk.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\runargv.c +copy runargv.obj objects +del runargv.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\arlib.c +copy arlib.obj objects +del arlib.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\_chdir.c +copy _chdir.obj objects +del _chdir.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\switchar.c +copy switchar.obj objects +del switchar.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\rmprq.c +copy rmprq.obj objects +del rmprq.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\find.c +copy find.obj objects +del find.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\spawn.c +copy spawn.obj objects +del spawn.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\bccdos\tempnam.c +copy tempnam.obj objects +del tempnam.obj +bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\bccdos\utime.c +copy utime.obj objects +del utime.obj +copy msdos\bccdos\startup.mk startup.mk +tlink @msdos\bccdos\objswp.rsp,dmake.exe,NUL.MAP,@msdos\bccdos\libswp.rsp diff --git a/dmake/msdos/bccdos/obj.rsp b/dmake/msdos/bccdos/obj.rsp new file mode 100644 index 0000000..685ff98 --- /dev/null +++ b/dmake/msdos/bccdos/obj.rsp @@ -0,0 +1,32 @@ +d:\cc\bcc\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\basename.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\_chdir.obj+ +objects\switchar.obj+ +objects\rmprq.obj+ +objects\tee.obj+ +objects\tempnam.obj+ +objects\utime.obj diff --git a/dmake/msdos/bccdos/objswp.rsp b/dmake/msdos/bccdos/objswp.rsp new file mode 100644 index 0000000..b5e48f8 --- /dev/null +++ b/dmake/msdos/bccdos/objswp.rsp @@ -0,0 +1,34 @@ +d:\cc\bcc\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\basename.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\_chdir.obj+ +objects\switchar.obj+ +objects\rmprq.obj+ +objects\find.obj+ +objects\spawn.obj+ +objects\tempnam.obj+ +objects\utime.obj diff --git a/dmake/msdos/bccdos/public.h b/dmake/msdos/bccdos/public.h new file mode 100644 index 0000000..fe5e0c8 --- /dev/null +++ b/dmake/msdos/bccdos/public.h @@ -0,0 +1,152 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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 _chdir ANSI((char *)); +void Remove_prq ANSI((CELLPTR)); +void Hook_std_writes ANSI((char *)); + +#endif diff --git a/dmake/msdos/bccdos/startup.mk b/dmake/msdos/bccdos/startup.mk new file mode 100644 index 0000000..34bd7e6 --- /dev/null +++ b/dmake/msdos/bccdos/startup.mk @@ -0,0 +1,154 @@ +# MSDOS DMAKE startup file. Customize to suit your needs. +# Assumes MKS toolkit for the tool commands, and Turbo-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 := bcc # C-compiler and flags + CFLAGS += + + AS := tasm # Assembler and flags + ASFLAGS += + + LD = tlink # Loader and flags + LDFLAGS += + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(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 := tpc # 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 .SWAP: %.c ; $(CC) $(CFLAGS) -c $< + %$O .SWAP: %$P ; $(PC) $(PFLAGS) -c $< + %$O .SWAP: %$S ; $(AS) $(ASFLAGS) $(<:s,/,\); + %$O : %.cl ; class -c $< + %$O .SWAP: %.e %.r %.F %$F ; $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $< + +# Executables + %$E .SWAP: %$O ; $(CC) $(LDFLAGS) -e$@ $< + +# lex and yacc rules + %.c .SWAP: %.y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@ + %.c .SWAP: %.l ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@ + +# RCS support +.IF $(_HAVE_RCS) + % : $$(@:d)RCS/$$(@:f)$V;- $(CO) $(COFLAGS) $@ + .NOINFER : $$(@:d)RCS/$$(@:f)$V +.END + +# SCCS support +.IF $(_HAVE_SCCS) + % : s.% ; get $< + .NOINFER : s.% +.END + +# Recipe to make archive files. +%$A .SWAP: +[ + $(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) + +#include +#include +#include + +#if defined(max) +# undef max +#endif +#define max(A,B) (((A)<(B))?(B):(A)) + +extern char *mktemp(); +extern int access(); +int _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); + if( dir != NULL ) dl = strlen(dir); + + if( (p = malloc((unsigned)(max(max(dl,tl),pl)+13))) == NULL ) + return(NULL); + + *p = '\0'; + + if( (tl == 0) || (_access( strcpy(p, tmpdir), 0) != 0) ) + if( (dl == 0) || (_access( strcpy(p, dir), 0) != 0) ) + if( _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); +} + + + +_access( name, flag ) +char *name; +int flag; +{ + 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, "/" ); + + return( r ); +} diff --git a/dmake/msdos/bccdos/utime.c b/dmake/msdos/bccdos/utime.c new file mode 100644 index 0000000..60bf6b6 --- /dev/null +++ b/dmake/msdos/bccdos/utime.c @@ -0,0 +1,42 @@ +/* +** change access and modify times of file +*/ +#include +#include +#include + +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 0000000..239b52c --- /dev/null +++ b/dmake/msdos/config.mk @@ -0,0 +1,68 @@ +# 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) @$(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) + +# 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/ztcdos/config.mk. +SWAP *= y +.IF $(OSRELEASE) != ztcdos + .IF $(SWAP) == y + SWP_SRC = find.c 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 _chdir.c switchar.c rmprq.c\ + $(SWP_SRC) +SRC += $(OS_SRC) +.SETDIR=$(OS) : $(ASRC) $(OS_SRC) + +# Provide our own %$O : %$S rule. +%$O : %$S + $(AS) $(ASFLAGS) $(<:s,/,\,); + 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/dirbrk.c b/dmake/msdos/dirbrk.c new file mode 100644 index 0000000..34c4df6 --- /dev/null +++ b/dmake/msdos/dirbrk.c @@ -0,0 +1,51 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/dirbrk.c,v 1.1 1992/01/24 03:27:29 dvadura 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@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. +-- +-- LOG +-- $Log: dirbrk.c,v $ + * Revision 1.1 1992/01/24 03:27:29 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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/dirlib.h b/dmake/msdos/dirlib.h new file mode 100644 index 0000000..f9c7769 --- /dev/null +++ b/dmake/msdos/dirlib.h @@ -0,0 +1,42 @@ +/* DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89 */ + +#ifndef _DIRLIB_h_ +#define _DIRLIB_h_ + +#include +#include "stdmacs.h" + +#define MAXNAMLEN 15 + +struct direct { + long d_ino; + unsigned short d_reclen; + unsigned short d_namlen; + char d_name[MAXNAMLEN+1]; +}; + +typedef struct { + char fcb[21]; + char attr; + short time; + short date; + long size; + char name[13]; +} DTA; + +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 direct *readdir ANSI((DIR *)); +extern long telldir ANSI((DIR *)); +extern void seekdir ANSI((DIR *, long)); +extern void closedir ANSI((DIR *)); +extern DTA *findfirst ANSI((char *, DTA *)); +extern DTA *findnext ANSI((DTA *)); + +#define rewinddir(dirp) seekdir(dirp,0L) +#endif diff --git a/dmake/msdos/exec.asm b/dmake/msdos/exec.asm new file mode 100644 index 0000000..db745ae --- /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 +a_prog equ +a_tail equ +a_env equ +a_tmp equ + +a_handle equ + + +; 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 0000000..21dffb1 --- /dev/null +++ b/dmake/msdos/exec.h @@ -0,0 +1,19 @@ +#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 0000000..0859c74 --- /dev/null +++ b/dmake/msdos/exec.uue @@ -0,0 +1,63 @@ +begin 600 exec.obj +M@! #DU31$]37&5X96,N87-M;(@@ '%1U0# 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 &5C.B!& +M86EL=7)E(')E861I;F<@F4-"B1E>&5C.B!&86EL=7)E('1O(&9R964@82!B;&]C:PT*)&5X +M96,Z(%!R;V=R86T@!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�$ 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"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 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",QT7W(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 <-5 ''HE0!QZE4 <>T5 ''N%0!Q\-4 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-O (NC :^ KJS [@C)C #HU?TNQ1:\ K@C) +M7C ".PR;$'C0 )HI' 2ZBTP$FB@$NHM(! +MN"$US2$NB1[, 2Z,!LX!'HS(CMBZV *X(27-(1]?7+L46S &,V O"= FX +M(26<+O\>S $?RPJ +#include +#include +#include +#include +#include +#include "dirlib.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 _err; +static DTA far *_getsetdta ANSI((DTA far *)); + +/* + * 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); + _err = r.x.ax; + if (r.x.cflag) + return (DTA *) 0; + + 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); + _err = r.x.ax; + if (r.x.cflag) + return (DTA *) 0; + + return dta; +} diff --git a/dmake/msdos/mscdos/config.h b/dmake/msdos/mscdos/config.h new file mode 100644 index 0000000..5628595 --- /dev/null +++ b/dmake/msdos/mscdos/config.h @@ -0,0 +1,83 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/mscdos/config.h,v 1.1 1992/01/24 03:27:25 dvadura 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@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. +-- +-- LOG +-- $Log: config.h,v $ + * Revision 1.1 1992/01/24 03:27:25 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 + +/* 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 * diff --git a/dmake/msdos/mscdos/config.mk b/dmake/msdos/mscdos/config.mk new file mode 100644 index 0000000..f06fc35 --- /dev/null +++ b/dmake/msdos/mscdos/config.mk @@ -0,0 +1,93 @@ +# 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) + +# Local configuration modifications for CFLAGS +# If you have a 286 or better, you can uncomment the following line. +#HAVE_286 = y + +.IF $(HAVE_286) + CFLAGS += -G2 + ASFLAGS += -Dhave286 +.END + +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 4.0, 5.0, 5.1, or 6.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. + +.IMPORT .IGNORE : MSC_VER +MSC_VER *= 6.0 # If unset, assume 6.0 by default. + +.IF $(MSC_VER) == 4.0 + CFLAGS += -I$(osrdir) $(C_$(MODEL):s/A/m/) + CFLAGS += -DM_I86=1 # 5.0+ define this automatically +# CFLAGS += -D__STDC__=1 # 5.0, 5.1, but not 6.0 do this automatically + NDB_CFLAGS += + DB_CFLAGS += -Zi +.ELSE + DB_CFLAGS += -Zi + CFLAGS += -I$(osrdir) $(C_$(MODEL)) + .IF $(MSC_VER) != 6.0 + # For 5.0 and 5.1, we define _MSC_VER=500 or 510 + CFLAGS += -D_MSC_VER=$(MSC_VER:s,.,,)0 + NDB_CFLAGS += -Oscl -Gs + .ELSE + # Microsoft C 6.0 auto defines _MSC_VER=600, but not __STDC__ + CFLAGS += -D__STDC__=1 # incredibly not auto done by 6.0 + NDB_CFLAGS += -Osecgl -Gs + + # Redefine rule for making our objects, we don't need mv + %$O : %.c ;% $(CC) -c $(CFLAGS) -Fo$@ $< + .END + NDB_LDFLAGS += /exe /packc /batch + NDB_LDLIBS += +.END + +# 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/mscdos/lib.rsp b/dmake/msdos/mscdos/lib.rsp new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/dmake/msdos/mscdos/lib.rsp @@ -0,0 +1 @@ + diff --git a/dmake/msdos/mscdos/libswp.rsp b/dmake/msdos/mscdos/libswp.rsp new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/dmake/msdos/mscdos/libswp.rsp @@ -0,0 +1 @@ + diff --git a/dmake/msdos/mscdos/mk40.bat b/dmake/msdos/mscdos/mk40.bat new file mode 100644 index 0000000..228c791 --- /dev/null +++ b/dmake/msdos/mscdos/mk40.bat @@ -0,0 +1,93 @@ +md objects +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 infer.c +copy infer.obj objects +del infer.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 make.c +copy make.obj objects +del make.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 stat.c +copy stat.obj objects +del stat.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 expand.c +copy expand.obj objects +del expand.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 dmstring.c +copy dmstring.obj objects +del dmstring.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 hash.c +copy hash.obj objects +del hash.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 dag.c +copy dag.obj objects +del dag.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 dmake.c +copy dmake.obj objects +del dmake.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 path.c +copy path.obj objects +del path.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 imacs.c +copy imacs.obj objects +del imacs.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 sysintf.c +copy sysintf.obj objects +del sysintf.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 parse.c +copy parse.obj objects +del parse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 getinp.c +copy getinp.obj objects +del getinp.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 quit.c +copy quit.obj objects +del quit.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 state.c +copy state.obj objects +del state.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 basename.c +copy basename.obj objects +del basename.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 dmdump.c +copy dmdump.obj objects +del dmdump.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 macparse.c +copy macparse.obj objects +del macparse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 rulparse.c +copy rulparse.obj objects +del rulparse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 percent.c +copy percent.obj objects +del percent.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 function.c +copy function.obj objects +del function.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\ruletab.c +copy ruletab.obj objects +del ruletab.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\dirbrk.c +copy dirbrk.obj objects +del dirbrk.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\runargv.c +copy runargv.obj objects +del runargv.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\arlib.c +copy arlib.obj objects +del arlib.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\_chdir.c +copy _chdir.obj objects +del _chdir.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\switchar.c +copy switchar.obj objects +del switchar.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\rmprq.c +copy rmprq.obj objects +del rmprq.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\tee.c +copy tee.obj objects +del tee.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\mscdos\tempnam.c +copy tempnam.obj objects +del tempnam.obj +copy msdos\mscdos\startup.mk startup.mk +link /stack:4096 @msdos\mscdos\obj.rsp,dmake.exe,NUL.MAP; diff --git a/dmake/msdos/mscdos/mk40swp.bat b/dmake/msdos/mscdos/mk40swp.bat new file mode 100644 index 0000000..3521d3b --- /dev/null +++ b/dmake/msdos/mscdos/mk40swp.bat @@ -0,0 +1,98 @@ +md objects +masm -t -mx -Dmlarge msdos\exec.asm; +mv exec.obj objects +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 infer.c +copy infer.obj objects +del infer.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 make.c +copy make.obj objects +del make.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 stat.c +copy stat.obj objects +del stat.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 expand.c +copy expand.obj objects +del expand.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 dmstring.c +copy dmstring.obj objects +del dmstring.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 hash.c +copy hash.obj objects +del hash.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 dag.c +copy dag.obj objects +del dag.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 dmake.c +copy dmake.obj objects +del dmake.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 path.c +copy path.obj objects +del path.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 imacs.c +copy imacs.obj objects +del imacs.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 sysintf.c +copy sysintf.obj objects +del sysintf.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 parse.c +copy parse.obj objects +del parse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 getinp.c +copy getinp.obj objects +del getinp.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 quit.c +copy quit.obj objects +del quit.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 state.c +copy state.obj objects +del state.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 basename.c +copy basename.obj objects +del basename.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 dmdump.c +copy dmdump.obj objects +del dmdump.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 macparse.c +copy macparse.obj objects +del macparse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 rulparse.c +copy rulparse.obj objects +del rulparse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 percent.c +copy percent.obj objects +del percent.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 function.c +copy function.obj objects +del function.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\ruletab.c +copy ruletab.obj objects +del ruletab.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\dirbrk.c +copy dirbrk.obj objects +del dirbrk.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\runargv.c +copy runargv.obj objects +del runargv.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\arlib.c +copy arlib.obj objects +del arlib.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\_chdir.c +copy _chdir.obj objects +del _chdir.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\switchar.c +copy switchar.obj objects +del switchar.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\rmprq.c +copy rmprq.obj objects +del rmprq.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\find.c +copy find.obj objects +del find.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\spawn.c +copy spawn.obj objects +del spawn.obj +cl -c -I. -Imsdos -Imsdos\mscdos -mL -DM_I86=1 msdos\mscdos\tempnam.c +copy tempnam.obj objects +del tempnam.obj +copy msdos\mscdos\startup.mk startup.mk +link /stack:4096 @msdos\mscdos\objswp.rsp,dmake.exe,NUL.MAP; diff --git a/dmake/msdos/mscdos/mk50.bat b/dmake/msdos/mscdos/mk50.bat new file mode 100644 index 0000000..983adf4 --- /dev/null +++ b/dmake/msdos/mscdos/mk50.bat @@ -0,0 +1,93 @@ +md objects +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs infer.c +copy infer.obj objects +del infer.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs make.c +copy make.obj objects +del make.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs stat.c +copy stat.obj objects +del stat.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs expand.c +copy expand.obj objects +del expand.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs dmstring.c +copy dmstring.obj objects +del dmstring.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs hash.c +copy hash.obj objects +del hash.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs dag.c +copy dag.obj objects +del dag.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs dmake.c +copy dmake.obj objects +del dmake.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs path.c +copy path.obj objects +del path.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs imacs.c +copy imacs.obj objects +del imacs.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs sysintf.c +copy sysintf.obj objects +del sysintf.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs parse.c +copy parse.obj objects +del parse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs getinp.c +copy getinp.obj objects +del getinp.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs quit.c +copy quit.obj objects +del quit.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs state.c +copy state.obj objects +del state.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs basename.c +copy basename.obj objects +del basename.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs dmdump.c +copy dmdump.obj objects +del dmdump.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs macparse.c +copy macparse.obj objects +del macparse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs rulparse.c +copy rulparse.obj objects +del rulparse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs percent.c +copy percent.obj objects +del percent.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs function.c +copy function.obj objects +del function.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\ruletab.c +copy ruletab.obj objects +del ruletab.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\dirbrk.c +copy dirbrk.obj objects +del dirbrk.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\runargv.c +copy runargv.obj objects +del runargv.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\arlib.c +copy arlib.obj objects +del arlib.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\_chdir.c +copy _chdir.obj objects +del _chdir.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\switchar.c +copy switchar.obj objects +del switchar.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\rmprq.c +copy rmprq.obj objects +del rmprq.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\tee.c +copy tee.obj objects +del tee.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\mscdos\tempnam.c +copy tempnam.obj objects +del tempnam.obj +copy msdos\mscdos\startup.mk startup.mk +link /stack:4096 /exe /packc /batch @msdos\mscdos\obj.rsp,dmake.exe,NUL.MAP; diff --git a/dmake/msdos/mscdos/mk50swp.bat b/dmake/msdos/mscdos/mk50swp.bat new file mode 100644 index 0000000..159196f --- /dev/null +++ b/dmake/msdos/mscdos/mk50swp.bat @@ -0,0 +1,98 @@ +md objects +masm -t -mx -Dmlarge msdos\exec.asm; +mv exec.obj objects +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs infer.c +copy infer.obj objects +del infer.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs make.c +copy make.obj objects +del make.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs stat.c +copy stat.obj objects +del stat.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs expand.c +copy expand.obj objects +del expand.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs dmstring.c +copy dmstring.obj objects +del dmstring.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs hash.c +copy hash.obj objects +del hash.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs dag.c +copy dag.obj objects +del dag.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs dmake.c +copy dmake.obj objects +del dmake.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs path.c +copy path.obj objects +del path.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs imacs.c +copy imacs.obj objects +del imacs.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs sysintf.c +copy sysintf.obj objects +del sysintf.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs parse.c +copy parse.obj objects +del parse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs getinp.c +copy getinp.obj objects +del getinp.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs quit.c +copy quit.obj objects +del quit.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs state.c +copy state.obj objects +del state.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs basename.c +copy basename.obj objects +del basename.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs dmdump.c +copy dmdump.obj objects +del dmdump.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs macparse.c +copy macparse.obj objects +del macparse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs rulparse.c +copy rulparse.obj objects +del rulparse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs percent.c +copy percent.obj objects +del percent.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs function.c +copy function.obj objects +del function.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\ruletab.c +copy ruletab.obj objects +del ruletab.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\dirbrk.c +copy dirbrk.obj objects +del dirbrk.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\runargv.c +copy runargv.obj objects +del runargv.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\arlib.c +copy arlib.obj objects +del arlib.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\_chdir.c +copy _chdir.obj objects +del _chdir.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\switchar.c +copy switchar.obj objects +del switchar.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\rmprq.c +copy rmprq.obj objects +del rmprq.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\find.c +copy find.obj objects +del find.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\spawn.c +copy spawn.obj objects +del spawn.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=500 -Oscl -Gs msdos\mscdos\tempnam.c +copy tempnam.obj objects +del tempnam.obj +copy msdos\mscdos\startup.mk startup.mk +link /stack:4096 /exe /packc /batch @msdos\mscdos\objswp.rsp,dmake.exe,NUL.MAP; diff --git a/dmake/msdos/mscdos/mk51.bat b/dmake/msdos/mscdos/mk51.bat new file mode 100644 index 0000000..37398bd --- /dev/null +++ b/dmake/msdos/mscdos/mk51.bat @@ -0,0 +1,93 @@ +md objects +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs infer.c +copy infer.obj objects +del infer.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs make.c +copy make.obj objects +del make.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs stat.c +copy stat.obj objects +del stat.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs expand.c +copy expand.obj objects +del expand.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs dmstring.c +copy dmstring.obj objects +del dmstring.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs hash.c +copy hash.obj objects +del hash.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs dag.c +copy dag.obj objects +del dag.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs dmake.c +copy dmake.obj objects +del dmake.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs path.c +copy path.obj objects +del path.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs imacs.c +copy imacs.obj objects +del imacs.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs sysintf.c +copy sysintf.obj objects +del sysintf.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs parse.c +copy parse.obj objects +del parse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs getinp.c +copy getinp.obj objects +del getinp.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs quit.c +copy quit.obj objects +del quit.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs state.c +copy state.obj objects +del state.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs basename.c +copy basename.obj objects +del basename.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs dmdump.c +copy dmdump.obj objects +del dmdump.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs macparse.c +copy macparse.obj objects +del macparse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs rulparse.c +copy rulparse.obj objects +del rulparse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs percent.c +copy percent.obj objects +del percent.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs function.c +copy function.obj objects +del function.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\ruletab.c +copy ruletab.obj objects +del ruletab.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\dirbrk.c +copy dirbrk.obj objects +del dirbrk.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\runargv.c +copy runargv.obj objects +del runargv.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\arlib.c +copy arlib.obj objects +del arlib.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\_chdir.c +copy _chdir.obj objects +del _chdir.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\switchar.c +copy switchar.obj objects +del switchar.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\rmprq.c +copy rmprq.obj objects +del rmprq.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\tee.c +copy tee.obj objects +del tee.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\mscdos\tempnam.c +copy tempnam.obj objects +del tempnam.obj +copy msdos\mscdos\startup.mk startup.mk +link /stack:4096 /exe /packc /batch @msdos\mscdos\obj.rsp,dmake.exe,NUL.MAP; diff --git a/dmake/msdos/mscdos/mk51swp.bat b/dmake/msdos/mscdos/mk51swp.bat new file mode 100644 index 0000000..1deaf9f --- /dev/null +++ b/dmake/msdos/mscdos/mk51swp.bat @@ -0,0 +1,98 @@ +md objects +masm -t -mx -Dmlarge msdos\exec.asm; +mv exec.obj objects +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs infer.c +copy infer.obj objects +del infer.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs make.c +copy make.obj objects +del make.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs stat.c +copy stat.obj objects +del stat.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs expand.c +copy expand.obj objects +del expand.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs dmstring.c +copy dmstring.obj objects +del dmstring.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs hash.c +copy hash.obj objects +del hash.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs dag.c +copy dag.obj objects +del dag.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs dmake.c +copy dmake.obj objects +del dmake.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs path.c +copy path.obj objects +del path.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs imacs.c +copy imacs.obj objects +del imacs.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs sysintf.c +copy sysintf.obj objects +del sysintf.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs parse.c +copy parse.obj objects +del parse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs getinp.c +copy getinp.obj objects +del getinp.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs quit.c +copy quit.obj objects +del quit.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs state.c +copy state.obj objects +del state.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs basename.c +copy basename.obj objects +del basename.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs dmdump.c +copy dmdump.obj objects +del dmdump.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs macparse.c +copy macparse.obj objects +del macparse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs rulparse.c +copy rulparse.obj objects +del rulparse.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs percent.c +copy percent.obj objects +del percent.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs function.c +copy function.obj objects +del function.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\ruletab.c +copy ruletab.obj objects +del ruletab.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\dirbrk.c +copy dirbrk.obj objects +del dirbrk.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\runargv.c +copy runargv.obj objects +del runargv.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\arlib.c +copy arlib.obj objects +del arlib.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\_chdir.c +copy _chdir.obj objects +del _chdir.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\switchar.c +copy switchar.obj objects +del switchar.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\rmprq.c +copy rmprq.obj objects +del rmprq.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\find.c +copy find.obj objects +del find.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\spawn.c +copy spawn.obj objects +del spawn.obj +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D_MSC_VER=510 -Oscl -Gs msdos\mscdos\tempnam.c +copy tempnam.obj objects +del tempnam.obj +copy msdos\mscdos\startup.mk startup.mk +link /stack:4096 /exe /packc /batch @msdos\mscdos\objswp.rsp,dmake.exe,NUL.MAP; diff --git a/dmake/msdos/mscdos/mk60.bat b/dmake/msdos/mscdos/mk60.bat new file mode 100644 index 0000000..4ce222e --- /dev/null +++ b/dmake/msdos/mscdos/mk60.bat @@ -0,0 +1,33 @@ +md objects +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\infer.obj infer.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\make.obj make.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\stat.obj stat.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\expand.obj expand.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\dmstring.obj dmstring.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\hash.obj hash.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\dag.obj dag.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\dmake.obj dmake.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\path.obj path.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\imacs.obj imacs.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\sysintf.obj sysintf.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\parse.obj parse.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\getinp.obj getinp.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\quit.obj quit.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\state.obj state.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\basename.obj basename.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\dmdump.obj dmdump.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\macparse.obj macparse.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\rulparse.obj rulparse.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\percent.obj percent.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\function.obj function.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\ruletab.obj msdos\ruletab.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\dirbrk.obj msdos\dirbrk.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\runargv.obj msdos\runargv.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\arlib.obj msdos\arlib.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\_chdir.obj msdos\_chdir.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\switchar.obj msdos\switchar.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\rmprq.obj msdos\rmprq.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\tee.obj msdos\tee.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\tempnam.obj msdos\mscdos\tempnam.c +copy msdos\mscdos\startup.mk startup.mk +link /stack:4096 /exe /packc /batch @msdos\mscdos\obj.rsp,dmake.exe,NUL.MAP; diff --git a/dmake/msdos/mscdos/mk60swp.bat b/dmake/msdos/mscdos/mk60swp.bat new file mode 100644 index 0000000..836f295 --- /dev/null +++ b/dmake/msdos/mscdos/mk60swp.bat @@ -0,0 +1,36 @@ +md objects +masm -t -mx -Dmlarge msdos\exec.asm; +mv exec.obj objects +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\infer.obj infer.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\make.obj make.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\stat.obj stat.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\expand.obj expand.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\dmstring.obj dmstring.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\hash.obj hash.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\dag.obj dag.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\dmake.obj dmake.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\path.obj path.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\imacs.obj imacs.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\sysintf.obj sysintf.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\parse.obj parse.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\getinp.obj getinp.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\quit.obj quit.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\state.obj state.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\basename.obj basename.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\dmdump.obj dmdump.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\macparse.obj macparse.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\rulparse.obj rulparse.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\percent.obj percent.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\function.obj function.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\ruletab.obj msdos\ruletab.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\dirbrk.obj msdos\dirbrk.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\runargv.obj msdos\runargv.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\arlib.obj msdos\arlib.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\_chdir.obj msdos\_chdir.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\switchar.obj msdos\switchar.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\rmprq.obj msdos\rmprq.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\find.obj msdos\find.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\spawn.obj msdos\spawn.c +cl -c -I. -Imsdos -Imsdos\mscdos -AL -D__STDC__=1 -Osecgl -Gs -Foobjects\tempnam.obj msdos\mscdos\tempnam.c +copy msdos\mscdos\startup.mk startup.mk +link /stack:4096 /exe /packc /batch @msdos\mscdos\objswp.rsp,dmake.exe,NUL.MAP; diff --git a/dmake/msdos/mscdos/obj.rsp b/dmake/msdos/mscdos/obj.rsp new file mode 100644 index 0000000..83533ff --- /dev/null +++ b/dmake/msdos/mscdos/obj.rsp @@ -0,0 +1,30 @@ +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\basename.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\_chdir.obj+ +objects\switchar.obj+ +objects\rmprq.obj+ +objects\tee.obj+ +objects\tempnam.obj diff --git a/dmake/msdos/mscdos/objswp.rsp b/dmake/msdos/mscdos/objswp.rsp new file mode 100644 index 0000000..4912472 --- /dev/null +++ b/dmake/msdos/mscdos/objswp.rsp @@ -0,0 +1,32 @@ +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\basename.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\_chdir.obj+ +objects\switchar.obj+ +objects\rmprq.obj+ +objects\find.obj+ +objects\spawn.obj+ +objects\tempnam.obj diff --git a/dmake/msdos/mscdos/optoff.h b/dmake/msdos/mscdos/optoff.h new file mode 100644 index 0000000..5e9dd09 --- /dev/null +++ b/dmake/msdos/mscdos/optoff.h @@ -0,0 +1,3 @@ +#if _MSC_VER < 600 +# pragma loop_opt(off) +#endif diff --git a/dmake/msdos/mscdos/public.h b/dmake/msdos/mscdos/public.h new file mode 100644 index 0000000..fe5e0c8 --- /dev/null +++ b/dmake/msdos/mscdos/public.h @@ -0,0 +1,152 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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 _chdir ANSI((char *)); +void Remove_prq ANSI((CELLPTR)); +void Hook_std_writes ANSI((char *)); + +#endif diff --git a/dmake/msdos/mscdos/startup.mk b/dmake/msdos/mscdos/startup.mk new file mode 100644 index 0000000..a1ea0f2 --- /dev/null +++ b/dmake/msdos/mscdos/startup.mk @@ -0,0 +1,154 @@ +# MSDOS DMAKE startup file. Customize to suit your needs. +# Assumes MKS toolkit for the tool commands, and Microsoft 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 := cl # C-compiler and flags + CFLAGS += + + AS := masm # Assembler and flags + ASFLAGS += + + LD = link # Loader and flags + LDFLAGS += + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(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 : %$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 : +[ + $(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) + +#include +#include +#include + +#if defined(max) +# undef max +#endif +#define max(A,B) (((A)<(B))?(B):(A)) + +extern char *mktemp(); +extern int access(); +int _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); + if( dir != NULL ) dl = strlen(dir); + + if( (p = malloc((unsigned)(max(max(dl,tl),pl)+13))) == NULL ) + return(NULL); + + *p = '\0'; + + if( (tl == 0) || (_access( strcpy(p, tmpdir), 0) != 0) ) + if( (dl == 0) || (_access( strcpy(p, dir), 0) != 0) ) + if( _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); +} + + + +_access( name, flag ) +char *name; +int flag; +{ + 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, "/" ); + + return( r ); +} diff --git a/dmake/msdos/rmprq.c b/dmake/msdos/rmprq.c new file mode 100644 index 0000000..2dd7fa5 --- /dev/null +++ b/dmake/msdos/rmprq.c @@ -0,0 +1,47 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/rmprq.c,v 1.1 1992/01/24 03:27:30 dvadura 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@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. +-- +-- LOG +-- $Log: rmprq.c,v $ + * Revision 1.1 1992/01/24 03:27:30 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +PUBLIC void +Remove_prq( tcp ) +CELLPTR tcp; +{ + tcp->ce_flag &= ~(F_MADE|F_VISITED); + tcp->ce_time = 0L; + + Make( tcp, NIL(LINK), NIL(CELL) ); +} diff --git a/dmake/msdos/ruletab.c b/dmake/msdos/ruletab.c new file mode 100644 index 0000000..34eed20 --- /dev/null +++ b/dmake/msdos/ruletab.c @@ -0,0 +1,52 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/ruletab.c,v 1.1 1992/01/24 03:27:43 dvadura 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@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. +-- +-- LOG +-- $Log: ruletab.c,v $ + * Revision 1.1 1992/01/24 03:27:43 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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 := 2046", + "MAXPROCESSLIMIT := 1", + "MAXPROCESS := 1", + ".IMPORT .IGNORE: ROOTDIR", + ".MAKEFILES : makefile.mk makefile", + ".SOURCE : .NULL", +#include "startup.h" + 0 }; + +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 0000000..05302dd --- /dev/null +++ b/dmake/msdos/runargv.c @@ -0,0 +1,119 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/runargv.c,v 1.1 1992/01/24 03:27:35 dvadura Exp $ +-- SYNOPSIS -- run a sub process. +-- +-- DESCRIPTION +-- Use spawn to run a subprocess. +-- +-- 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. +-- +-- LOG +-- $Log: runargv.c,v $ + * Revision 1.1 1992/01/24 03:27:35 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include +#include +#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) + extern char **environ; +#endif + int status; + char **argv; + char path[MAX_PATH_LEN+1]; + + argv = Pack_argv( group, shell, cmd ); + _add_child(target, ignore); + + /* Preserve the current working directory accross a spawn call + * DOS is brain dead about this. */ + strcpy(path,Get_current_dir()); + status = spawnvpe(P_WAIT, *argv, argv, environ); + Set_dir(path); + + 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 0000000..b9f5cc7 --- /dev/null +++ b/dmake/msdos/spawn.c @@ -0,0 +1,416 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/spawn.c,v 1.1 1992/01/24 03:27:31 dvadura 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@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. +-- +-- LOG +-- $Log: spawn.c,v $ + * Revision 1.1 1992/01/24 03:27:31 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include +#include + +#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 +# undef spawnvpe + int spawnvpe(int, char *, char **, char **); +#else +# include +#endif + +#include +#include +#include +#include +#include +#include "extern.h" +#include "dirlib.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 **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))?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) ); + + /* 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 */ + } + *environment = '\0'; + + /* Clear the interrupted flag, and exec */ + Interrupted = 0; + i = exec(doswap,CF(program),CF(cmdtail),FP_SEG(environment),CF(swptmp)); + + /* 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=_strjoin(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=_strjoin(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 = _strdup(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 0000000..b17fa7b --- /dev/null +++ b/dmake/msdos/startup.h @@ -0,0 +1,7 @@ +/* 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)/etc/startup.mk", diff --git a/dmake/msdos/stdarg.h b/dmake/msdos/stdarg.h new file mode 100644 index 0000000..1d87473 --- /dev/null +++ b/dmake/msdos/stdarg.h @@ -0,0 +1,22 @@ +/* + * stdarg.h + * + * defines ANSI style macros for accessing arguments of a function which takes + * a variable number of arguments + * + */ + +#if !defined(__STDARG) +#define __STDARG + +#if !defined(ZTC) +#define __ss +#endif + +typedef char __ss *va_list; + +#define va_dcl int va_alist +#define va_start(ap,v) ap = (va_list)&va_alist +#define va_arg(ap,t) ((t*)(ap += sizeof(t)))[-1] +#define va_end(ap) ap = NULL +#endif diff --git a/dmake/msdos/switchar.c b/dmake/msdos/switchar.c new file mode 100644 index 0000000..ecad0ff --- /dev/null +++ b/dmake/msdos/switchar.c @@ -0,0 +1,39 @@ +/* +** return switch char +*/ +#if defined(OS2) || defined(_MSC_VER) +#include +#endif +#if !defined(OS2) +#include +#endif /* !OS2 */ +#include +#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) +#if !defined(OS2) + union REGS rg; +#endif /* ! OS2 */ + static char *_env_switchar = NIL(char); + + if( _env_switchar != NIL(char) || + (_env_switchar = (char *)getenv("SWITCHAR")) != NIL(char) ) + return(*_env_switchar); + +#if !defined(OS2) + rg.h.ah = 0x37; /* switch char request */ + rg.h.al = 0; /* get (not set) */ + + intdos(&rg, &rg); + return (rg.h.dl); +#endif /* ! OS2 */ +#endif /* M_I86 */ + + return ('-'); +} diff --git a/dmake/msdos/sysintf.h b/dmake/msdos/sysintf.h new file mode 100644 index 0000000..99ae5a8 --- /dev/null +++ b/dmake/msdos/sysintf.h @@ -0,0 +1,29 @@ +/* +** assorted bits of system interface +*/ + +#define STAT stat +#define VOID_LCACHE(l,m) +#define GETPID _psp + +extern char * tempnam(); +extern char * getcwd(); + +/* +** standard C items +*/ + +/* +** DOS interface standard items +*/ +#define chdir(p) _chdir(p) + +/* +** make parameters +*/ +#ifdef _POSIX_NAME_MAX +#undef _POSIX_NAME_MAX +#endif +#define _POSIX_NAME_MAX 12 +#define _POSIX_PATH_MAX 64 +#define MAX_PATH_LEN _POSIX_PATH_MAX diff --git a/dmake/msdos/tccdos/config.h b/dmake/msdos/tccdos/config.h new file mode 100644 index 0000000..8666cd9 --- /dev/null +++ b/dmake/msdos/tccdos/config.h @@ -0,0 +1,54 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/tccdos/config.h,v 1.1 1992/01/24 03:27:32 dvadura 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@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. +-- +-- LOG +-- $Log: config.h,v $ + * Revision 1.1 1992/01/24 03:27:32 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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 * diff --git a/dmake/msdos/tccdos/config.mk b/dmake/msdos/tccdos/config.mk new file mode 100644 index 0000000..71723dc --- /dev/null +++ b/dmake/msdos/tccdos/config.mk @@ -0,0 +1,50 @@ +# 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) + +# Definition of macros for library, and C startup code. +LDLIBS = d:/cc/tcc/lib/c$(MODEL) +CSTARTUP = d:/cc/tcc/lib/c0$(MODEL).obj + +# 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) -f- -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/tccdos/lib.rsp b/dmake/msdos/tccdos/lib.rsp new file mode 100644 index 0000000..66de004 --- /dev/null +++ b/dmake/msdos/tccdos/lib.rsp @@ -0,0 +1 @@ +d:\cc\tcc\lib\cl diff --git a/dmake/msdos/tccdos/libswp.rsp b/dmake/msdos/tccdos/libswp.rsp new file mode 100644 index 0000000..66de004 --- /dev/null +++ b/dmake/msdos/tccdos/libswp.rsp @@ -0,0 +1 @@ +d:\cc\tcc\lib\cl diff --git a/dmake/msdos/tccdos/mk.bat b/dmake/msdos/tccdos/mk.bat new file mode 100644 index 0000000..bdf93b2 --- /dev/null +++ b/dmake/msdos/tccdos/mk.bat @@ -0,0 +1,96 @@ +md objects +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml infer.c +copy infer.obj objects +del infer.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml make.c +copy make.obj objects +del make.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml stat.c +copy stat.obj objects +del stat.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml expand.c +copy expand.obj objects +del expand.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml dmstring.c +copy dmstring.obj objects +del dmstring.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml hash.c +copy hash.obj objects +del hash.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml dag.c +copy dag.obj objects +del dag.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml dmake.c +copy dmake.obj objects +del dmake.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml path.c +copy path.obj objects +del path.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml imacs.c +copy imacs.obj objects +del imacs.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml sysintf.c +copy sysintf.obj objects +del sysintf.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml parse.c +copy parse.obj objects +del parse.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml getinp.c +copy getinp.obj objects +del getinp.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml quit.c +copy quit.obj objects +del quit.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml state.c +copy state.obj objects +del state.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml basename.c +copy basename.obj objects +del basename.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml dmdump.c +copy dmdump.obj objects +del dmdump.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml macparse.c +copy macparse.obj objects +del macparse.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml rulparse.c +copy rulparse.obj objects +del rulparse.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml percent.c +copy percent.obj objects +del percent.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml function.c +copy function.obj objects +del function.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\ruletab.c +copy ruletab.obj objects +del ruletab.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\dirbrk.c +copy dirbrk.obj objects +del dirbrk.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\runargv.c +copy runargv.obj objects +del runargv.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\arlib.c +copy arlib.obj objects +del arlib.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\_chdir.c +copy _chdir.obj objects +del _chdir.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\switchar.c +copy switchar.obj objects +del switchar.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\rmprq.c +copy rmprq.obj objects +del rmprq.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\tee.c +copy tee.obj objects +del tee.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\tccdos\tempnam.c +copy tempnam.obj objects +del tempnam.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\tccdos\utime.c +copy utime.obj objects +del utime.obj +copy msdos\tccdos\startup.mk startup.mk +tlink @msdos\tccdos\obj.rsp,dmake.exe,NUL.MAP,@msdos\tccdos\lib.rsp diff --git a/dmake/msdos/tccdos/mkswp.bat b/dmake/msdos/tccdos/mkswp.bat new file mode 100644 index 0000000..ffaa9d5 --- /dev/null +++ b/dmake/msdos/tccdos/mkswp.bat @@ -0,0 +1,101 @@ +md objects +tasm -t -mx -dmlarge msdos\exec.asm; +mv exec.obj objects +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml infer.c +copy infer.obj objects +del infer.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml make.c +copy make.obj objects +del make.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml stat.c +copy stat.obj objects +del stat.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml expand.c +copy expand.obj objects +del expand.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml dmstring.c +copy dmstring.obj objects +del dmstring.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml hash.c +copy hash.obj objects +del hash.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml dag.c +copy dag.obj objects +del dag.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml dmake.c +copy dmake.obj objects +del dmake.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml path.c +copy path.obj objects +del path.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml imacs.c +copy imacs.obj objects +del imacs.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml sysintf.c +copy sysintf.obj objects +del sysintf.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml parse.c +copy parse.obj objects +del parse.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml getinp.c +copy getinp.obj objects +del getinp.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml quit.c +copy quit.obj objects +del quit.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml state.c +copy state.obj objects +del state.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml basename.c +copy basename.obj objects +del basename.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml dmdump.c +copy dmdump.obj objects +del dmdump.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml macparse.c +copy macparse.obj objects +del macparse.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml rulparse.c +copy rulparse.obj objects +del rulparse.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml percent.c +copy percent.obj objects +del percent.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml function.c +copy function.obj objects +del function.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\ruletab.c +copy ruletab.obj objects +del ruletab.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\dirbrk.c +copy dirbrk.obj objects +del dirbrk.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\runargv.c +copy runargv.obj objects +del runargv.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\arlib.c +copy arlib.obj objects +del arlib.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\_chdir.c +copy _chdir.obj objects +del _chdir.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\switchar.c +copy switchar.obj objects +del switchar.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\rmprq.c +copy rmprq.obj objects +del rmprq.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\find.c +copy find.obj objects +del find.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\spawn.c +copy spawn.obj objects +del spawn.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\tccdos\tempnam.c +copy tempnam.obj objects +del tempnam.obj +tcc -c -I. -Imsdos -Imsdos\tccdos -f- -d -O -N- -w-nod -ml msdos\tccdos\utime.c +copy utime.obj objects +del utime.obj +copy msdos\tccdos\startup.mk startup.mk +tlink @msdos\tccdos\objswp.rsp,dmake.exe,NUL.MAP,@msdos\tccdos\libswp.rsp diff --git a/dmake/msdos/tccdos/obj.rsp b/dmake/msdos/tccdos/obj.rsp new file mode 100644 index 0000000..6f9c2c8 --- /dev/null +++ b/dmake/msdos/tccdos/obj.rsp @@ -0,0 +1,32 @@ +d:\cc\tcc\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\basename.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\_chdir.obj+ +objects\switchar.obj+ +objects\rmprq.obj+ +objects\tee.obj+ +objects\tempnam.obj+ +objects\utime.obj diff --git a/dmake/msdos/tccdos/objswp.rsp b/dmake/msdos/tccdos/objswp.rsp new file mode 100644 index 0000000..2212a6c --- /dev/null +++ b/dmake/msdos/tccdos/objswp.rsp @@ -0,0 +1,34 @@ +d:\cc\tcc\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\basename.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\_chdir.obj+ +objects\switchar.obj+ +objects\rmprq.obj+ +objects\find.obj+ +objects\spawn.obj+ +objects\tempnam.obj+ +objects\utime.obj diff --git a/dmake/msdos/tccdos/public.h b/dmake/msdos/tccdos/public.h new file mode 100644 index 0000000..fe5e0c8 --- /dev/null +++ b/dmake/msdos/tccdos/public.h @@ -0,0 +1,152 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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 _chdir ANSI((char *)); +void Remove_prq ANSI((CELLPTR)); +void Hook_std_writes ANSI((char *)); + +#endif diff --git a/dmake/msdos/tccdos/startup.mk b/dmake/msdos/tccdos/startup.mk new file mode 100644 index 0000000..3ad92c3 --- /dev/null +++ b/dmake/msdos/tccdos/startup.mk @@ -0,0 +1,154 @@ +# MSDOS DMAKE startup file. Customize to suit your needs. +# Assumes MKS toolkit for the tool commands, and Turbo-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 := tcc # C-compiler and flags + CFLAGS += + + AS := tasm # Assembler and flags + ASFLAGS += + + LD = tlink # Loader and flags + LDFLAGS += + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(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 := tpc # 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 : %$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/$$(@:f)$V;- $(CO) $(COFLAGS) $@ + .NOINFER : $$(@:d)RCS/$$(@:f)$V +.END + +# SCCS support +.IF $(_HAVE_SCCS) + % : s.% ; get $< + .NOINFER : s.% +.END + +# Recipe to make archive files. +%$A : +[ + $(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) + +#include +#include +#include + +#if defined(max) +# undef max +#endif +#define max(A,B) (((A)<(B))?(B):(A)) + +extern char *mktemp(); +extern int access(); +int _access(); + +/* Turbo 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) +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); + if( dir != NULL ) dl = strlen(dir); + + if( (p = malloc((unsigned)(max(max(dl,tl),pl)+13))) == NULL ) + return(NULL); + + *p = '\0'; + + if( (tl == 0) || (_access( strcpy(p, tmpdir), 0) != 0) ) + if( (dl == 0) || (_access( strcpy(p, dir), 0) != 0) ) + if( _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); +} + + + +_access( name, flag ) +char *name; +int flag; +{ + 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, "/" ); + + return( r ); +} diff --git a/dmake/msdos/tccdos/utime.c b/dmake/msdos/tccdos/utime.c new file mode 100644 index 0000000..60bf6b6 --- /dev/null +++ b/dmake/msdos/tccdos/utime.c @@ -0,0 +1,42 @@ +/* +** change access and modify times of file +*/ +#include +#include +#include + +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/tee.c b/dmake/msdos/tee.c new file mode 100644 index 0000000..6664076 --- /dev/null +++ b/dmake/msdos/tee.c @@ -0,0 +1,40 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/tee.c,v 1.1 1992/01/24 03:27:37 dvadura Exp $ +-- SYNOPSIS -- Hook_std_writes() dummy call for non swapping MSDOS versions. +-- +-- DESCRIPTION +-- +-- 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. +-- +-- LOG +-- $Log: tee.c,v $ + * Revision 1.1 1992/01/24 03:27:37 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +PUBLIC void +Hook_std_writes( file ) +char *file; +{ +} diff --git a/dmake/msdos/ztcdos/config.h b/dmake/msdos/ztcdos/config.h new file mode 100644 index 0000000..1c14380 --- /dev/null +++ b/dmake/msdos/ztcdos/config.h @@ -0,0 +1,59 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/ztcdos/config.h,v 1.1 1992/01/24 03:27:49 dvadura 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@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. +-- +-- LOG +-- $Log: config.h,v $ + * Revision 1.1 1992/01/24 03:27:49 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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 * diff --git a/dmake/msdos/ztcdos/config.mk b/dmake/msdos/ztcdos/config.mk new file mode 100644 index 0000000..e947dc8 --- /dev/null +++ b/dmake/msdos/ztcdos/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/ztcdos/environ.c b/dmake/msdos/ztcdos/environ.c new file mode 100644 index 0000000..be40c09 --- /dev/null +++ b/dmake/msdos/ztcdos/environ.c @@ -0,0 +1,35 @@ +/*LINTLIBRARY*/ +#include +#include +#include +#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/ztcdos/lib.rsp b/dmake/msdos/ztcdos/lib.rsp new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/dmake/msdos/ztcdos/lib.rsp @@ -0,0 +1 @@ + diff --git a/dmake/msdos/ztcdos/libswp.rsp b/dmake/msdos/ztcdos/libswp.rsp new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/dmake/msdos/ztcdos/libswp.rsp @@ -0,0 +1 @@ + diff --git a/dmake/msdos/ztcdos/mk.bat b/dmake/msdos/ztcdos/mk.bat new file mode 100644 index 0000000..09c6d7e --- /dev/null +++ b/dmake/msdos/ztcdos/mk.bat @@ -0,0 +1,34 @@ +md objects +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\infer.obj infer.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\make.obj make.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\stat.obj stat.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\expand.obj expand.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dmstring.obj dmstring.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\hash.obj hash.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dag.obj dag.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dmake.obj dmake.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\path.obj path.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\imacs.obj imacs.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\sysintf.obj sysintf.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\parse.obj parse.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\getinp.obj getinp.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\quit.obj quit.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\state.obj state.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\basename.obj basename.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dmdump.obj dmdump.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\macparse.obj macparse.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\rulparse.obj rulparse.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\percent.obj percent.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\function.obj function.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\ruletab.obj msdos\ruletab.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dirbrk.obj msdos\dirbrk.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\runargv.obj msdos\runargv.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\arlib.obj msdos\arlib.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\_chdir.obj msdos\_chdir.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\switchar.obj msdos\switchar.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\rmprq.obj msdos\rmprq.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\tee.obj msdos\tee.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\tempnam.obj msdos\ztcdos\tempnam.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\environ.obj msdos\ztcdos\environ.c +copy msdos\ztcdos\startup.mk startup.mk +blink @msdos\ztcdos\obj.rsp,dmake.exe,NUL.MAP; diff --git a/dmake/msdos/ztcdos/mkswp.bat b/dmake/msdos/ztcdos/mkswp.bat new file mode 100644 index 0000000..a78cb81 --- /dev/null +++ b/dmake/msdos/ztcdos/mkswp.bat @@ -0,0 +1,34 @@ +md objects +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\infer.obj infer.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\make.obj make.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\stat.obj stat.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\expand.obj expand.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dmstring.obj dmstring.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\hash.obj hash.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dag.obj dag.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dmake.obj dmake.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\path.obj path.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\imacs.obj imacs.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\sysintf.obj sysintf.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\parse.obj parse.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\getinp.obj getinp.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\quit.obj quit.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\state.obj state.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\basename.obj basename.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dmdump.obj dmdump.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\macparse.obj macparse.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\rulparse.obj rulparse.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\percent.obj percent.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\function.obj function.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\ruletab.obj msdos\ruletab.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\dirbrk.obj msdos\dirbrk.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\runargv.obj msdos\runargv.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\arlib.obj msdos\arlib.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\_chdir.obj msdos\_chdir.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\switchar.obj msdos\switchar.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\rmprq.obj msdos\rmprq.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\tee.obj msdos\tee.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\tempnam.obj msdos\ztcdos\tempnam.c +ztc -c -I. -Imsdos -Imsdos\ztcdos -mL -DM_I86=1 -DMSDOS -b -mi -p -o -oobjects\environ.obj msdos\ztcdos\environ.c +copy msdos\ztcdos\startup.mk startup.mk +blink @msdos\ztcdos\objswp.rsp,dmake.exe,NUL.MAP; diff --git a/dmake/msdos/ztcdos/obj.rsp b/dmake/msdos/ztcdos/obj.rsp new file mode 100644 index 0000000..655cbc0 --- /dev/null +++ b/dmake/msdos/ztcdos/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\basename.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\_chdir.obj+ +objects\switchar.obj+ +objects\rmprq.obj+ +objects\tee.obj+ +objects\tempnam.obj+ +objects\environ.obj diff --git a/dmake/msdos/ztcdos/objswp.rsp b/dmake/msdos/ztcdos/objswp.rsp new file mode 100644 index 0000000..ab8d9c2 --- /dev/null +++ b/dmake/msdos/ztcdos/objswp.rsp @@ -0,0 +1,32 @@ +_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\basename.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\_chdir.obj+ +objects\switchar.obj+ +objects\rmprq.obj+ +objects\tee.obj+ +objects\tempnam.obj+ +objects\environ.obj diff --git a/dmake/msdos/ztcdos/public.h b/dmake/msdos/ztcdos/public.h new file mode 100644 index 0000000..fe5e0c8 --- /dev/null +++ b/dmake/msdos/ztcdos/public.h @@ -0,0 +1,152 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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 _chdir ANSI((char *)); +void Remove_prq ANSI((CELLPTR)); +void Hook_std_writes ANSI((char *)); + +#endif diff --git a/dmake/msdos/ztcdos/startup.mk b/dmake/msdos/ztcdos/startup.mk new file mode 100644 index 0000000..0cbc674 --- /dev/null +++ b/dmake/msdos/ztcdos/startup.mk @@ -0,0 +1,155 @@ +# 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) $(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 : +[ + $(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) + +#include +#include +#include + +#if defined(max) +# undef max +#endif +#define max(A,B) (((A)<(B))?(B):(A)) + +extern char *mktemp(); +extern int access(); +int _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); + if( dir != NULL ) dl = strlen(dir); + + if( (p = malloc((unsigned)(max(max(dl,tl),pl)+13))) == NULL ) + return(NULL); + + *p = '\0'; + + if( (tl == 0) || (_access( strcpy(p, tmpdir), 0) != 0) ) + if( (dl == 0) || (_access( strcpy(p, dir), 0) != 0) ) + if( _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); +} + + + +_access( name, flag ) +char *name; +int flag; +{ + 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, "/" ); + + return( r ); +} diff --git a/dmake/os2/_chdir.c b/dmake/os2/_chdir.c new file mode 100644 index 0000000..c4811b9 --- /dev/null +++ b/dmake/os2/_chdir.c @@ -0,0 +1,59 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/os2/_chdir.c,v 1.1 1992/01/24 03:29:24 dvadura Exp $ +-- SYNOPSIS -- Change directory. +-- +-- DESCRIPTION +-- Under DOS change the current drive as well as the current directory. +-- +-- 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. +-- +-- LOG +-- $Log: _chdir.c,v $ + * Revision 1.1 1992/01/24 03:29:24 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include +#include +#include "extern.h" + +PUBLIC int +_chdir(path) +char *path; +{ + int res; + + res = chdir(path); + + if (res == 0 && path[1] == ':') +#ifdef OS2 + DosSelectDisk((*path & ~0x20) - '@'); +#else + unsigned new_drive; + unsigned max_drives; + + new_drive = (*path & ~0x20) - 'A' + 1; + _dos_setdrive(new_drive, &max_drives); +#endif + + return (res); +} diff --git a/dmake/os2/config.mk b/dmake/os2/config.mk new file mode 100644 index 0000000..9fb07aa --- /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 *= mscdos +# 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) -DOS2 + +# 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 runargv.c _chdir.c switchar.c +DOS_SRC = dirbrk.c arlib.c +UNIX_SRC = rmprq.c + +SRC += $(OS_SRC) $(DOS_SRC) $(UNIX_SRC) +.SETDIR=$(OS) : $(ASRC) $(OS_SRC) +.SETDIR=msdos : $(DOS_SRC) +.SETDIR=unix : $(UNIX_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/dmake.bad b/dmake/os2/dmake.bad new file mode 100644 index 0000000..040d2ad --- /dev/null +++ b/dmake/os2/dmake.bad @@ -0,0 +1,2 @@ +DOSCWAIT +DOSKILLPROCESS diff --git a/dmake/os2/dmake.cs b/dmake/os2/dmake.cs new file mode 100644 index 0000000..4417753 --- /dev/null +++ b/dmake/os2/dmake.cs @@ -0,0 +1,13 @@ +(-I. -Ios2 -Ios2\mscdos -DOS2 -D__STDC__=1 -W1 +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 +basename.c dmdump.c macparse.c rulparse.c percent.c function.c +os2\ruletab.c os2\runargv.c os2\_chdir.c os2\switchar.c +msdos\dirbrk.c msdos\arlib.c unix\rmprq.c os2\mscdos\tempnam.c +) + +dmake.exe +os2\dmake.def +os2\dmake.bad + +-AL -LB -S0x2000 diff --git a/dmake/os2/dmake.def b/dmake/os2/dmake.def new file mode 100644 index 0000000..16c8726 --- /dev/null +++ b/dmake/os2/dmake.def @@ -0,0 +1,5 @@ +NAME DMAKE WINDOWCOMPAT NEWFILES +DESCRIPTION 'DMAKE Version 3.8 - for MS-DOS and OS/2' + +; IMPORTS +; SESMGR.DOSSMSETTITLE diff --git a/dmake/os2/ibm/config.h b/dmake/os2/ibm/config.h new file mode 100644 index 0000000..28cc2c7 --- /dev/null +++ b/dmake/os2/ibm/config.h @@ -0,0 +1,78 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/os2/ibm/config.h,v 1.1 1992/01/24 03:29:29 dvadura 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@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. +-- +-- LOG +-- $Log: config.h,v $ + * Revision 1.1 1992/01/24 03:29:29 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 * diff --git a/dmake/os2/ibm/config.mk b/dmake/os2/ibm/config.mk new file mode 100644 index 0000000..5cbbd5e --- /dev/null +++ b/dmake/os2/ibm/config.mk @@ -0,0 +1,83 @@ +# This is the MSC 4.0 and higher OS/2 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) + +# 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) + +# Local configuration modifications for CFLAGS +# OS/2 always has at least a 286 so this is enabled by default: +CFLAGS += -G2 + +SET_STACK = /stack:8192 +NDB_LDFLAGS += $(SET_STACK) + +# Microsoft C doesn't need tail but needs head +LDTAIL = $(OS)$(DIRSEPSTR)$(TARGET:b).def; +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 4.0, 5.0, 5.1, or 6.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. + +.IMPORT .IGNORE : MSC_VER +MSC_VER *= 6.0 # If unset, assume 6.0 by default. + +.IF $(MSC_VER) == 4.0 + CFLAGS += -I$(osrdir) $(C_$(MODEL):s/A/m/) + CFLAGS += -DM_I86=1 # 5.0+ define this automatically + CFLAGS += -D__STDC__=1 # 5.0, 5.1, but not 6.0 do this automatically + NDB_CFLAGS += + DB_CFLAGS += -Zi +.ELSE + DB_CFLAGS += -Zi + CFLAGS += -I$(osrdir) $(C_$(MODEL)) + .IF $(MSC_VER) != 6.0 + # For 5.0 and 5.1, we define _MSC_VER=500 or 510 + CFLAGS += -D_MSC_VER=$(MSC_VER:s,.,,)0 + NDB_CFLAGS += -Osl -Gs + .ELSE + # Microsoft C 6.0 auto defines _MSC_VER=600, but not __STDC__ + CFLAGS += -D__STDC__=1 # incredibly not auto done by 6.0 + NDB_CFLAGS += -Osecgl -Gs + + # Redefine rule for making our objects, we don't need mv + %$O : %.c ;% $(CC) -c $(CFLAGS) -Fo$@ $< + .END + NDB_LDFLAGS += /exe /packc /batch + NDB_LDLIBS += /NOD:LLIBCE LLIBCEP +.END + +# 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/os2/ibm/dmake.ini b/dmake/os2/ibm/dmake.ini new file mode 100644 index 0000000..f89b64f --- /dev/null +++ b/dmake/os2/ibm/dmake.ini @@ -0,0 +1,154 @@ +# MSDOS DMAKE startup file. Customize to suit your needs. +# Assumes MKS toolkit for the tool commands, and Microsoft 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 cmd.exe) or +# MKS Korn Shell. +.IF $(SHELL)==$(COMSPEC) + SHELLFLAGS := $(SWITCHAR)c + GROUPFLAGS := $(SHELLFLAGS) + SHELLMETAS := *"?<>|& + GROUPSUFFIX := .cmd + 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 := cl # C-compiler and flags + CFLAGS += + + AS := masm # Assembler and flags + ASFLAGS += + + LD = link # Loader and flags + LDFLAGS += + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(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 : %$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 : +[ + $(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) + +#include +#include +#include + +#if defined(max) +# undef max +#endif +#define max(A,B) (((A)<(B))?(B):(A)) + +extern int access(); +int _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) || (_access( strcpy(p, tmpdir), 0) != 0) ) + if( (dl == 0) || (_access( strcpy(p, dir), 0) != 0) ) + if( _access( strcpy(p, P_tmpdir), 0) != 0 ) + if( !prefix ) + prefix = "tp"; + + if(prefix) + { + *(p+strlen(p)+2) = '\0'; + (void)strncat(p, prefix, 2); + } + +#ifdef OS2 + sprintf( buf, "%08x", getpid() ); +#else + sprintf( buf, "%08x", _psp ); +#endif + 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); +} + + + +_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/mscdos/config.h b/dmake/os2/mscdos/config.h new file mode 100644 index 0000000..dce7c85 --- /dev/null +++ b/dmake/os2/mscdos/config.h @@ -0,0 +1,78 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/os2/mscdos/config.h,v 1.1 1992/01/24 03:29:25 dvadura 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@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. +-- +-- LOG +-- $Log: config.h,v $ + * Revision 1.1 1992/01/24 03:29:25 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 * diff --git a/dmake/os2/mscdos/config.mk b/dmake/os2/mscdos/config.mk new file mode 100644 index 0000000..5cbbd5e --- /dev/null +++ b/dmake/os2/mscdos/config.mk @@ -0,0 +1,83 @@ +# This is the MSC 4.0 and higher OS/2 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) + +# 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) + +# Local configuration modifications for CFLAGS +# OS/2 always has at least a 286 so this is enabled by default: +CFLAGS += -G2 + +SET_STACK = /stack:8192 +NDB_LDFLAGS += $(SET_STACK) + +# Microsoft C doesn't need tail but needs head +LDTAIL = $(OS)$(DIRSEPSTR)$(TARGET:b).def; +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 4.0, 5.0, 5.1, or 6.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. + +.IMPORT .IGNORE : MSC_VER +MSC_VER *= 6.0 # If unset, assume 6.0 by default. + +.IF $(MSC_VER) == 4.0 + CFLAGS += -I$(osrdir) $(C_$(MODEL):s/A/m/) + CFLAGS += -DM_I86=1 # 5.0+ define this automatically + CFLAGS += -D__STDC__=1 # 5.0, 5.1, but not 6.0 do this automatically + NDB_CFLAGS += + DB_CFLAGS += -Zi +.ELSE + DB_CFLAGS += -Zi + CFLAGS += -I$(osrdir) $(C_$(MODEL)) + .IF $(MSC_VER) != 6.0 + # For 5.0 and 5.1, we define _MSC_VER=500 or 510 + CFLAGS += -D_MSC_VER=$(MSC_VER:s,.,,)0 + NDB_CFLAGS += -Osl -Gs + .ELSE + # Microsoft C 6.0 auto defines _MSC_VER=600, but not __STDC__ + CFLAGS += -D__STDC__=1 # incredibly not auto done by 6.0 + NDB_CFLAGS += -Osecgl -Gs + + # Redefine rule for making our objects, we don't need mv + %$O : %.c ;% $(CC) -c $(CFLAGS) -Fo$@ $< + .END + NDB_LDFLAGS += /exe /packc /batch + NDB_LDLIBS += /NOD:LLIBCE LLIBCEP +.END + +# 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/os2/mscdos/dmake.ini b/dmake/os2/mscdos/dmake.ini new file mode 100644 index 0000000..f89b64f --- /dev/null +++ b/dmake/os2/mscdos/dmake.ini @@ -0,0 +1,154 @@ +# MSDOS DMAKE startup file. Customize to suit your needs. +# Assumes MKS toolkit for the tool commands, and Microsoft 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 cmd.exe) or +# MKS Korn Shell. +.IF $(SHELL)==$(COMSPEC) + SHELLFLAGS := $(SWITCHAR)c + GROUPFLAGS := $(SHELLFLAGS) + SHELLMETAS := *"?<>|& + GROUPSUFFIX := .cmd + 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 := cl # C-compiler and flags + CFLAGS += + + AS := masm # Assembler and flags + ASFLAGS += + + LD = link # Loader and flags + LDFLAGS += + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(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 : %$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 : +[ + $(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) + +#include +#include +#include + +#if defined(max) +# undef max +#endif +#define max(A,B) (((A)<(B))?(B):(A)) + +extern int access(); +int _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) || (_access( strcpy(p, tmpdir), 0) != 0) ) + if( (dl == 0) || (_access( strcpy(p, dir), 0) != 0) ) + if( _access( strcpy(p, P_tmpdir), 0) != 0 ) + if( !prefix ) + prefix = "tp"; + + if(prefix) + { + *(p+strlen(p)+2) = '\0'; + (void)strncat(p, prefix, 2); + } + +#ifdef OS2 + sprintf( buf, "%08x", getpid() ); +#else + sprintf( buf, "%08x", _psp ); +#endif + 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); +} + + + +_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/optoff.h b/dmake/os2/optoff.h new file mode 100644 index 0000000..5e9dd09 --- /dev/null +++ b/dmake/os2/optoff.h @@ -0,0 +1,3 @@ +#if _MSC_VER < 600 +# pragma loop_opt(off) +#endif diff --git a/dmake/os2/ruletab.c b/dmake/os2/ruletab.c new file mode 100644 index 0000000..0c470da --- /dev/null +++ b/dmake/os2/ruletab.c @@ -0,0 +1,55 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/os2/ruletab.c,v 1.1 1992/01/24 03:29:18 dvadura 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@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. +-- +-- LOG +-- $Log: ruletab.c,v $ + * Revision 1.1 1992/01/24 03:29:18 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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: ROOTDIR INIT", + ".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/runargv.c b/dmake/os2/runargv.c new file mode 100644 index 0000000..8e8b74e --- /dev/null +++ b/dmake/os2/runargv.c @@ -0,0 +1,327 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/os2/runargv.c,v 1.1 1992/01/24 03:29:19 dvadura Exp $ +-- SYNOPSIS -- invoke a sub process, modified unix/runargv.c for OS/2. +-- +-- DESCRIPTION +-- Use the standard methods of executing a sub process. +-- +-- 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. +-- +-- LOG +-- $Log: runargv.c,v $ + * Revision 1.1 1992/01/24 03:29:19 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#define INCL_DOSPROCESS +#include + +#include +#include +#include +#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; + +extern unsigned int _far _pascal DosSmSetTitle(char _far *s); +static void SetSessionTitle (char *s); +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; +{ + 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" ); + +#ifdef SESSTITLE + SetSessionTitle(target->CE_NAME); +#endif + argv = Pack_argv( group, shell, cmd ); + + if((pid=spawnvp((_osmode == DOS_MODE)?P_WAIT:P_NOWAIT,argv[0],argv)) == -1){ + Error("%s: %s", argv[0], sys_errlist[errno]); + Handle_result(-1, ignore, _abort_flg, target); + return(-1); + } + else if( _osmode == DOS_MODE ) { + _add_child(4711, target, ignore, last); + _finished_child(4711, pid); + } + else + _add_child(pid, target, ignore, last); + + return(1); +} + + +#ifdef SESSTITLE +/* N.B. The system call used below is undocumented and therefore possibly + * subject to change. It sets the session title even from a full screen + * session, so you can see which target is being built. + * If dubious about undocumented calls simply remove it. + */ +PUBLIC void +SetSessionTitle(char *s) +{ + char buff[128]; + strncpy(buff, Pname, sizeof(buff)); + buff[sizeof(buff)-1] = 0; + strncat(buff, " - ", sizeof(buff)); + strncat(buff, s, sizeof(buff)); + buff[sizeof(buff)-1] = 0; + DosSmSetTitle(buff); +} +#endif + + +PUBLIC int +Wait_for_child( abort_flg, pid ) +int abort_flg; +int pid; +{ + int wid; + int status; + int waitchild; + + if( _osmode == DOS_MODE ) return(1); + + 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( _osmode == DOS_MODE ) { + _abort_flg = TRUE; + _finished_child(4711, -1); + return; + } + + if( _procs != NIL(PR) ) { + for( i=0; ipr_valid = 1; + pp->pr_pid = pid; + pp->pr_target = target; + pp->pr_ignore = ignore; + pp->pr_last = last; + pp->pr_dir = _strdup(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; iprp_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); + + 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; iprp_cmd = _strdup(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/os2/startup.h b/dmake/os2/startup.h new file mode 100644 index 0000000..9e2a918 --- /dev/null +++ b/dmake/os2/startup.h @@ -0,0 +1,7 @@ +/* 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 := $(INIT)/dmake.ini", diff --git a/dmake/os2/switchar.c b/dmake/os2/switchar.c new file mode 100644 index 0000000..fe7bdf1 --- /dev/null +++ b/dmake/os2/switchar.c @@ -0,0 +1,39 @@ +/* +** return switch char +*/ +#if defined(OS2) || defined(_MSC_VER) +#include +#endif +#if !defined(OS2) +#include +#endif /* !OS2 */ +#include +#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(M_I86) +#if !defined(OS2) + union REGS rg; +#endif /* ! OS2 */ + static char *_env_switchar = NIL(char); + + if( _env_switchar != NIL(char) || + (_env_switchar = (char *)getenv("SWITCHAR")) != NIL(char) ) + return(*_env_switchar); + +#if !defined(OS2) + rg.h.ah = 0x37; /* switch char request */ + rg.h.al = 0; /* get (not set) */ + + intdos(&rg, &rg); + return (rg.h.dl); +#endif /* ! OS2 */ +#endif /* M_I86 */ + + return ('/'); +} diff --git a/dmake/os2/sysintf.h b/dmake/os2/sysintf.h new file mode 100644 index 0000000..d84cee8 --- /dev/null +++ b/dmake/os2/sysintf.h @@ -0,0 +1,26 @@ +/* +** assorted bits of system interface +*/ + +#define STAT stat +#define VOID_LCACHE(l,m) +#define Hook_std_writes(A) +#define GETPID getpid() + +extern char * tempnam(); +extern char * getcwd(); + +/* +** standard C items +*/ + +/* +** DOS interface standard items +*/ +#define chdir(p) _chdir(p) + +/* +** make parameters +*/ +#define MAX_PATH_LEN 256 + diff --git a/dmake/parse.c b/dmake/parse.c new file mode 100644 index 0000000..96e552d --- /dev/null +++ b/dmake/parse.c @@ -0,0 +1,158 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/parse.c,v 1.1 1992/01/24 03:26:53 dvadura 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@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. +-- +-- LOG +-- $Log: parse.c,v $ + * Revision 1.1 1992/01/24 03:26:53 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 */ + + 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 { + 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 = _strspn( 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( Buffer, TRUE, TRUE ); + rule = TRUE; + } + else + State = NORMAL_SCAN; + } + else { + if( *Buffer == '\t' + || (Notabs && *Buffer == ' ') ) { + Add_recipe_to_list( Buffer, FALSE, FALSE ); + rule = TRUE; + } + else if( *p == ']' ) + Fatal( "Found unmatched ']'" ); + else if( *Buffer && *p || (Notabs && !*Buffer && !*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 , so lets + * try to scan the thing as a macro or rule definition. */ + + + case NORMAL_SCAN: + if( !*Buffer ) 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", Buffer, 7 ) && + (Buffer[7] == ' ' || Buffer[7] == '\t') ) + { + char *tmp; + + tmp = _strjoin( ".INCLUDE:", Buffer+7, -1, FALSE ); + strcpy( Buffer, 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(Buffer, 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( *_strspn( 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/patchlvl.h b/dmake/patchlvl.h new file mode 100644 index 0000000..91a8737 --- /dev/null +++ b/dmake/patchlvl.h @@ -0,0 +1,3 @@ +/* dmake patch level, reset to 0 for each new version release. */ + +#define PATCHLEVEL 1 diff --git a/dmake/path.c b/dmake/path.c new file mode 100644 index 0000000..9f73159 --- /dev/null +++ b/dmake/path.c @@ -0,0 +1,116 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/path.c,v 1.1 1992/01/24 03:27:54 dvadura Exp $ +-- SYNOPSIS -- pathname manipulation code +-- +-- DESCRIPTION +-- Pathname routines to handle building and pulling appart +-- pathnames. +-- +-- 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. +-- +-- LOG +-- $Log: path.c,v $ + * Revision 1.1 1992/01/24 03:27:54 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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); +} + + + +/* +** 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 ); + } + strcat( path, name ); + + q=path; + while( *q ) { + char *t; + + p=_strpbrk(q,DirBrkStr); + t=_strpbrk(p+1,DirBrkStr); + if( !*p || !*t ) break; + + if( !(p-q == 2 && strncmp(q,"..",2) == 0) + && t-p-1 == 2 && strncmp(p+1,"..",2) == 0 ) { + t = _strspn(t,DirBrkStr); + strcpy(q,t); + } + else + q = p+1; + } + + return( path ); +} diff --git a/dmake/percent.c b/dmake/percent.c new file mode 100644 index 0000000..61105d1 --- /dev/null +++ b/dmake/percent.c @@ -0,0 +1,260 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/percent.c,v 1.1 1992/01/24 03:29:34 dvadura 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@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. +-- +-- LOG +-- $Log: percent.c,v $ + * Revision 1.1 1992/01/24 03:29:34 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 = _substr( 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 know 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(FAIL); + + return(NO_ACTION); +} diff --git a/dmake/posix.h b/dmake/posix.h new file mode 100644 index 0000000..ea8b39b --- /dev/null +++ b/dmake/posix.h @@ -0,0 +1,66 @@ +#ifndef _POSIX_NAME_MAX +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/posix.h,v 1.1 1992/04/07 04:42:46 dvadura 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@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. +-- +-- LOG +-- $Log: posix.h,v $ + * Revision 1.1 1992/04/07 04:42:46 dvadura + * Initial revision + * +*/ + +/* 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 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_MATH_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 + +#endif diff --git a/dmake/quit.c b/dmake/quit.c new file mode 100644 index 0000000..f85066e --- /dev/null +++ b/dmake/quit.c @@ -0,0 +1,78 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/quit.c,v 1.1 1992/01/24 03:27:53 dvadura Exp $ +-- SYNOPSIS -- end the dmake session. +-- +-- DESCRIPTION +-- Handles dmake termination. +-- +-- 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. +-- +-- LOG +-- $Log: quit.c,v $ + * Revision 1.1 1992/01/24 03:27:53 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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/readme/apple.IIgs b/dmake/readme/apple.IIgs new file mode 100644 index 0000000..f3a8e32 --- /dev/null +++ b/dmake/readme/apple.IIgs @@ -0,0 +1,448 @@ +This is the README file for dmake, Apple IIgs v1.0, running Gno/ME. + +If you find a bug that is not mentioned in the "TO DO" section below, please +report it. + + +============ +INSTALLATION +============ + +The default installation uses the following directories: + + /usr/local/bin -- executables + /usr/local/lib -- configuration file + /usr/man -- documentation + +If you do not have these directories or if you prefer the files to be +located elsewhere, you will either have to edit the makefile, the install +script, or do a manual installation. Do not try to do an installation +by typing "dmake" from the top level directory; this is currently broken. + +For automated installation using dmake (uses "Makefile.mk"): + + cd dmake/unix/gno + dmake install + +For automated installation using the shell script: + + cd dmake/unix/gno + ./install + +If you want to do a manual installation: + + file: goes to: + + dmake/unix/gno/dmake /usr/local/bin/dmake + dmake/unix/gno/GS.startup.mk /usr/local/lib/startup.mk + dmake/man/dmake.nc $USRMAN/cat1/dmake.1 + rmroot/rmroot /usr/local/bin/rmroot + rmroot/rmroot.1 $USRMAN/man1/rmroot.1 + + Note: If you want to place rmroot anywhere else, you will have to + edit the recipe for .REMOVE in /usr/local/lib/startup.mk to + use the proper path. You can use just "rmroot" rather than + "/usr/local/bin/rmroot", but giving the full pathname will + reduce execution time. + +In all cases, put this into your gshrc: + + # + # Set environment variables for dmake + # + + # Mandatory definitions; location of the startup configuration + # file and shell. + + setenv MAKESTARTUP "/usr/local/lib/startup.mk" + setenv SHELL "/bin/gsh" + + # If you define NOPURGE, dmake will _not_ do a memory purge on + # startup. + + # setenv NOPURGE 1 + + # + # End of dmake environment variables + # + +=========== +COMPILATION +=========== + +In order to compile dmake, you need: + + The lenviron library, version 1.1.2 or later (current lenviron + release is v1.1.4). You should use the latest release in order + to get bug fixes which affect dmake; + + Soenke Behrens' occ front end for Orca/C; + + Orca/C v2.0.1 or later; and + + Gno v2.0.4 (with modified libraries) or later; + +Contrary to the overall instructions for dmake, you cannot make the IIgs +version from the main directory. Instead, change directory into +dmake/unix/gno and type (without the quotes): + + "dmake dmake" + If you have a previously compiled version of dmake; + + "make.sh" + If you have none of the above make utilities. This is + an APW command file. + +============= +RELEASE NOTES +============= + +1. Dmake requires Gno/ME v2.0.0 or later. + +2. New users, _please_ read the manual page and this file in detail. Many +of your questions are already answered. However, if something has you +"stumped", post a question to comp.sys.apple2.gno. A postscript version +of the man page (landscape orientation, 2 pages per sheet) is available +with this archive (dmake.ps.Z) via ftp to caltech, grind, or pindarus. + + The file dmake.ps.Z is for dmake v3.8 patch level 1. For the IIgs +version, all information in that man page is applicable, but there is further +info in this file with which you should familiarize yourself. + +3. Ensure you have your gshrc in your $HOME directory when dmake is run; +this affects commands where sub-shells must be started. + +4. The default settings in startup.mk will cause Orca/C to use the +"#pragma ignore" directive. If you don't like this, remove the "-i" from +the definitions of CFLAGS, MAINFLAGS, and VAFLAGS in startup.mk. + +5. Use of dmake with the default startup.mk file requires the use of Soenke +Behrens' occ front end for Orca/C. If you don't like this, you just have to +modify startup.mk appropriately. See the man page. + +6. See the end of this file for copying and use restrictions. + +===== + FAQ +===== + +Q: Can I use Unix makefiles with dmake? + +A: Yes, in fact dmake is originally a Unix utility. In particular, it + expects action lines to start with tabs (although spaces can be used + if invoked with the -B flag or .NOTABS macro), and has a rich macro + language. + +Q: When I include "rm *.o *.root" as an action, I get "dmake: Error -- + rm: No such file or directory", yet it works when typed from the shell. + +A: In many installations of Gno, rm is an alias for "cp -p rm". In order + for dmake to find a command it must either be a file within your $PATH, + or be prefixed by a '+' (as in "+rm") so that it can be executed with a + sub-shell. + + In order use the rm command without invoking a sub-shell, use either + "cp -p rm" or "$(RM)". Note that if you use wildcards in the filename + arguments then a sub-shell will still be invoked. + +Q: dmake is rebuilding a target for which the dependancies have not changed + since the last build. Why? + +A: On the Apple IIgs, file timestamps do not have seconds. As a safety + precaution, any target which has the same timestamp as at least one of + its prerequisites will be remade. Therefore, if a target was made within + a minute of updating its prequisite, it will be remade later. + +Q: Does it matter where I install the dmake files? + +A: No, as long as the location of the startup.mk file is defined by the + MAKESTARTUP environment variable. You must also edit the recipe for + $(RM) in startup.mk to reflect the location of rmroot(1). + +Q: I'm getting unexpected output when using the function macros such + as $(subst,.o,.c text). Is this a bug? + +A: This is often due to inappropriate spaces placed in the macro definition. + Note that there are no spaces after the commas in function macros. + + +========================= +KNOWN BUGS & "TO DO" LIST +========================= + +If a target and recipe similar to + file.o : file file.h fubar.h schnib.h + cc -c file.c +is given without an explicit recipe for making "file", the default rules in +startup.mk will result in a stack overflow. If you are not using the debugging +version of dmake, this will likely result in a crash to the monitor, as no +stack checking is done in the optimized version. It is unclear whether this is +a bug with Orca/C or one introduced while porting dmake to Gno; it does not +appear in the SVR4 version. The debugging version of dmake is labelled +as such in it's rVersion resource fork (see getvers(1)) and is available via +anonymous ftp from menaik.cs.ualberta.ca in /pub/gno. + +The top level makefile should be fixed so that a make can be done from the +top level directory. + +The Gno version should be incorporated into the base version. + + +======= +CHANGES -- Ignore comments in square brackets; they are for internal +======= reference, and therefore may not be otherwise meaningful. + +v1.0 -- Added a check on the return value of setenv() in execp() + when using default $PATH. [runargv.c] + + Made a few changes to the lenviron library, upon which dmake + is dependant. This included fixing a bug where the first + (physically) listed directory in $PATH would not be checked for + executables. + + Sources are provided for this distribution. Sources were also + cleaned up and placed in the expected hierarchy. + + The assignment of segments was redone; hopefully they're now + grouped a bit better according to usage. + + On startup, dmake will do a memory purge provided that the + environment variable NOPURGE is _not_ set. Unless there are + complaints, I will be leaving this implemented as a + system("purge >.null"); + + Under conditions where dmake removes the intermediate *.o files, + it was not removing the respective *.root files. This is now fixed + Through a bit of a kludge; the default .REMOVE rule defined in + startup.mk now invokes "rmroot" as well as "rm". "rmroot" will + delete .root files for any .a or .o files given as arguments on its + command line. The .a and .o files don't actually have to exist. + "rmroot" will ignore any other arguments. + + Cleaned up the code a bit with the help of gcc. There were spots + where sloppy conditionals may have made incorrect branches. + + Fixed bug where, if an absolute path name was used in a recipe, + there was an inappropriate free. [runargv.c: strdup'd path in execp] + + The bug with using a makefile in other than the current directory + (the -f option) seems to be fixed, although it wasn't explicitly + actioned. Let me know if you find a problem with it. + + Similarily, the $00/0000 memory trashing bug seems to be fixed. + This may be related to a reference to memory free'd in execp(). + + Fixed bug where the $(shell ...) function macro was trying to dup + stdin rather than stdout. [function.c: _exec_shell()] + + Standard location of files has been changed. Binaries by default + are now located in /usr/local/bin, and startup.mk in /usr/local/lib. + Man pages remain in /usr/man. + + Added a $(MV) macro to startup.mk for the default move command. + + Added rules to startup.mk to allow Pascal targets to be correctly + made. + +v0.4.3b -- No changes to dmake's executable, but the startup.mk file + was modified as listed below. These changes make it pretty + well necessary to use Soenke's occ, but there's not much purpose + to using dmake without occ, anyway. + + Use of the -r flag for CFLAGS, VAFLAGS was discontinued. + It may cause confusion to new users when their compilations + don't behave as expected, and knowledgable users can + always redefine the flags for themselves. + + Redefined standard rules for making *.a, *.o, and *.root + files to be more intelligent; appropriate use is made of + occ's -a flag to achieve the desired result rather than + just forcing *.o files. In other words, a *.a target will + use -a1, a *.o target will use -a0, and a *.root target + will use neither flag. + +v0.4.2b -- Initial release to general Apple II community (no source + included with this release). + + Only the optimized executable was included with the distribution, + not the debug executable. + + Fixed bug that was causing dmake to exit prematurely when + sent a ^Z. [Incorrect handling of wait()'s return value in + runargv.c::execp().] + + The definition of $(SHELLMETAS) in /usr/bin/startup.mk was + modified to match gsh. One biggie here is that using the + ':' pathname delimiter will no longer result in a subshell + being started. + + Macros $(MAINFLAGS) and $(VAFLAGS) have been added to + /usr/bin/startup.mk for use with makedmake. + +v0.4.1b -- Fixed bug that make ^C do Bad Things (in particular, dmake + would hang waiting for a child that no longer existed). + [#pragma databank 1 for quit.c] + + Added rules for resource (*.rez) files to startup.mk. + + Changed definition of $(CC) in startup.mk from "scc" to "occ" + to correspond with the renaming of Soenke Behrens' front end + for the Orca/C compiler. + + Added default CFLAG of -a0 in startup.mk to force the production + of *.o object files. This will be over-ridden if the user's + makefile uses a macro definition of + CFLAGS = + rather than + CFLAGS += + + All *.c files were massaged with the new version of ccprep that + uses the __CCFRONT__ macro. + + Changed the makefile search to search for just "makefile.mk", + followed by "Makefile"; the last search for "makefile" was + removed. This is easily restored should GS/OS obtain a case- + sensitive file system by _not_ using -DNO_CASE when compiling + ruletab.c. + + [dirbrk.c::If_root_path() and runargv.c::execp()] + dmake's definition of an absolute path name has changed from a + string containing '/' to either: + + A string beginning with either '/' or ':' and with + length greater than 1; or + + A string beginning with either ".d" or ".D" and with at least + least one character following either a ':' or '/'; or + + A string beginning with a digit (GS/OS prefix). + + Using '-' at the beginning of an action previously had no effect. + This has been fixed so that it will ignore errors generated by the + recipe line, similar to the effect of "dmake -k" or ".IGNORE". + [make.c::Exec_commands() -- When setting kludge_int1, there was + a mix of long integers and unsigned long integers.] + + Avoided Orca/C bug that appeared in optimized version -- dmake + wouldn't be able to find its recipes. [Cannot use loop-invariant + optimization on getinp.c] + + Added an initial memory purge when dmake starts up. This won't + work if purge is not in the $(PATH), so it should be changed to + a normal purge routine rather than a system("purge"). + +v0.4.0b -- Fixed bug where return values of commands are always ignored. + [execp returning 0 unless exec failed. Recovered return values + during wait(2).] + + The responsibility of case sensitivity for file names has been + dumped on to GS/OS via access(3) and fopen(3). Dmake no longer + uses code that is inherently case sensitive for file names. + [Changed in lenviron exec.c] + + Prefixes (numeric or otherwise) are now permitted in path names. + This applies to both actions within the makefile and to default + macros in /usr/bin/startup.mk. If partial pathnames are used, + they still must reside within $PATH. [Changed in lenviron exec.c] + + The opening of temporary files was (I think) fixed, but cannot + be tested until an _execve(2) bug in kern v2.0.4 is fixed. + [access(3) not showing execute permissions for directories. + Changed in tempnam.c] + + Bug was squashed that caused a stack error and abort when trying + to display warnings or errors. [va code extracted from main.c + to va.c, compiled with -O8 and no -G] + + Fixed bug that caused partial pathnames to be prefixed by "./". + (From interim version.) [execp() in runargv.c]. + + $PATH search direction matches gsh now (meaning that it's backwards + from the "norm"). [lenviron::exec.c] + + Lengths of rule actions are no longer limited to 256 bytes; they are + limited by either available memory, or the maximum size allowed + as arguments to Kexecve. Realistically, you should try to keep + them under 1k for portability reasons; some make's use system(2) + which often has a 1k limit. + +v0.3.0b -- Cleaned up code, deleted a lot of debug routines, started GS- + specific documentation. + +v0.2.3a -- Working with Gno v2.0.1 (Gno v1.1 never released?). + +v0.2.2a -- Working with Gno v1.0. Awaiting Gno v1.1 prior to beta release. + +v0.2.1a -- Entire (almost) rewrite using virgin source. Everything proto- + typed. Still crashing, but simple rules work. + +v0.2.0a -- First modifications made by Devin Reade. Crashing miserably. + +v0.1.0 -- Port to the IIgs started by James Brookes. + + +=========== +BUG REPORTS +=========== + +send to (in order of priority): + + glyn@cs.ualberta.ca or + gdr@myrias.ab.ca or + dreade@gpu.srv.ualberta.ca or + glyn@ersys.edm.ab.ca If you still can't reach me, try + the comp.sys.apple2 newsgroup. + +Ensure you tell me what the makefile recipes are that are causing the +problems. + +It is much more helpful to me if you can dump the output (both stdout and +stderr) from a problem dmake run to a file and send it to me. [I don't +need it in a separate file from your email, but the exact output of dmake +is more helpful than an approximation from memory.] + +================ +ACKNOWLEDGEMENTS +================ + +dmake was written by Dennis Vadura, dvadura@watdragon.uwaterloo.ca +CS DEPT, University of Waterloo, Waterloo, Ont., Canada. + +The initial port of dmake to the Apple IIgs was made by James Brookes. + +I would like to thank the following people for their help during beta +testing: Soenke Behrens, James Brookes, Mike Hackett, Kevin Henigan, +Dave Huang, Gerald Lester, and Dave Tribby. And of course thanks to +Jawaid Bazyar and Procyon for making it all possible. + +GNO and GNO/ME are trademarks of Procyon Enterprises Incorporated. + +This program includes routines developed by the University of California, +Berkeley, and its contributors. + +Unix is a registered trademark of AT&T Bell Laboratories. + +This program contains material from the Orca/C Run-Time Libraries, +copyright 1987-1994 by Byte Works, Inc. Used with permission. + +Apple IIgs and GS/OS are registered trademarks of Apple Computer, Inc. + +========================== +COPYRIGHT and DISTRIBUTION +========================== + +-- 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. diff --git a/dmake/readme/apple.mac b/dmake/readme/apple.mac new file mode 100644 index 0000000..110b19f --- /dev/null +++ b/dmake/readme/apple.mac @@ -0,0 +1,42 @@ +Notes on the Macintosh implementation of dmake: + +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. + +I was getting memory trashing errors when I was reading in +environmental variables >4K with the -e option. I had trouble +tracking down exactly what was causing the problem, so decided it +was easier to just clip the length before sending it to the dmake +parser. I arbitrarily picked 1K as the maximum length, figuring +it was highly unlikely anyone really needed a variable longer than +that from within a makefile. (This error may be related to the +value you set for MAXLINELENGTH, so to be safe, you should keep +it >1K.) + +In order to run dmake, you must set (and export) the environmental +variable "OS" to "mac". + +Finally, dmake looks for the file startup.mk in +"{MPW}tools:{DMSTARTUPDIR}". "DMSTARTUPDIR" can be defined if you +want to override the default tools directory location. + +Micah Doyle +micah@leland.Stanford.EDU diff --git a/dmake/readme/atari.tos b/dmake/readme/atari.tos new file mode 100644 index 0000000..bb74e97 --- /dev/null +++ b/dmake/readme/atari.tos @@ -0,0 +1,13 @@ +This file describes the Atari-tos distribution of dmake. + +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 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 readme/msdos file for further information. + +-dennis diff --git a/dmake/readme/cover b/dmake/readme/cover new file mode 100644 index 0000000..770872c --- /dev/null +++ b/dmake/readme/cover @@ -0,0 +1,60 @@ +This is the DMAKE Version 3.8 distribution. DMAKE is a Make like tool that +has been written by me and has been used by individuals at the University of +Waterloo. This release replaces the previous version 3.7 release which is no +longer supported. Please read the file 'readme/release' which accompanies +this distribution and describes details of this release (This note is found +in readme/cover). + +dmake is available for anonymous ftp from watmsg.uwaterloo.ca address is +129.97.141.9. It is in the pub/dmake directory, set your mode to binary, +and copy either: + + dmake38.tar.Z - compressed tar archive + dmake38.zoo - zoo archive + dmake38-msdos-exe.zoo - MSDOS executable zoo archive + + dmake38.shar01 - xx part shar archive, get all parts + ... + dmake38.sharxx + + dmake38.patchY - Patch Y for dmake 3.8 + +Note that all archives are created on a UNIX system. This means that the +distributions heading for DOS-land need to have the turned into a +. There exist a number of filters for doing this (sed comes to mind), +and is easily run over each file using a UNIX shell script. Thus I don't +provide two different versions of the archives. + +dmake is different from other versions of make in that it supports significant +enhancements (See the man page). A short summary of the more important +ones follows: + + . support for portable makefiles + . runs on many platforms (DOS, generic unix [sysv and bsd4.3], + apollo, OS/2, Atari, and many others) + . significantly enhanced macro facilities + . transitive closure on inference graph + . sophisticated inference algorithm + . 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 + . highly configurable + . 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 + +All code found in this distribution is original and written by me except where +noted in the source and the following: + +- dbug/dbug package from Fred Fish (dmake DEBUG=1, to make a debugging version + of dmake) + +- malloc.c package in dbug/malloc from the NET, see the directory for + attribution. + +-dennis diff --git a/dmake/readme/msdos b/dmake/readme/msdos new file mode 100644 index 0000000..7ee6132 --- /dev/null +++ b/dmake/readme/msdos @@ -0,0 +1,135 @@ +Notes on the MSDOS implementation of dmake. + +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: + tcc - Turbo C 2.0 compile. + tccswp - Turbo C 2.0 compile of swapping dmake. + bcc - Borland C++ 2.0 compile. + bccswp - Borland C++ 2.0 compile of swapping dmake. + msc40 - Microsoft C 4.0 compile. + msc50 - Microsoft C 5.0 compile. + msc51 - Microsoft C 5.1 compile. + msc60 - Microsoft C 6.0 compile. + msc40swp - Microsoft C 4.0, MASM 5.1 compile of swapping dmake. + msc50swp - Microsoft C 5.0, MASM 5.1 compile of swapping dmake. + msc51swp - Microsoft C 5.1, MASM 5.1 compile of swapping dmake. + msc60swp - Microsoft C 6.0, MASM 5.1 compile of swapping dmake. + ztc - Zortech C++ 2.1 compile. + ztcswp - Zortech C++ 2.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 compile. The Turbo-C version, as a final step, + invokes tlink with two response files. The second of these response files, + named in msdos/tccdos/mk*.bat, contains absolute path names to Turbo-C + libraries. You may need to edit these before getting a successful binary + linked. + + By default the batch files make an executable that will run on an 8088 + cpu and up. You can change that by making the initial version and then + editing the config.mk files found in either msdos/tccdos or msdos/mscdos + (depending on the compiler you use), and selecting a diferrent cpu type by + supplying the appropriate compiler flags. You then need to remake dmake + again but this time use dmake itself, see below. + + 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 the appropriate objects directory. + + +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 them are listed in the readme/options file. For example, if you + are using MSDOS, with Turbo-C then the valid settings are: + + set OS=msdos + set OSRELEASE=tccdos + set OSENVIRONMENT= + + dmake searches for an initial startup file, you should set the environment + variable MAKESTARTUP to contain the full path to the startup file, eg: + + set MAKESTARTUP=d:\usr\lib\startup.mk + + The dmake makefile has several variables that can be user specified and + default to reasonable values if not set. + + MODEL - defines the model to compile, valid values are + {s,c,m, or l}, defaults to 'l' (ie. large) model + if unspecified. + + MSC_VER - defines the version of Microsoft C in use, should be set to + one of 4.0, 5.0, 5.1 or 6.0; defaults to 6.0. + + SWAP - If set to 'y', compile the dmake swapping version of + spawnvpe. This has the effect of turning on swapping of the + executable to disk if the MSDOS version is made. + + DEBUG - If set to '1' then make the debugging version of dmake, this + will also set MODEL to 'l'. + + To set the above variables you must specify them on the dmake command line + or insert them into the makefile.mk definition. + + +Memory Requirements and Swapping: +--------------------------------- + The swapping code currently only swaps to DISK, I have left hooks + in to accomodate XMS and EMS, I have some code that performs the + necessary XMS/EMS accesses but have not incorporated it in yet. + It appears that a ramdisk seems to work just fine. If anyone + wishes to fill in the hooks please do and I'll be happy to include + them in future distributions. + + +^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. + + 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. It 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/os2 b/dmake/readme/os2 new file mode 100644 index 0000000..7ae0b30 --- /dev/null +++ b/dmake/readme/os2 @@ -0,0 +1,141 @@ +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. The port was made possible by files supplied +by: + + Duncan Booth -- (duncanb@ibmpcug.co.uk, Bix:jrichards) + Kai Uwe Rommel -- (rommel@lan.informatik.tu-muenchen.dbp.de), + +For which I am grateful. I have taken the two ports and integrated them +into a single port using the structure supplied by Duncan Booth, and some +files and OS2'ism supplied by Kai Rommel. + +If there are any problems with the port then please let myself or one of the +two people above know. I will then attempt to fix the problem. I do not +have access to an OS/2 box to verify any problems myself. + + +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: + msc40 - Microsoft C 4.0 compile. + msc50 - Microsoft C 5.0 compile. + msc51 - Microsoft C 5.1 compile. + msc60 - Microsoft C 6.0 compile. + ibm - IBM C2 compile. + + 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.cmd target'. + + The command file runs a second command 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 compile. + + By default the command files make an executable that will run on an 8088 + cpu and up. You can change that by making the initial version and then + editing the config.mk file found in os2/mscdos and selecting a diferrent + cpu type by supplying the appropriate compiler flags. + You then need to remake dmake again but this time use dmake itself, + see below. + + +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 (not needed for OS/2) + + These three variables should be defined in your environment. Valid values + for them are listed in the dmake makefile.mk file. For example, if you + are using OS/2, with Microsoft-C then the valid settings are: + + set OS=os2 + set OSRELEASE=mscdos + + dmake searches for an initial startup file, you should set the environment + variable MAKESTARTUP to contain the full path to the startup file, eg: + + set MAKESTARTUP=\init\dmake.ini + + The dmake makefile has several variables that can be user specified and + default to reasonable values if not set. + + MODEL - defines the model to compile, valid values are + {s,c,m, or l}, defaults to 'l' (ie. large) model + if unspecified. + + MSC_VER - defines the version of Microsoft C in use, should be set to + one of 4.0, 5.0, 5.1 or 6.0; defaults to 6.0. + + DEBUG - If set to '1' then make the debugging version of dmake, this + will also set MODEL to 'l'. + + To set the above variables you must specify them on the dmake command line + or insert them into the makefile.mk script. + + + +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: + + $(INIT)/dmake.ini + + 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. The OS/2 directory contains files required by Kai Rommel's compiler + shell. However you do not need the compiler shell to build dmake. + + 5. 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/patch1 b/dmake/readme/patch1 new file mode 100644 index 0000000..9cf3521 --- /dev/null +++ b/dmake/readme/patch1 @@ -0,0 +1,70 @@ +dmake Version 3.8 Patch #1 +========================== + +Nature: This patch fixes the anoying problem with POSIX_NAME_MAX and NAME_MAX +------- incompatibility that I introduced with version 3.8. I hope this + makes all of the problems go away. I may have gotten it wrong for + some systems (mac, atari, os2) if so then please let me know and + I shall add the fix. + +Availability: +------------- + This patch is available for anonymous ftp from watmsg.uwaterloo.ca + (129.97.141.9) as: + + pub/dmake/dmake38-patch1.Z + + You must apply the patch to version 3.8 PL0 of dmake. If you do not + want to apply the patch yourself you can get the full distribution + from watmsg. It has the patch applied. To get the whole + distribution grab the files that most suit your unpacking + facilities. + + pub/dmake/dmake38.tar.Z - compressed tar archive + pub/dmake/dmake38.zoo - zoo archive + pub/dmake/dmake38-msdos-exe.zoo - MSDOS executable zoo archive + pub/dmake/dmake38.shar01 - xx part shar archive + ... (get all parts) + pub/dmake/dmake38.sharxx + + To apply the patch simply uncompress it and run the result through + /bin/sh. The patch requires the availability of the patch program + in order to function correctly. Everything is done for you by the + script. + +=============== Summary of fixes ============================================= +- For Coherent version of dmake, added the equivalent of + + #define void int + + through the use of -D command line flag. + +- Minor tweaks to the control-C handling under MSDOS, it should now terminate + more quickly and deliver correct error codes back to dmake. + +- replaced the use of _POSIX_NAME_MAX as the file component length to, + NAME_MAX, this should greatly enhance portability as I have supplied + NAME_MAX definitions for those OS's that don't potentially have it already. + (bloody braindamage here folks) + +- Deleted the file unix/explode.c. The code there is no longer used and + should not have been distributed (blush). Oh well, dese tings do 'appen! + +- Deleted the use of #elif define(blah) to satisfy broken compilers. + +- Added a 'limits.h' file to unix/bsd43 (it's blank, normal distributions of + BSD43 don't come with this file) + +- Compiles and works using gcc under Sun OS 4.1.1, hopefully now works elsewhere + using gcc as well. Let me know of problems you may come accross. + +- Changed Sun tempnam.c code to make sure we don't write to a static string. + Also fixed a call to Closefile() in state.c to not pass any parameters. + +- Added -X flag to allow users to suppress execution of #! line at start of + makefile. + +- Fixed arlib.c for 386i boxes, it now correctly sets PORTAR prior to + including . + +- Cleaned up output of dmake -h a little. diff --git a/dmake/readme/release b/dmake/readme/release new file mode 100644 index 0000000..87aac6e --- /dev/null +++ b/dmake/readme/release @@ -0,0 +1,109 @@ +dmake Version 3.8 +================= + +FULL RELEASE OF DMAKE, REPLACES VERSION 3.7 + +Nature: This release is an attempt at addressing all of the little obscure +------- bugs and "features" that still remained in dmake and often caused + spurious or incorrect behaviour. As such there is no major new + functionality but several small enhancements to make life a little + more interesting. + + This distribution advances dmake to Version 3.8, patch level 0. + + +Availability: +------------- + dmake is available via anonymous ftp from watmsg.uwaterloo.ca + (129.97.141.9) as: + + pub/dmake/dmake38.tar.Z - compressed tar archive + pub/dmake/dmake38.zoo - zoo archive + pub/dmake/dmake38-msdos-exe.zoo - MSDOS executable zoo archive + pub/dmake/dmake38.shar01 - xx part shar archive + ... (get all parts) + pub/dmake/dmake38.sharxx + + and comes in several archive formats. Choose the one that best + suits your needs. + +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. + + +DETAILS OF ENHANCEMENTS/TWEAKS: +=============================== +- Added the following functionality: + + #! command + + is scanned for and recognized if it is the first line of your makefile. + The command string is expanded and executed. + The command is restricted in that it cannot be a command requiring a shell + for it's execution. The values of the command line macros have been set + and are available for execution purposes. This is not as general as one + would like but it is not bad for bootstrapping different non dmake + makefiles. If the command result code is zero, then dmake continues parsing + its input and processes the makefile. If the result is non-zero dmake + exits. (suggested by Paul Sander, paul@hal.com) + +- Allowed the inclusion of white space inside quoted prerequisites. + i.e. you can now say: + + foo : "some stuff" + + and have "some stuff" treated as a single prerequisite. The mod is + necessary to allow for prerequisites that contain $(shell ... ) expansion + scripts and other simillar function macros. + +- Changed the following piece of code to be more in line with dmake + philosophy. That is, $(macname:str=sub) now expands 'sub' prior to + performing the substitution, however if '-A' or '.AUGMAKE := yes' are + specified then the expansion is suppressed. + +- Added _POSIX_NAME_MAX to the source, on any stat if the basename of a file + is larger than the value of _POSIX_NAME_MAX then it returns 0. You must + define _POSIX_NAME_MAX in a lower level config if you want it to override + the default in {unix,msdos,mac,os2,atari}/config.h. + +- Disallowed export of macros whose names contain the characters "+=:*" + as these are valid macro assignment operators and we don't want to cause + trouble when we go to reparse the environment again. Perhaps the fix + could be a little bit less drastic, but for now it seems reasonable. + +- Tweaked the output of -v to more accurately show which of a set of :: + targets is getting made. The info was there so I might as well use it. + +- Added a seperate directory substructure for XENIX since I was having trouble + linking properly in the generic SYSVR3 environment. Looks as if you pretty + much need 'make xenixpwd' since XENIX uses popen to call getcwd. + If you use 'make xenix' and your implementation of xenix uses popen this + causes dmake to get confused about child processes and occationally + complain that it lost one. + +- Cleaned up OS/2 building scripts, and made sure that OS2 define is checked + where needed. + + +DETAILS OF BUG FIXES: +===================== +- Fixed the handling of :: targets if they appear first in the makefile. + This was incorrectly handled by the internal DAG construction code, ugly!. + +- Fixed an output statement in dump.c so that macro values containing % + signs are correctly printed (guess where that broke, blush). + +- Fixed a bug in dealing with .SETDIR=a targets and multiprocessing. Too + obscure to describe but annoying if you stumble onto it. + +- Fixed DIRSEPSTR macro to be user modifiable (as the manpage claims :-) + so that people can change it in startup.mk depending on shell/OS + (mostly effects DOS and/or OS/2 implementations). + +- Fixed a bug dealing with complex .IF/.ELIF/.ELSE/.END expressions. + It now correctly selects only a single matching instance in a complex + .IF/.ELIF/.ELSE/.END expr. diff --git a/dmake/rulparse.c b/dmake/rulparse.c new file mode 100644 index 0000000..f511e01 --- /dev/null +++ b/dmake/rulparse.c @@ -0,0 +1,1325 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/rulparse.c,v 1.1 1992/01/24 03:27:57 dvadura 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@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. +-- +-- LOG +-- $Log: rulparse.c,v $ + * Revision 1.1 1992/01/24 03:27:57 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +/* prototypes for local functions */ +static void _add_global_prereq ANSI((CELLPTR)); +static int _add_root ANSI((CELLPTR)); +static void _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 = _strspn( 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 ) ) { + /* 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 = _strdup( tok ); + + attr |= at; + } + else { + int tmp; + + tmp = _is_special( tok ); + if( _is_percent( tok ) ) percent++; + + if( percent ) + if( targets != NIL(CELL) ) + Fatal( "Multiple targets are not allowed in %% rules" ); + else + cp->ce_flag |= F_PERCENT; + + if( special ) + Fatal( "Special target must appear alone", tok ); + else if( !(cp->ce_flag & F_MARK) ) { + cp->ce_link = targets; /* targets are stacked in this list*/ + cp->ce_flag |= F_MARK | F_EXPLICIT; + targets = cp; + + special = tmp; + } + else if( !(cp->ce_attr & A_LIBRARY) ) + Warning("Duplicate entry [%s] in target list",cp->CE_NAME); + } + } + 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) ) + 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; + + 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); + + 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; + + /* 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) ); + + /* 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 = (*_strspn(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; + + 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 ignore = (((Glob_attr | attr) & A_IGNORE) != 0); + int pushed = FALSE; + 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; + + 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( fil != NIL(FILE) ) + Parse( fil ); + else if( !((Glob_attr | attr) & A_IGNORE) ) + Fatal( "Include file %s, not found", name ); + } + + if( pushed ) Pop_dir(FALSE); + attr &= ~(A_IGNORE|A_SETDIR); + } + 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 */ + char *p; /* temporary char pointer */ + CELLPTR prev_cell; /* pointer for .UPDATEALL processing */ + CELLPTR first_cell; /* pointer for .UPDATEALL processing */ + int update; /* A_UPDATEALL attribute flag */ + int smagic = 0; /* collective amount of magic :-) */ + int tflag = FALSE; /* set to TRUE if we add target to root */ + + DB_ENTER( "_do_targets" ); + + if( update = ((attr & A_UPDATEALL) != 0) ) + if( targets == NIL(CELL) ) + Fatal( ".UPDATEALL attribute requires non-empty list of targets" ); + + first_cell = prev_cell = 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); + smagic |= magic; + + if( !(op & R_OP_DCL ) && (tg1->ce_flag & F_MULTI) && !magic ) + Fatal( "Inconsistency in inference rules for %s", tg1->CE_NAME ); + + if( magic ) + do { + _build_graph( op, tg1, prereq ); + if( prereq != NIL(CELL) ) prereq = prereq->ce_link; + } while( prereq != NIL(CELL) ); + else if( !(tg1->ce_flag & F_SPECIAL) && + (prereq == NIL(CELL)) && + (p = _is_magic( tg1->CE_NAME )) != NIL(char)) + smagic |= _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 ); + + if( update ) { + if( smagic ) Fatal( ".UPDATEALL attribute not legal in meta rule" ); + + /* Check this as it would break another circular .UPATEALL list if + * we blindly assign it and it is part of another list already. */ + if( tg1->ce_all != NIL(CELL) ) + Fatal( "Target [%s] appears on multiple .UPDATEALL lists" ); + + tg1->ce_all = prev_cell; + if( prev_cell == NIL(CELL) ) first_cell = tg1; + prev_cell = 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; + if( first_cell != NIL(CELL) ) first_cell->ce_all = prev_cell; + + + /* 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. + * Cannot happen for F_PERCENT targets. (ie. in that case targets is always + * not NIL) */ + + 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 ); + + /* Fix up the ce_link pointers so that when we go to attach a recipe in + * Bind_targets to rules we get the right thing if it's an .UPDATEALL :: + * recipe */ + if( update ) { + for( tp1=NIL(CELL),tg1=prev_cell; tg1!=first_cell; tg1=tg1->ce_all ) { + tg1->ce_link = tp1; + tp1 = tg1; + } + tg1->ce_link = tp1; + targets = first_cell; + } + + /* 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 .. or + . 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 = _substr( 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 = Augmake ? name[strlen(name)-1] == '~' : 0; + + tmp = _strjoin( test ? "s.%" : "%", name, -1, FALSE); + if( test ) tmp[ strlen(tmp)-1 ] = '\0'; + + return(tmp); +} + + + +static void +_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. + + It also assumes that target cell has F_PERCENT set already. */ +int op; +CELLPTR target; +CELLPTR prereq; +{ + LINKPTR edl; + CELLPTR edge; + int match; + + DB_ENTER( "_build_graph" ); + DB_PRINT( "%", ("Building graph for [%s : %s]", target->CE_NAME, + (prereq == NIL(CELL)) ? "" : prereq->CE_NAME) ); + + if( prereq != NIL(CELL) ) { + char *name = prereq->CE_NAME; + int len = strlen(name); + + if( *name == '\'' && name[len-1]=='\'' ){ + _add_global_prereq( prereq ); + name[len-1] = '\0'; + strcpy(name, name+1); + DB_VOID_RETURN; + } + } + + /* Search the list of prerequisites for the current target and see if + * any of them match the current %-meta : prereq pair. NOTE that %-metas + * are built as if they were F_MULTI targets. */ + + match = FALSE; + for( edl=target->ce_prq; edl != NIL(LINK); edl=edl->cl_next ) { + edge = edl->cl_prq; + + DB_PRINT( "%", ("Trying to match [%s]", edge?edge->CE_NAME:"(nil)") ); + + if( (!edge->ce_prq && !prereq) + || ( edge->ce_prq + && edge->ce_prq->cl_prq == prereq + && ( edge->ce_dir == _sv_setdir + || ( edge->ce_dir + && _sv_setdir + && !strcmp(edge->ce_dir,strchr(_sv_setdir,'=')+1) + ) + ) + ) + ) { + match = TRUE; + break; + } + } + + if( match ) { + /* match is TRUE hence, we found an edge joining the target and the + * prerequisite so reset the new edge's how values to reflect the new + * recipe etc. */ + 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") ); + + if( !(target->ce_flag & F_DFA) ) { + Add_nfa( target->CE_NAME ); + target->ce_flag |= F_DFA; + } + edge = _make_multi(target); + if( prereq ) Add_prerequisite(edge, prereq, 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_VOID_RETURN; +} + + +static CELLPTR +_make_multi( tg ) +CELLPTR tg; +{ + CELLPTR cp; + + /* This first handle 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; + + 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); + } + else { + cp->ce_flag &= ~(F_RULES|F_MULTI); + cp->ce_attr &= ~A_SEQ; + cp->ce_prq = NIL(LINK); + cp->ce_index = 0; + } + cp->ce_count = ++tg->ce_index; + cp->ce_flag |= F_TARGET; + + 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; + + 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 ) { + dir = strchr( set_dir, '=' ) + 1; + + if( cp->ce_dir ) + Warning( "Multiple .SETDIR for %s ignored", cp->CE_NAME ); + else + if( *dir ) cp->ce_dir = _strdup(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 + + 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': attr = (strcmp(name, "EPILOG")) ? 0 : A_EPILOG; break; + case 'I': attr = (strcmp(name, "IGNORE")) ? 0 : A_IGNORE; break; + case 'L': attr = (strcmp(name, "LIBRARY")) ? 0 : A_LIBRARY; break; + case 'M': attr = (strcmp(name, "MKSARGS")) ? 0 : A_MKSARGS; 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 + .INCLUDEDIRS .MAKEFILES .REMOVE .KEEP_STATE +*/ +char *tg; +{ + DB_ENTER( "_is_special" ); + + if( *tg++ != '.' ) DB_RETURN( 0 ); + + switch( *tg ) + { + 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 'M': + if( !strcmp( tg, "MAKEFILES" ) ) DB_RETURN( ST_REST ); + break; + + case 'E': + if( !strcmp( tg, "ERROR" ) ) DB_RETURN( ST_REST ); + else if( !strcmp( tg, "EXPORT" ) ) DB_RETURN( ST_EXPORT ); + break; + + case 'G': + if( !strcmp( tg, "GROUPPROLOG" )) DB_RETURN( ST_REST ); + else if( !strcmp( tg, "GROUPEPILOG" )) DB_RETURN( ST_REST ); + break; + + case 'K': + if( !strcmp( tg, "KEEP_STATE" ) ) DB_RETURN( ST_KEEP ); + 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 + .. or . + 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( !Augmake ) + return( NIL(char) ); + + /* np points at the second . of .. string. + * if the special target is of the form . then np points at the + * first . in the token. */ + + return( np ); +} + + +static int +_add_root(tg) +CELLPTR tg; +{ + int res = FALSE; + + if( !Target && !(tg->ce_flag & (F_SPECIAL|F_PERCENT)) ) { + Add_prerequisite( Root, tg, FALSE, TRUE ); + + tg->ce_flag |= F_TARGET; + tg->ce_attr |= A_FRINGE; + res = TRUE; + } + + return(res); +} diff --git a/dmake/stat.c b/dmake/stat.c new file mode 100644 index 0000000..e354fd2 --- /dev/null +++ b/dmake/stat.c @@ -0,0 +1,248 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/stat.c,v 1.1 1992/01/24 03:27:58 dvadura 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@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. +-- +-- LOG +-- $Log: stat.c,v $ + * Revision 1.1 1992/01/24 03:27:58 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + + +static int _check_dir_list ANSI((CELLPTR, CELLPTR, int)); + +#ifdef DBUG + /* Just a little ditty for debugging this thing */ + static time_t + _do_stat( name, lib, sym ) + char *name; + char *lib; + char **sym; + { + time_t res; + DB_ENTER( "_do_stat" ); + + res = Do_stat(name, lib, sym); + DB_PRINT( "stat", ("Statted [%s,%s,%d,%ld]", name, lib, sym, res) ); + + DB_RETURN( res ); + } +#define DO_STAT(A,B,C) _do_stat(A,B,C) +#else +#define DO_STAT(A,B,C) Do_stat(A,B,C) +#endif + +static char *_first; /* local storage of first attempted path */ + +PUBLIC void +Stat_target( cp, setfname )/* +============================= + 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; +{ + 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 ); + + 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 _strdup */ + + 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 = _strjoin( ".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 ); + + /* Check just .SOURCE */ + if( !res && (srchp != NIL(HASH)) ) + res = _check_dir_list( cp, srchp->CP_OWNR, setfname ); + + /* 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 *)); + + if( !cp->ce_time && Tmd && *Tmd && cp->ce_lib ) { + cp->ce_lib=Build_path(Tmd,cp->ce_lib); + cp->ce_time = DO_STAT(name, cp->ce_lib, NIL(char *)); + } + + 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) ) { + 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; + } + } + 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; + + DB_VOID_RETURN; +} + + + +static int +_check_dir_list( cp, sp, setfname )/* +===================================== + 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; +{ + register 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 and 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 = Build_path( dir, name ); + + res = ((cp->ce_time = DO_STAT(path,NIL(char),NIL(char *))) != (time_t)0L); +#if 0 +I think this will break a lot of things! + /* It didn't work and TMD macro has a value so try to stat it + * relative to the original MAKEDIR directory. */ + if( Tmd && !*Tmd && !res ) { + char *p = _strdup(path); + path = Build_path(Tmd,p); FREE(p); + res = ((cp->ce_time = DO_STAT(path,NIL(char),NIL(char *))) != (time_t)0L); + } +#endif + + /* Have to use _strdup 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 ); + _first = nodup ? NIL(char) : _strdup(path); + fset = 1; + } + + DB_PRINT( "stat", ("_first [%s], path [%s]", _first, path) ); + if( dir != lp->cl_prq->CE_NAME ) FREE(dir); + } + } + + 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 0000000..886439f --- /dev/null +++ b/dmake/state.c @@ -0,0 +1,230 @@ +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/state.c,v 1.2 1992/04/07 04:42:46 dvadura 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@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. +-- +-- LOG +-- $Log: state.c,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Removed a parameter to call of Closefile(), it doesn't need one. + * + * Revision 1.1 1992/01/24 03:27:05 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 = _strdup(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( 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 ; ist_next ) { + char *cmnd = Expand(sp->st_string); + + (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 0000000..e6a9805 --- /dev/null +++ b/dmake/stdmacs.h @@ -0,0 +1,65 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/stdmacs.h,v 1.1 1992/01/24 03:29:36 dvadura 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@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. +-- +-- LOG +-- $Log: stdmacs.h,v $ + * Revision 1.1 1992/01/24 03:29:36 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#ifndef MACROS_h +#define MACROS_h + +/* stupid AIX and Mac MPW define __STDC__ as special, but defined(__STDC__) is false, and + * it's value is nothing */ +#if !defined(__STDC__) && !defined(_AIX) && !defined(_MPW) +#define __STDC__ 0 +#endif + +#if __STDC__ || defined(__TURBOC__) +#define ANSI(x) x +#else +#define ANSI(x) () +#endif + +#define NIL(p) ((p*)NULL) + +#if !defined(atarist) +#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 0000000..cd659cd --- /dev/null +++ b/dmake/struct.h @@ -0,0 +1,259 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/struct.h,v 1.1 1992/01/24 03:29:32 dvadura 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@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. +-- +-- LOG +-- $Log: struct.h,v $ + * Revision 1.1 1992/01/24 03:29:32 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 */ + char *ht_name; /* name of this cell */ + char *ht_value; /* cell value if and */ + uint32 ht_hash; /* actual hash_value 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; + + + +/* 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 tcell *ce_all; /* link for grouping UPDATEALL cells*/ + struct tcell *ce_setdir; /* SETDIR ROOT pointer for this cell*/ + struct tcell *ce_link; /* link for temporary list making */ + + struct lcell *ce_prq; /* list of prerequisites for cell */ + 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 */ + + 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 + + +/* 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; + + +/* 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; + + + +/* 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 0000000..a445194 --- /dev/null +++ b/dmake/sysintf.c @@ -0,0 +1,690 @@ +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/sysintf.c,v 1.2 1992/04/07 04:42:46 dvadura 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() +-- STAT() +-- Remove_prq() +-- +-- C-LIB SPECIFIC: (should be present in your C-lib) +-- utime() +-- time() +-- getenv() +-- putenv() +-- getcwd() +-- signal() +-- chdir() +-- tempnam() +-- +-- 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. +-- +-- LOG +-- $Log: sysintf.c,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Replaced the use of _POSIX_NAME_MAX and MAX_PATH_LEN by NAME_MAX and + * PATH_MAX respectively. + * + * Revision 1.1 1992/01/24 03:27:08 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 _strdup the name and return make the +** pointer pointed at by sym point at it. Not handled for now! +*/ +PUBLIC time_t +Do_stat(name, lib, member) +char *name; +char *lib; +char **member; +{ + 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( strlen(basename(name)) > NAME_MAX ) + return((time_t)0L); + else + return( (STAT(name,&buf)==-1 || (Augmake && (buf.st_mode & S_IFDIR))) + ? (time_t)0L + : (time_t) buf.st_mtime + ); +} + + + +/* 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 + 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( 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; + } + + if( (Packed_shell = shell||group||(*_strpbrk(cmd, Shell_metas)!='\0')) ) { + 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 = _stradd(ename, value, FALSE); + + p = envstr+strlen(ename); /* Don't change this code, _stradd 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) + extern char **environ; +#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( signal(SIGINT, SIG_IGN) != SIG_IGN ) + signal( SIGINT, fn ); + if( signal(SIGQUIT, SIG_IGN) != SIG_IGN ) + signal( SIGQUIT, fn ); +} + + + +/* +** Clear any previously set signals +*/ +PUBLIC void +Clear_signals() +{ + if( signal(SIGINT, SIG_IGN) != SIG_IGN ) + signal( SIGINT, SIG_DFL ); + if( signal(SIGQUIT, SIG_IGN) != SIG_IGN ) + signal( SIGQUIT, SIG_DFL ); +} + + + +/* +** Set program name +*/ +PUBLIC void +Prolog(argc, argv) +int argc; +char* argv[]; +{ + char buf[50]; + + Pname = (argc == 0) ? DEF_MAKE_PNAME : argv[0]; + sprintf( buf, "dmake-%d-root", GETPID ); + Root = Def_cell( buf ); + 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 = _strjoin( 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 ) + printf( "%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 ) { + fprintf( stderr, "%s: Error code %d, while making '%s'", + Pname, status, target->ce_fname ); + + if( ignore || Continue ) { + fputs( " (Ignored)\n", stderr ); + } + else { + fputc( '\n', stderr ); + + if( !(target->ce_attr & A_PRECIOUS) ) + 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) ) + Remove_file( target->ce_fname ); +} + + +PUBLIC void +Update_time_stamp( cp ) +CELLPTR cp; +{ + HASHPTR hp; + CELLPTR tcp; + int phony = ((cp->ce_attr&A_PHONY) != 0); + + tcp = cp; + do { + 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 ) + Stat_target(tcp, -1); + + 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 %ld\n", + Pname, tcp->CE_NAME, tcp->ce_time ); + + Unlink_temp_files( tcp ); + tcp->ce_flag |= F_MADE; + tcp->ce_attr |= A_UPDATED; + tcp = tcp->ce_all; + } + while( tcp != NIL(CELL) && tcp != cp ); + + + /* 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) && + !Force; + + if( rem ) { + CELLPTR tmp = prq; + do { + (Add_prerequisite(tcp,prq,FALSE,FALSE))->cl_flag |= F_TARGET; + prq->ce_flag &= ~F_REMOVE; + prq = prq->ce_all; + } + while( prq != NIL(CELL) && prq != tmp ); + flag = TRUE; + } + } + + if( flag ) { + Remove_prq( tcp ); + + 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/arlib.c b/dmake/tos/arlib.c new file mode 100644 index 0000000..9bf4bca --- /dev/null +++ b/dmake/tos/arlib.c @@ -0,0 +1,504 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/tos/arlib.c,v 1.1 1992/01/24 03:27:09 dvadura 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@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. +-- +-- LOG +-- $Log: arlib.c,v $ + * Revision 1.1 1992/01/24 03:27:09 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include +#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. */ + +#define ASCARCH 1 /* ASCII time stored in archive */ +#define LC 1 /* Turn on library cacheing */ +#define DECODE_ALL_AR_FIELDS 0 /* decode only fields make needs*/ + +#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 32 /* Longest file name in archive */ +#define MAXMNAME 8 /* Max module name < MAXFNAME */ + + +/* This struct is used to pass the library and member information 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 * )); + +#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; + + +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, "rb")) == 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 ); +} + + +PUBLIC 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, "rb+")) == 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( strcmp(argp->member, arp->ar_name) == 0 ) { + 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( strcmp(argp->member, arp->ar_name) == 0 ) { + _check_cache( argp->member, argp->lib, &now, TRUE ); + ar_touch(f, now ); + + return( TRUE ); + } + + return( FALSE ); /* continue scan */ +} + + + + +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 ANSI((char *)); + register char *p; + struct ar_hdr arhdr; /* external archive header */ + off_t offset; /* member seek offset */ + +#if ASCARCH + char magic[SARMAG]; +#else + unsigned short word; +#endif + + fseek( f, 0L, 0 ); /* Start at the beginning of the archive file */ + +#if ASCARCH + fread( magic, sizeof(magic), 1, f ); + if( strncmp(magic, ARMAG, SARMAG) != 0 ) return( -1 ); +#else + fread( (char*)&word, sizeof(word), 1, f ); + if( word != ARMAG ) return( -1 ); +#endif + + /* scan the library, calling `function' for each member + */ + while( 1 ) { + if( fread((char*) &arhdr, sizeof(arhdr), 1, f) != 1 ) break; + offset = ftell(f); + strncpy(_ar.ar_name, arhdr.ar_name, sizeof(arhdr.ar_name)); + + for( p = &_ar.ar_name[sizeof(arhdr.ar_name)]; + --p >= _ar.ar_name && *p == ' ';); + + p[1] = '\0'; + if( *p == '/' ) *p = 0; /* Only SysV has trailing '/' */ + +#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 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_size = arhdr.ar_size; + _ar.ar_uid = arhdr.ar_uid; + _ar.ar_gid = arhdr.ar_gid; +#endif +#endif + + if( (*function)(f, &_ar, arg) ) return( 1 ); + fseek( f, offset + (_ar.ar_size+1 & ~1L), 0 ); + } + + if( !feof(f) ) return( -1 ); + 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, - (off_t) (sizeof(arhdr) - sizeof(arhdr.ar_name)), 1); + +#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/tos/config.h b/dmake/tos/config.h new file mode 100644 index 0000000..99c4de4 --- /dev/null +++ b/dmake/tos/config.h @@ -0,0 +1,53 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/tos/config.h,v 1.1 1992/01/24 03:27:15 dvadura 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@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. +-- +-- LOG +-- $Log: config.h,v $ + * Revision 1.1 1992/01/24 03:27:15 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include + +/* 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() Malloc(-1L) + +/* Define the getcwd function that is used in the code, since BSD does + * not have getcwd, but call it getwd instead. */ +extern char *getcwd ANSI((char *, int)); + +/* Don't need the const decl */ +#define CONST + +/* a small problem with pointer to voids on some unix machines needs this */ +#define PVOID void * diff --git a/dmake/tos/config.mk b/dmake/tos/config.mk new file mode 100644 index 0000000..282f6ba --- /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 += arlib.c ruletab.c runargv.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/dirbrk.c b/dmake/tos/dirbrk.c new file mode 100644 index 0000000..c9c7503 --- /dev/null +++ b/dmake/tos/dirbrk.c @@ -0,0 +1,53 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/tos/dirbrk.c,v 1.1 1992/01/24 03:27:11 dvadura 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@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. +-- +-- LOG +-- $Log: dirbrk.c,v $ + * Revision 1.1 1992/01/24 03:27:11 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" +#include + +/* tos 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 +*/ +int +If_root_path(name) +char *name; +{ + return( (strchr(DirBrkStr, *name) != NIL(char)) || + (isalpha(*name) && name[1] == ':') ); +} diff --git a/dmake/tos/make.sh b/dmake/tos/make.sh new file mode 100644 index 0000000..78dd08b --- /dev/null +++ b/dmake/tos/make.sh @@ -0,0 +1,59 @@ +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 basename.c +mv basename.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/arlib.c +mv arlib.o objects +gcc -c -I. -Itos -O tos/ruletab.c +mv ruletab.o objects +gcc -c -I. -Itos -O tos/runargv.c +mv runargv.o objects +gcc -c -I. -Itos -O msdos/rmprq.c +mv rmprq.o objects +gcc -c -I. -Itos -O msdos/dirbrk.c +mv dirbrk.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/startup.mk startup.mk diff --git a/dmake/tos/public.h b/dmake/tos/public.h new file mode 100644 index 0000000..e111b80 --- /dev/null +++ b/dmake/tos/public.h @@ -0,0 +1,150 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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 *)); +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)); +int If_root_path ANSI((char *)); + +#endif diff --git a/dmake/tos/putenv.c b/dmake/tos/putenv.c new file mode 100644 index 0000000..215c53f --- /dev/null +++ b/dmake/tos/putenv.c @@ -0,0 +1,87 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/tos/putenv.c,v 1.1 1992/01/24 03:27:17 dvadura 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@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. +-- +-- LOG +-- $Log: putenv.c,v $ + * Revision 1.1 1992/01/24 03:27:17 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include +#include + +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/rmprq.c b/dmake/tos/rmprq.c new file mode 100644 index 0000000..a169f10 --- /dev/null +++ b/dmake/tos/rmprq.c @@ -0,0 +1,49 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/tos/rmprq.c,v 1.1 1992/01/24 03:27:16 dvadura 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@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. +-- +-- LOG +-- $Log: rmprq.c,v $ + * Revision 1.1 1992/01/24 03:27:16 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" +#include "alloc.h" + +void +Remove_prq( tcp ) +CELLPTR tcp; +{ + tcp->ce_flag &= ~(F_MADE|F_VISITED); + tcp->CE_HOW->hw_flag &= ~(F_MADE|F_VISITED); + tcp->ce_time = 0L; + + Make( tcp, tcp->CE_HOW, NIL(CELL) ); +} diff --git a/dmake/tos/ruletab.c b/dmake/tos/ruletab.c new file mode 100644 index 0000000..82011ba --- /dev/null +++ b/dmake/tos/ruletab.c @@ -0,0 +1,51 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/tos/ruletab.c,v 1.1 1992/01/24 03:27:12 dvadura 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@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. +-- +-- LOG +-- $Log: ruletab.c,v $ + * Revision 1.1 1992/01/24 03:27:12 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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/runargv.c b/dmake/tos/runargv.c new file mode 100644 index 0000000..bacaa4c --- /dev/null +++ b/dmake/tos/runargv.c @@ -0,0 +1,115 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/tos/runargv.c,v 1.1 1992/01/24 03:27:13 dvadura Exp $ +-- SYNOPSIS -- run a sub process. +-- +-- DESCRIPTION +-- Use spawn to run a subprocess. +-- +-- 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. +-- +-- LOG +-- $Log: runargv.c,v $ + * Revision 1.1 1992/01/24 03:27:13 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include +#include +#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; +{ + int status; + char **argv; + char path[MAX_PATH_LEN+1]; + + argv = Pack_argv( group, shell, cmd ); + _add_child(target, ignore); + + /* save and restore current working directory across a spawn call */ + strcpy(path, Get_current_dir()); + status = spawnvp(P_WAIT, *argv, argv); + Set_dir(path); + + 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/tos/startup.h b/dmake/tos/startup.h new file mode 100644 index 0000000..b17fa7b --- /dev/null +++ b/dmake/tos/startup.h @@ -0,0 +1,7 @@ +/* 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)/etc/startup.mk", diff --git a/dmake/tos/startup.mk b/dmake/tos/startup.mk new file mode 100644 index 0000000..022e958 --- /dev/null +++ b/dmake/tos/startup.mk @@ -0,0 +1,136 @@ +# Generic UNIX DMAKE startup file. Customize to suit your needs. +# Should work for both SYSV, and BSD 4.3 +# 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 => RCS is installed. +_HAVE_SCCS := # yes => SCCS is installed. + +# Applicable suffix definitions +A := .olb # Libraries +E := # Executables +F := .f # Fortran +O := .o # Objects +P := .p # Pascal +S := .s # Assembler sources +V := ,v # RCS suffix + +# Recipe execution configurations +SHELL := /bin/sh +SHELLFLAGS := +GROUPSHELL := $(SHELL) +GROUPFLAGS := +SHELLMETAS := |();&<>?*][$$:\\#`'" +GROUPSUFFIX := .bat +DIVFILE = $(TMPFILE) + +# Standard C-language command names and flags + CPP := /gnu/lib/cpp # C-preprocessor + CC := gcc # C-compiler and flags + CFLAGS += + + AS := /gnu/lib/as # Assembler and flags + ASFLAGS += + + LD = $(CC) # Loader and flags + LDFLAGS += + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(MFLAGS) + +# Definition of Print command for this system. + PRINT = lpr + +# Language and Parser generation Tools and their flags + YACC := yacc # standard yacc + YFLAGS += + YTAB := y.tab # yacc output files name stem. + + LEX := lex # standard lex + LFLAGS += + LEXYY := lex.yy # lex output file + +# Other Compilers, Tools and their flags + PC := pc # pascal compiler + RC := f77 # ratfor compiler + FC := f77 # fortran compiler + + CO := co # check out for RCS + COFLAGS += -q + + AR := gar # archiver + ARFLAGS+= ruv + + RM := /gnu/bin/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 : %$P ; $(PC) $(PFLAGS) -c $< + %$O : %$S ; $(AS) $(ASFLAGS) $< + %$O : %.cl ; class -c $< + %$O : %.e %.r %.F %$F + $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $< + +# Executables + %$E : %$O ; $(LD) $(LDFLAGS) -o $@ $< $(LDLIBS) + +# lex and yacc rules + %.c : %.y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@ + %.c : %.l ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@ + +# This rule tells how to make *.out from it's immediate list of prerequisites +# UNIX only. + %.out :; $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +# RCS support +.IF $(_HAVE_RCS) + % : %$V $$(@:d)RCS/$$(@:f)$V;- $(CO) $(COFLAGS) $@ + .NOINFER : %$V $$(@:d)RCS/$$(@:f)$V +.END + +# SCCS support +.IF $(_HAVE_SCCS) + % : s.% ; get $< + .NOINFER : s.% +.END + +# Recipe to make archive files. +%$A : +[ + $(AR) $(ARFLAGS) $@ $? + $(RM) $(RMFLAGS) $? + ranlib $@ +] + +# 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) + +#include +#include + +#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/86ix/ar.h b/dmake/unix/86ix/ar.h new file mode 100644 index 0000000..cdc4c25 --- /dev/null +++ b/dmake/unix/86ix/ar.h @@ -0,0 +1,2 @@ +#define PORTAR 1 +#include "/usr/include/ar.h" diff --git a/dmake/unix/86ix/config.h b/dmake/unix/86ix/config.h new file mode 100644 index 0000000..5a32d76 --- /dev/null +++ b/dmake/unix/86ix/config.h @@ -0,0 +1,54 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/unix/386ix/config.h,v 1.1 1992/01/24 03:28:02 dvadura 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@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. +-- +-- LOG +-- $Log: config.h,v $ + * Revision 1.1 1992/01/24 03:28:02 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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 + +/* Define the getcwd function that is used in the code, since BSD does + * not have getcwd, but call it getwd instead. */ +extern char *getcwd ANSI((char *, int)); + +/* Define setvbuf, SysV doesn't have one */ +#define setvbuf(fp, bp, type, len) setbuf( fp, NULL ); + +/* We don't care about CONST */ +#define CONST + +/* a small problem with pointer to voids on some unix machines needs this */ +#define PVOID void * diff --git a/dmake/unix/86ix/config.mk b/dmake/unix/86ix/config.mk new file mode 100644 index 0000000..4c1eac9 --- /dev/null +++ b/dmake/unix/86ix/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/86ix/make.sh b/dmake/unix/86ix/make.sh new file mode 100644 index 0000000..e731eb1 --- /dev/null +++ b/dmake/unix/86ix/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 basename.c +mv basename.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 -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/basename.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 +cp unix/386ix/startup.mk startup.mk diff --git a/dmake/unix/86ix/public.h b/dmake/unix/86ix/public.h new file mode 100644 index 0000000..796aa7a --- /dev/null +++ b/dmake/unix/86ix/public.h @@ -0,0 +1,149 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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(()); + +#endif diff --git a/dmake/unix/86ix/startup.mk b/dmake/unix/86ix/startup.mk new file mode 100644 index 0000000..44f4e19 --- /dev/null +++ b/dmake/unix/86ix/startup.mk @@ -0,0 +1,136 @@ +# Generic UNIX DMAKE startup file. Customize to suit your needs. +# Should work for both SYSV, and BSD 4.3 +# 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 # yes => SCCS is installed. + +# Applicable suffix definitions +A := .a # Libraries +E := # Executables +F := .f # Fortran +O := .o # Objects +P := .p # Pascal +S := .s # Assembler sources +V := ,v # RCS suffix + +# Recipe execution configurations +SHELL := /bin/sh +SHELLFLAGS := -ce +GROUPSHELL := $(SHELL) +GROUPFLAGS := +SHELLMETAS := |();&<>?*][$$:\\#`'" +GROUPSUFFIX := +DIVFILE = $(TMPFILE) + +# Standard C-language command names and flags + CPP := /lib/cpp # C-preprocessor + CC := cc # C-compiler and flags + CFLAGS += + + AS := as # Assembler and flags + ASFLAGS += + + LD = $(CC) # Loader and flags + LDFLAGS += + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(MFLAGS) + +# Definition of Print command for this system. + PRINT = lpr + +# Language and Parser generation Tools and their flags + YACC := yacc # standard yacc + YFLAGS += + YTAB := y.tab # yacc output files name stem. + + LEX := lex # standard lex + LFLAGS += + LEXYY := lex.yy # lex output file + +# Other Compilers, Tools and their flags + PC := pc # pascal compiler + RC := f77 # ratfor compiler + FC := f77 # fortran compiler + + CO := co # check out for RCS + COFLAGS += -q + + AR := ar # archiver + ARFLAGS+= ruv + + RM := /bin/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 : %$P ; $(PC) $(PFLAGS) -c $< + %$O : %$S ; $(AS) $(ASFLAGS) $< + %$O : %.cl ; class -c $< + %$O : %.e %.r %.F %$F + $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $< + +# Executables + %$E : %$O ; $(LD) $(LDFLAGS) -o $@ $< $(LDLIBS) + +# lex and yacc rules + %.c : %.y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@ + %.c : %.l ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@ + +# This rule tells how to make *.out from it's immediate list of prerequisites +# UNIX only. + %.out :; $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +# RCS support +.IF $(_HAVE_RCS) + % : %$V $$(@:d)RCS/$$(@:f)$V;- $(CO) $(COFLAGS) $@ + .NOINFER : %$V $$(@:d)RCS/$$(@:f)$V +.END + +# SCCS support +.IF $(_HAVE_SCCS) + % : s.% ; get $< + .NOINFER : s.% +.END + +# Recipe to make archive files. +%$A : +[ + $(AR) $(ARFLAGS) $@ $? + $(RM) $(RMFLAGS) $? + ranlib $@ +] + +# 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) + +#endif + +#endif /* _STDLIB_INCLUDED_ */ diff --git a/dmake/unix/86ix/time.h b/dmake/unix/86ix/time.h new file mode 100644 index 0000000..b9fb543 --- /dev/null +++ b/dmake/unix/86ix/time.h @@ -0,0 +1,10 @@ +/* +** 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 0000000..14e7c80 --- /dev/null +++ b/dmake/unix/arlib.c @@ -0,0 +1,558 @@ +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/unix/RCS/arlib.c,v 1.2 1992/04/07 04:42:46 dvadura 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@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. +-- +-- LOG +-- $Log: arlib.c,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Added definition of PORTAR for syn 386i boxen as they are a bit broken. + * + * Revision 1.1 1992/01/24 03:28:06 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* Sun unix on 386i's has a broken ar.h that does not assume PORTAR format + * by default, so we fix it here. */ +#ifdef i386 +#define PORTAR 1 +#endif + +#include +#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 DECODE_ALL_AR_FIELDS +#define DECODE_ALL_AR_FIELDS 0 /* decode only fields make needs*/ +#endif + +#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 * )); + +#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( strcmp(argp->member, arp->ar_name) == 0 ) { + 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( strcmp(argp->member, arp->ar_name) == 0 ) { + _check_cache( argp->member, argp->lib, &now, TRUE ); + ar_touch(f, now ); + + return( TRUE ); + } + + return( FALSE ); /* continue scan */ +} + + + + +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 ANSI((char *)); + register char *p; + struct ar_hdr arhdr; /* archive member header */ + int nsize; /* size of member name */ +#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 '/' */ + +#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 +#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( (*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.h b/dmake/unix/bsd43/config.h new file mode 100644 index 0000000..bb0e4f7 --- /dev/null +++ b/dmake/unix/bsd43/config.h @@ -0,0 +1,58 @@ +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/unix/bsd43/RCS/config.h,v 1.2 1992/04/07 04:42:46 dvadura 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@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. +-- +-- LOG +-- $Log: config.h,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Deleted definition of PORTAR for sun 386i boxen. + * + * Revision 1.1 1992/01/24 03:28:07 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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 + +/* Define the getcwd function that is used in the code, since BSD does + * not have getcwd, but call it getwd instead. */ +extern char* getwd ANSI((char*)); +#define getcwd(buf,siz) getwd(buf) + +/* We don't care about CONST */ +#define CONST + +/* a small problem with pointer to voids on some unix machines needs this */ +#define PVOID void * + +/* Sequent dynix doesn't have tzset() Arrrrgh! */ +#define tzset() diff --git a/dmake/unix/bsd43/config.mk b/dmake/unix/bsd43/config.mk new file mode 100644 index 0000000..e999373 --- /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/limits.h b/dmake/unix/bsd43/limits.h new file mode 100644 index 0000000..6e0eebc --- /dev/null +++ b/dmake/unix/bsd43/limits.h @@ -0,0 +1,7 @@ +#include +#include +#include + +#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 0000000..9504e21 --- /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 basename.c +mv basename.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/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 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/basename.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/putenv.o objects/tempnam.o objects/utime.o objects/setvbuf.o +cp unix/bsd43/startup.mk startup.mk diff --git a/dmake/unix/bsd43/public.h b/dmake/unix/bsd43/public.h new file mode 100644 index 0000000..796aa7a --- /dev/null +++ b/dmake/unix/bsd43/public.h @@ -0,0 +1,149 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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(()); + +#endif diff --git a/dmake/unix/bsd43/putenv.c b/dmake/unix/bsd43/putenv.c new file mode 100644 index 0000000..167ea08 --- /dev/null +++ b/dmake/unix/bsd43/putenv.c @@ -0,0 +1,87 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/unix/bsd43/putenv.c,v 1.1 1992/01/24 03:28:09 dvadura 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@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. +-- +-- LOG +-- $Log: putenv.c,v $ + * Revision 1.1 1992/01/24 03:28:09 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include +#include + +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 0000000..9b3b1a8 --- /dev/null +++ b/dmake/unix/bsd43/setvbuf.c @@ -0,0 +1,49 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/unix/bsd43/setvbuf.c,v 1.1 1992/01/24 03:28:10 dvadura Exp $ +-- SYNOPSIS -- setvbuf for BSD +-- +-- DESCRIPTION +-- A sysv call, standard BSD doesn't have this. +-- +-- 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. +-- +-- LOG +-- $Log: setvbuf.c,v $ + * Revision 1.1 1992/01/24 03:28:10 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include + +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/startup.mk b/dmake/unix/bsd43/startup.mk new file mode 100644 index 0000000..44f4e19 --- /dev/null +++ b/dmake/unix/bsd43/startup.mk @@ -0,0 +1,136 @@ +# Generic UNIX DMAKE startup file. Customize to suit your needs. +# Should work for both SYSV, and BSD 4.3 +# 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 # yes => SCCS is installed. + +# Applicable suffix definitions +A := .a # Libraries +E := # Executables +F := .f # Fortran +O := .o # Objects +P := .p # Pascal +S := .s # Assembler sources +V := ,v # RCS suffix + +# Recipe execution configurations +SHELL := /bin/sh +SHELLFLAGS := -ce +GROUPSHELL := $(SHELL) +GROUPFLAGS := +SHELLMETAS := |();&<>?*][$$:\\#`'" +GROUPSUFFIX := +DIVFILE = $(TMPFILE) + +# Standard C-language command names and flags + CPP := /lib/cpp # C-preprocessor + CC := cc # C-compiler and flags + CFLAGS += + + AS := as # Assembler and flags + ASFLAGS += + + LD = $(CC) # Loader and flags + LDFLAGS += + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(MFLAGS) + +# Definition of Print command for this system. + PRINT = lpr + +# Language and Parser generation Tools and their flags + YACC := yacc # standard yacc + YFLAGS += + YTAB := y.tab # yacc output files name stem. + + LEX := lex # standard lex + LFLAGS += + LEXYY := lex.yy # lex output file + +# Other Compilers, Tools and their flags + PC := pc # pascal compiler + RC := f77 # ratfor compiler + FC := f77 # fortran compiler + + CO := co # check out for RCS + COFLAGS += -q + + AR := ar # archiver + ARFLAGS+= ruv + + RM := /bin/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 : %$P ; $(PC) $(PFLAGS) -c $< + %$O : %$S ; $(AS) $(ASFLAGS) $< + %$O : %.cl ; class -c $< + %$O : %.e %.r %.F %$F + $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $< + +# Executables + %$E : %$O ; $(LD) $(LDFLAGS) -o $@ $< $(LDLIBS) + +# lex and yacc rules + %.c : %.y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@ + %.c : %.l ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@ + +# This rule tells how to make *.out from it's immediate list of prerequisites +# UNIX only. + %.out :; $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +# RCS support +.IF $(_HAVE_RCS) + % : %$V $$(@:d)RCS/$$(@:f)$V;- $(CO) $(COFLAGS) $@ + .NOINFER : %$V $$(@:d)RCS/$$(@:f)$V +.END + +# SCCS support +.IF $(_HAVE_SCCS) + % : s.% ; get $< + .NOINFER : s.% +.END + +# Recipe to make archive files. +%$A : +[ + $(AR) $(ARFLAGS) $@ $? + $(RM) $(RMFLAGS) $? + ranlib $@ +] + +# 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) + +#endif + +#endif /* _STDLIB_INCLUDED_ */ diff --git a/dmake/unix/bsd43/string.h b/dmake/unix/bsd43/string.h new file mode 100644 index 0000000..0e7c2c0 --- /dev/null +++ b/dmake/unix/bsd43/string.h @@ -0,0 +1,16 @@ +/* +** BSD does this wrong +*/ +#include + +#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 + diff --git a/dmake/unix/bsd43/tempnam.c b/dmake/unix/bsd43/tempnam.c new file mode 100644 index 0000000..c4617f2 --- /dev/null +++ b/dmake/unix/bsd43/tempnam.c @@ -0,0 +1,78 @@ +/*LINTLIBRARY*/ +#include +#include +#include + +#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 0000000..ad46e51 --- /dev/null +++ b/dmake/unix/bsd43/utime.c @@ -0,0 +1,48 @@ +/* +** change access and modify times of file +*/ +#include +#include +#include +#include + +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 0000000..387c2ae --- /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 0000000..11f916d --- /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 basename.c +mv basename.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/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 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/basename.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/putenv.o objects/tempnam.o objects/utime.o objects/setvbuf.o -luw +cp unix/bsd43/uw/startup.mk startup.mk diff --git a/dmake/unix/bsd43/uw/public.h b/dmake/unix/bsd43/uw/public.h new file mode 100644 index 0000000..796aa7a --- /dev/null +++ b/dmake/unix/bsd43/uw/public.h @@ -0,0 +1,149 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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(()); + +#endif diff --git a/dmake/unix/bsd43/uw/startup.mk b/dmake/unix/bsd43/uw/startup.mk new file mode 100644 index 0000000..b29d98e --- /dev/null +++ b/dmake/unix/bsd43/uw/startup.mk @@ -0,0 +1,136 @@ +# Generic UNIX DMAKE startup file. Customize to suit your needs. +# Should work for both SYSV, and BSD 4.3 +# 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 # yes => SCCS is installed. + +# Applicable suffix definitions +A := .a # Libraries +E := # Executables +F := .f # Fortran +O := .o # Objects +P := .p # Pascal +S := .s # Assembler sources +V := ,v # RCS suffix + +# Recipe execution configurations +SHELL := /bin/sh +SHELLFLAGS := -ce +GROUPSHELL := $(SHELL) +GROUPFLAGS := +SHELLMETAS := |();&<>?*][$$:\\#`'" +GROUPSUFFIX := +DIVFILE = $(TMPFILE) + +# Standard C-language command names and flags + CPP := /lib/cpp # C-preprocessor + CC := cc # C-compiler and flags + CFLAGS += + + AS := as # Assembler and flags + ASFLAGS += + + LD = $(CC) # Loader and flags + LDFLAGS += + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(MFLAGS) + +# Definition of Print command for this system. + PRINT = lpr + +# Language and Parser generation Tools and their flags + YACC := yacc # standard yacc + YFLAGS += + YTAB := y.tab # yacc output files name stem. + + LEX := lex # standard lex + LFLAGS += + LEXYY := lex.yy # lex output file + +# Other Compilers, Tools and their flags + PC := pc # pascal compiler + RC := f77 # ratfor compiler + FC := f77 # fortran compiler + + CO := co # check out for RCS + COFLAGS += -q + + AR := ar # archiver + ARFLAGS+= ruv + + RM := /bin/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) -o $@ $(CFLAGS) -c $< + %$O : %$P ; $(PC) -o $@ $(PFLAGS) -c $< + %$O : %$S ; $(AS) -o $@ $(ASFLAGS) $< + %$O : %.cl ; class -c $< + %$O : %.e %.r %.F %$F + $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $< + +# Executables + %$E : %$O ; $(LD) $(LDFLAGS) -o $@ $< $(LDLIBS) + +# lex and yacc rules + %.c : %.y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@ + %.c : %.l ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@ + +# This rule tells how to make *.out from it's immediate list of prerequisites +# UNIX only. + %.out :; $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +# RCS support +.IF $(_HAVE_RCS) + % : %$V $$(@:d)RCS/$$(@:f)$V;- $(CO) $(COFLAGS) $@ + .NOINFER : %$V $$(@:d)RCS/$$(@:f)$V +.END + +# SCCS support +.IF $(_HAVE_SCCS) + % : s.% ; get $< + .NOINFER : s.% +.END + +# Recipe to make archive files. +%$A : +[ + $(AR) $(ARFLAGS) $@ $? + $(RM) $(RMFLAGS) $? + ranlib $@ +] + +# 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) += 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 0000000..796aa7a --- /dev/null +++ b/dmake/unix/bsd43/vf/public.h @@ -0,0 +1,149 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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(()); + +#endif diff --git a/dmake/unix/bsd43/vf/startup.mk b/dmake/unix/bsd43/vf/startup.mk new file mode 100644 index 0000000..44f4e19 --- /dev/null +++ b/dmake/unix/bsd43/vf/startup.mk @@ -0,0 +1,136 @@ +# Generic UNIX DMAKE startup file. Customize to suit your needs. +# Should work for both SYSV, and BSD 4.3 +# 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 # yes => SCCS is installed. + +# Applicable suffix definitions +A := .a # Libraries +E := # Executables +F := .f # Fortran +O := .o # Objects +P := .p # Pascal +S := .s # Assembler sources +V := ,v # RCS suffix + +# Recipe execution configurations +SHELL := /bin/sh +SHELLFLAGS := -ce +GROUPSHELL := $(SHELL) +GROUPFLAGS := +SHELLMETAS := |();&<>?*][$$:\\#`'" +GROUPSUFFIX := +DIVFILE = $(TMPFILE) + +# Standard C-language command names and flags + CPP := /lib/cpp # C-preprocessor + CC := cc # C-compiler and flags + CFLAGS += + + AS := as # Assembler and flags + ASFLAGS += + + LD = $(CC) # Loader and flags + LDFLAGS += + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(MFLAGS) + +# Definition of Print command for this system. + PRINT = lpr + +# Language and Parser generation Tools and their flags + YACC := yacc # standard yacc + YFLAGS += + YTAB := y.tab # yacc output files name stem. + + LEX := lex # standard lex + LFLAGS += + LEXYY := lex.yy # lex output file + +# Other Compilers, Tools and their flags + PC := pc # pascal compiler + RC := f77 # ratfor compiler + FC := f77 # fortran compiler + + CO := co # check out for RCS + COFLAGS += -q + + AR := ar # archiver + ARFLAGS+= ruv + + RM := /bin/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 : %$P ; $(PC) $(PFLAGS) -c $< + %$O : %$S ; $(AS) $(ASFLAGS) $< + %$O : %.cl ; class -c $< + %$O : %.e %.r %.F %$F + $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $< + +# Executables + %$E : %$O ; $(LD) $(LDFLAGS) -o $@ $< $(LDLIBS) + +# lex and yacc rules + %.c : %.y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@ + %.c : %.l ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@ + +# This rule tells how to make *.out from it's immediate list of prerequisites +# UNIX only. + %.out :; $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +# RCS support +.IF $(_HAVE_RCS) + % : %$V $$(@:d)RCS/$$(@:f)$V;- $(CO) $(COFLAGS) $@ + .NOINFER : %$V $$(@:d)RCS/$$(@:f)$V +.END + +# SCCS support +.IF $(_HAVE_SCCS) + % : s.% ; get $< + .NOINFER : s.% +.END + +# Recipe to make archive files. +%$A : +[ + $(AR) $(ARFLAGS) $@ $? + $(RM) $(RMFLAGS) $? + ranlib $@ +] + +# 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) + +#include + +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/coherent/config.h b/dmake/unix/coherent/config.h new file mode 100644 index 0000000..5a89307 --- /dev/null +++ b/dmake/unix/coherent/config.h @@ -0,0 +1,59 @@ +/* +-- COHERENT config.h +-- 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@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. +-- +-- LOG +-- $Log: config.h,v $ + * Revision 1.1 1992/01/24 03:28:39 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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 char *getcwd (); + +/* Define setvbuf, SysV doesn't have one */ +#define setvbuf(fp, bp, type, len) setbuf( fp, NULL ); +#define tzset settz + +/* We don't care about CONST */ +#define CONST +#define void int +typedef paddr_t off_t; + +/* options. . . */ +#define ASCARCH 0 + +/* a small problem with pointer to voids on some unix machines needs this */ +#define PVOID void * diff --git a/dmake/unix/coherent/config.mk b/dmake/unix/coherent/config.mk new file mode 100644 index 0000000..7f90773 --- /dev/null +++ b/dmake/unix/coherent/config.mk @@ -0,0 +1,27 @@ +# 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 +OSDSRC := vfprintf.c getcwd.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) -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/getcwd.c b/dmake/unix/coherent/getcwd.c new file mode 100644 index 0000000..8cd2102 --- /dev/null +++ b/dmake/unix/coherent/getcwd.c @@ -0,0 +1,24 @@ +#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/make.sh b/dmake/unix/coherent/make.sh new file mode 100644 index 0000000..02f7818 --- /dev/null +++ b/dmake/unix/coherent/make.sh @@ -0,0 +1,64 @@ +mkdir objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O infer.c +mv infer.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O make.c +mv make.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O stat.c +mv stat.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O expand.c +mv expand.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O dmstring.c +mv dmstring.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O hash.c +mv hash.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O dag.c +mv dag.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O dmake.c +mv dmake.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O path.c +mv path.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O imacs.c +mv imacs.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O sysintf.c +mv sysintf.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O parse.c +mv parse.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O getinp.c +mv getinp.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O quit.c +mv quit.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O state.c +mv state.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O basename.c +mv basename.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O dmdump.c +mv dmdump.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O macparse.c +mv macparse.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O rulparse.c +mv rulparse.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O percent.c +mv percent.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O function.c +mv function.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O unix/arlib.c +mv arlib.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O unix/dirbrk.c +mv dirbrk.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O unix/rmprq.c +mv rmprq.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O unix/ruletab.c +mv ruletab.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O unix/runargv.c +mv runargv.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O unix/coherent/vfprintf.c +mv vfprintf.o objects +cc -c -I. -Iunix -Iunix/coherent -Dvoid=int -O unix/coherent/getcwd.c +mv getcwd.o objects +cc -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/basename.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/vfprintf.o objects/getcwd.o +cp unix/coherent/startup.mk startup.mk diff --git a/dmake/unix/coherent/public.h b/dmake/unix/coherent/public.h new file mode 100644 index 0000000..796aa7a --- /dev/null +++ b/dmake/unix/coherent/public.h @@ -0,0 +1,149 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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(()); + +#endif diff --git a/dmake/unix/coherent/startup.mk b/dmake/unix/coherent/startup.mk new file mode 100644 index 0000000..44f4e19 --- /dev/null +++ b/dmake/unix/coherent/startup.mk @@ -0,0 +1,136 @@ +# Generic UNIX DMAKE startup file. Customize to suit your needs. +# Should work for both SYSV, and BSD 4.3 +# 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 # yes => SCCS is installed. + +# Applicable suffix definitions +A := .a # Libraries +E := # Executables +F := .f # Fortran +O := .o # Objects +P := .p # Pascal +S := .s # Assembler sources +V := ,v # RCS suffix + +# Recipe execution configurations +SHELL := /bin/sh +SHELLFLAGS := -ce +GROUPSHELL := $(SHELL) +GROUPFLAGS := +SHELLMETAS := |();&<>?*][$$:\\#`'" +GROUPSUFFIX := +DIVFILE = $(TMPFILE) + +# Standard C-language command names and flags + CPP := /lib/cpp # C-preprocessor + CC := cc # C-compiler and flags + CFLAGS += + + AS := as # Assembler and flags + ASFLAGS += + + LD = $(CC) # Loader and flags + LDFLAGS += + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(MFLAGS) + +# Definition of Print command for this system. + PRINT = lpr + +# Language and Parser generation Tools and their flags + YACC := yacc # standard yacc + YFLAGS += + YTAB := y.tab # yacc output files name stem. + + LEX := lex # standard lex + LFLAGS += + LEXYY := lex.yy # lex output file + +# Other Compilers, Tools and their flags + PC := pc # pascal compiler + RC := f77 # ratfor compiler + FC := f77 # fortran compiler + + CO := co # check out for RCS + COFLAGS += -q + + AR := ar # archiver + ARFLAGS+= ruv + + RM := /bin/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 : %$P ; $(PC) $(PFLAGS) -c $< + %$O : %$S ; $(AS) $(ASFLAGS) $< + %$O : %.cl ; class -c $< + %$O : %.e %.r %.F %$F + $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $< + +# Executables + %$E : %$O ; $(LD) $(LDFLAGS) -o $@ $< $(LDLIBS) + +# lex and yacc rules + %.c : %.y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@ + %.c : %.l ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@ + +# This rule tells how to make *.out from it's immediate list of prerequisites +# UNIX only. + %.out :; $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +# RCS support +.IF $(_HAVE_RCS) + % : %$V $$(@:d)RCS/$$(@:f)$V;- $(CO) $(COFLAGS) $@ + .NOINFER : %$V $$(@:d)RCS/$$(@:f)$V +.END + +# SCCS support +.IF $(_HAVE_SCCS) + % : s.% ; get $< + .NOINFER : s.% +.END + +# Recipe to make archive files. +%$A : +[ + $(AR) $(ARFLAGS) $@ $? + $(RM) $(RMFLAGS) $? + ranlib $@ +] + +# 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) + +#endif + +#endif /* _STDLIB_INCLUDED_ */ diff --git a/dmake/unix/coherent/time.h b/dmake/unix/coherent/time.h new file mode 100644 index 0000000..b9fb543 --- /dev/null +++ b/dmake/unix/coherent/time.h @@ -0,0 +1,10 @@ +/* +** 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/coherent/vfprintf.c b/dmake/unix/coherent/vfprintf.c new file mode 100644 index 0000000..0404152 --- /dev/null +++ b/dmake/unix/coherent/vfprintf.c @@ -0,0 +1,190 @@ +/* Portable vfprintf and vprintf by Robert A. Larson */ + +/* 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 + +#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 + +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/config.mk b/dmake/unix/config.mk new file mode 100644 index 0000000..66d283e --- /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 = +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 +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/dirbrk.c b/dmake/unix/dirbrk.c new file mode 100644 index 0000000..497f875 --- /dev/null +++ b/dmake/unix/dirbrk.c @@ -0,0 +1,51 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/unix/dirbrk.c,v 1.1 1992/01/24 03:28:27 dvadura 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@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. +-- +-- LOG +-- $Log: dirbrk.c,v $ + * Revision 1.1 1992/01/24 03:28:27 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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/gno/GS.startup.mk b/dmake/unix/gno/GS.startup.mk new file mode 100644 index 0000000..a51dd70 --- /dev/null +++ b/dmake/unix/gno/GS.startup.mk @@ -0,0 +1,188 @@ +# Startup file for Apple IIgs environment (Apple IIgs version 0.4.3b) +# 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 => RCS is installed. +_HAVE_SCCS := # yes => SCCS is installed. + +# Applicable suffix definitions +A := .lib # Libraries +E := # Executables +F := .f # Fortran +O := .o # Objects +P := .p # Pascal +S := .s # Assembler sources +V := ,v # RCS suffix + +# Recipe execution configuration +SHELL := /bin/gsh +#SHELL := #/bin/sh +#SHELLFLAGS := -ce +GROUPSHELL := $(SHELL) +GROUPFLAGS := +# SHELLMETAS := |();&<>?*][$$:\\#`'" # original +SHELLMETAS := |;&<>?*][$$\\'"~^ # for gsh +GROUPSUFFIX := +DIVFILE = $(TMPFILE) + +# Standard C-language command names and flags + CPP := #/lib/cpp # C-preprocessor + CC := 17/occ # C-compiler and flags + MAINFLAGS += -i # flags for file that has main() + VAFLAGS += -i -O8 # flags for files that use variable + # argument lists. You may want -r, too. + CFLAGS += -i # flags for other objects. You may want + # -r, too. + +# added flags for forcing .a and .o files +# Note that this will screw up with the rules for object files if +# you change $(CC) or $(AS)!! +__AFLAG = -a1 +__OFLAG = -a0 + + AS := $(CC) #as # Assembler and flags + ASFLAGS += -c + + LD = $(CC) # Loader and flags + LDFLAGS += + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(MFLAGS) + +# Definition of Print command for this system. + PRINT = lpr + +# Language and Parser generation Tools and their flags + YACC := bison # !standard yacc + YFLAGS += -y + YTAB := y.tab # yacc output files name stem. + + LEX := flex # !standard lex + LFLAGS += + LEXYY := lex.yy # lex output file + +# Other Compilers, Tools and their flags + PC := compile #pc # pascal compiler + PCFLAGS += -E -P + RC := #f77 # ratfor compiler + FC := #f77 # fortran compiler + REZ := $(CC) # resource compiler + REZFLAGS += + + CO := co # check out for RCS + COFLAGS += -q + + AR := makelib #ar # archiver + ARFLAGS+= #ruv + + RM := /bin/cp -p rm # remove a file command + RMFLAGS += + + CP := /bin/cp # copy files command + CPFLAGS += -f + + MV := /bin/cp -p mv # move files command + MVFLAGS += + +# Implicit generation rules for making inferences. +# We don't provide .yr or .ye rules here. They're obsolete. +# Rules for making *$O +# Note that $(__OFLAG) is an 'occ' thing and that the rules for pascal +# files will not really work since '.a' is generated by compile. + %$O : %.c ; $(CC) $(CFLAGS) $(__OFLAG) -c $< + %$O : %.cc ; $(CC) $(CFLAGS) $(__OFLAG) -c $< +# This is a bit of a kludge since there is no pc(1) yet. + %$O : %$P ; $(PC) $(PFLAGS) $< keep=$* ; $(MV) $*.a $*.o + %$O : %$S ; $(AS) $(ASFLAGS) $(__OFLAG) $< + %$O : %.asm ; $(AS) $(ASFLAGS) $(__OFLAG) $< +# %$O : %.cl ; class -c $< +# %$O : %.e %.r %.F %$F +# $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $< + +# We have two more suffixes for object files, so the above stuff +# is repeated for them. +# Object files ending in '.a': Force '.a' with occ + + %.a : %.c ; $(CC) $(CFLAGS) $(__AFLAG) -c $< + %.a : %.cc ; $(CC) $(CFLAGS) $(__AFLAG) -c $< + %.a : %$P ; $(PC) $(PFLAGS) $< keep=$* + %.a : %$S ; $(AS) $(ASFLAGS) $(__AFLAG) $< + %.a : %.asm ; $(AS) $(ASFLAGS) $(__AFLAG) $< + +# Object files ending in '.root': Force neither '.a' nor '.o' + + %.root : %.c ; $(CC) $(CFLAGS) -c $< + %.root : %.cc ; $(CC) $(CFLAGS) -c $< + %.root : %$P ; $(PC) $(PFLAGS) $< keep=$* + %.root : %$S ; $(AS) $(ASFLAGS) $< + %.root : %.asm ; $(AS) $(ASFLAGS) $< + +# Resource descriptions in REZ format + %.r : %.rez ; $(REZ) $(REZFLAGS) $< + +# Executables + %$E : %$O ; $(LD) $(LDFLAGS) -o $@ $< $(LDLIBES) + +# lex and yacc rules + %.c : %.y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@ + %.c : %.l ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@ + +# This rule tells how to make *.out from it's immediate list of prerequisites +# UNIX only. + %.out :; $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +# RCS support +.IF $(_HAVE_RCS) + % : %$V $$(@:d)RCS/$$(@:f)$V;- $(CO) $(COFLAGS) $@ + .NOINFER : %$V $$(@:d)RCS/$$(@:f)$V +.END + +# SCCS support +.IF $(_HAVE_SCCS) + % : s.% ; get $< + .NOINFER : s.% +.END + +# Recipe to make archive files. +%$A : ; @echo "dmake has no default rule for libraries" +#[ +# $(AR) $(ARFLAGS) $@ $? +# $(RM) $(RMFLAGS) $? +# ranlib $@ +#] + +# DMAKE uses this recipe to remove intermediate targets +# IIgs version note: DON'T put these on the same line while the +# Gno kernel still has the sub-shell bug. (See readme/apple.IIgs.) +.REMOVE : + /usr/local/bin/rmroot $< + $(RM) -f $< + +# AUGMAKE extensions for SYSV compatibility +@B = $(@:b) +@D = $(@:d) +@F = $(@:f) +"*B" = $(*:b) +"*D" = $(*:d) +"*F" = $(*:f) + +#endif +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/unix/RCS/arlib.c,v 1.2 1992/04/07 04:42:46 dvadura 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@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. +-- +-- LOG +-- $Log: arlib.c,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Added definition of PORTAR for syn 386i boxen as they are a bit broken. + * + * Revision 1.1 1992/01/24 03:28:06 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* Sun unix on 386i's has a broken ar.h that does not assume PORTAR format + * by default, so we fix it here. */ +#ifdef i386 +#define PORTAR 1 +#endif + +#include +#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 DECODE_ALL_AR_FIELDS +#define DECODE_ALL_AR_FIELDS 0 /* decode only fields make needs*/ +#endif + +#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 * )); + +#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( char *name, char *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. */ +{ + 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(char *name, char *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. */ +{ + 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( +/* +============================= + 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( strcmp(argp->member, arp->ar_name) == 0 ) { + 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 */ +} + +extern time_t time ANSI(( time_t * )); + +static int +touch_function( +/* +============================== + 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) +{ + time_t now = time((time_t*) NULL); /* Current time. */ + + if( strcmp(argp->member, arp->ar_name) == 0 ) { + _check_cache( argp->member, argp->lib, &now, TRUE ); + ar_touch(f, now ); + + return( TRUE ); + } + + return( FALSE ); /* continue scan */ +} + + + + +static int +ar_scan( +/* +=========================== + 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) +{ + register char *p; + struct ar_hdr arhdr; /* archive member header */ + int nsize; /* size of member name */ +#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 '/' */ + +#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 +#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( (*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( FILE *f, time_t now )/* +==================== + touch module header timestamp. */ +{ + 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( char *name, char *lib, time_t *pmtime, int 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. */ +{ + 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( char *name, char *lib, time_t mtime )/* +=================================== + Cache name in lib along with it's time */ +{ + 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( 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( char *lib, char *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. */ +{ +#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/gno/basename.c b/dmake/unix/gno/basename.c new file mode 100644 index 0000000..30d244d --- /dev/null +++ b/dmake/unix/gno/basename.c @@ -0,0 +1,57 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/basename.c,v 1.1 1992/01/24 03:26:56 dvadura Exp $ +-- SYNOPSIS -- return pointer to last pathname component +-- +-- DESCRIPTION +-- take a file name like /fred/foo/hoe/mary.k, and return the 'mary.k' +-- portion +-- +-- 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. +-- +-- LOG +-- $Log: basename.c,v $ + * Revision 1.1 1992/01/24 03:26:56 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +PUBLIC char* +basename( char *path ) +{ + char *p; + char *q; + + if( *(q = path) ) { + for(; *(p=_strpbrk(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 ); +} diff --git a/dmake/unix/gno/config.h b/dmake/unix/gno/config.h new file mode 100644 index 0000000..22e605f --- /dev/null +++ b/dmake/unix/gno/config.h @@ -0,0 +1,68 @@ +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/unix/bsd43/RCS/config.h,v 1.2 1992/04/07 04:42:46 dvadura 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@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. +-- +-- LOG +-- $Log: config.h,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Deleted definition of PORTAR for sun 386i boxen. + * + * Revision 1.1 1992/01/24 03:28:07 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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 + +/* Define the getcwd function that is used in the code, since BSD does + * not have getcwd, but call it getwd instead. */ +extern char* getwd ANSI((char*)); +#define getcwd(buf,siz) getwd(buf) + +/* We don't care about CONST */ +#define CONST + +/* a small problem with pointer to voids on some unix machines needs this */ +#define PVOID void * + +/* Sequent dynix doesn't have tzset() Arrrrgh! */ +#define tzset() + +#if defined(GNO) +# if !defined (PATH_MAX) +# define PATH_MAX 64 +# endif + +# if !defined(NAME_MAX) +# define NAME_MAX 15 +# endif +#endif /* GNO */ diff --git a/dmake/unix/gno/dag.c b/dmake/unix/gno/dag.c new file mode 100644 index 0000000..6883549 --- /dev/null +++ b/dmake/unix/gno/dag.c @@ -0,0 +1,490 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/dag.c,v 1.1 1992/01/24 03:26:55 dvadura 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@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. +-- +-- LOG +-- $Log: dag.c,v $ + * Revision 1.1 1992/01/24 03:26:55 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +PUBLIC HASHPTR +Get_name( + +/* +=============================== + 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 = _strdup( 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( + 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 +Def_macro( + +/* +================================= + 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( (hp->ht_flag & M_PRECIOUS) && !(flags & M_FORCE) ) { + 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( *_strpbrk(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 \ 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 = _strdup( _strspn( 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 = _strdup( value ); /* take string literally */ + + if( !*p ) { /* check if result is "" */ + FREE( p ); + p = NIL(char); + flags |= M_EXPANDED; + } + else if( *_strpbrk( 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)); + + /* 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 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; + } + + DB_RETURN( hp ); +} + + + +PUBLIC CELLPTR +Def_cell( char *name )/* +================== + Take a string passed in and define it as a cell + If the cell exists then return a pointer to it. */ +{ + 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; + } + 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( CELLPTR cell, CELLPTR prq, int head, int 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. */ +{ + 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( CELLPTR cell )/* +============================= + Clear out the list of prerequisites, freeing all of the LINK nodes, + and setting the list to NULL */ +{ + 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( CELLPTR cp, int fail )/* +========================= + Actually run through the graph */ +{ + 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( + +/* +============================================= + 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 = _strspn( 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 : _strspn( rcp, " \t@-+%" ); + + TALLOC( nsp, 1, STRING ); + nsp->st_string = _strdup( 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( char *rp )/* +====================== + Look at the recipe and return the set of attributes that it defines. */ +{ + 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/unix/gno/db.h b/dmake/unix/gno/db.h new file mode 100644 index 0000000..c28a342 --- /dev/null +++ b/dmake/unix/gno/db.h @@ -0,0 +1,74 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/db.h,v 1.1 1992/01/24 03:29:35 dvadura 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@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. +-- +-- LOG +-- $Log: db.h,v $ + * Revision 1.1 1992/01/24 03:29:35 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#ifndef DB_h +#define DB_h + +#if defined(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/unix/gno/dbug.h b/dmake/unix/gno/dbug.h new file mode 100644 index 0000000..9b75653 --- /dev/null +++ b/dmake/unix/gno/dbug.h @@ -0,0 +1,165 @@ +/****************************************************************************** + * * + * 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 + * + * 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_ 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_; + extern FILE *_db_fp_; + extern char *_db_process_; + extern void _db_doprnt_ (char *format, ...); + extern void _db_printf_ (int _line_, char *keyword, char *format, ...); + extern void _db_push_ (char *control); + extern void _db_pop_ (void); + extern void _db_enter_ (char *_func_, char *_file_, int _line_, char + **_sfunc_, char **_sfile_, int *_slevel_); + extern void _db_return_ (int _line_, char **_sfunc_, char **_sfile_, + int *_slevel_); + extern void _db_pargs_ (int _line_, char *keyword); + extern int _db_keyword_ (char *keyword); + extern void _db_setjmp_ (void); + extern void _db_longjmp_ (void); +# 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/unix/gno/dirbrk.c b/dmake/unix/gno/dirbrk.c new file mode 100644 index 0000000..e5238c8 --- /dev/null +++ b/dmake/unix/gno/dirbrk.c @@ -0,0 +1,78 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log: dirbrk.c,v $ + * Revision 1.1 1992/01/24 03:28:27 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +#if !defined(GNO) +#error "This version of dirbrk.c is for use with the Apple IIgs, only!" +#endif + +/* allowable directory separators */ +char* DirBrkStr = "/:"; + +/* allowable start of full file/device/prefix names */ +static char* PfxBrkStr = "/:0123456789.*@"; + +/* +** 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 +** +** GS/OS Note: The rules here aren't quite right for the above definition, +** but they match the Unix' version functionality. In other +** words, if it starts like a GS/OS volume or device name would +** start, then it returns TRUE. Caveat: It will return FALSE +** if the name is one character long and isn't "*" or "@" or a +** digit. +*/ +PUBLIC int +If_root_path(char *name) +{ + char *p; + + p = strchr(PfxBrkStr, *name); + if (p == NULL) return FALSE; + + if ((*p == '/') || (*p == ':') || (*p == '.')) { + if (*(p+1) == '\0') { + return FALSE; /* "zero" length volume/prefix names not allowed */ + } else return TRUE; + } + + return TRUE; +} diff --git a/dmake/unix/gno/dmake.c b/dmake/unix/gno/dmake.c new file mode 100644 index 0000000..73af215 --- /dev/null +++ b/dmake/unix/gno/dmake.c @@ -0,0 +1,901 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/dmake.c,v 1.3 1992/04/07 04:42:46 dvadura 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 +-- -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 +-- -D n - provide debugging information (Gno only). Higher +-- values of n give more information +-- +-- 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@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. +-- +-- LOG +-- $Log: dmake.c,v $ + * Revision 1.3 1992/04/07 04:42:46 dvadura + * Gnuiffied the source, and prettied up some of the output for -h. + * + * Revision 1.2 1992/04/01 03:31:03 dvadura + * changed use of #elif to satisfy broken compilers. + * + * Revision 1.1 1992/01/24 03:26:58 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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 "patchlvl.h" +#include "version.h" + +#ifdef USE_GETOPT +#include "/usr/include/getopt.h" +#endif + +#ifndef MSDOS +#define USAGE \ +"Usage:\n%s [-P#] [-{f|K} file] [-v{dfimt}] [-ABceEhiknpqrsStTuVxX]\n" +#define USAGE2 \ +"%s [macro[*][+][:]=value ...] [target ...]\n" +#else +#define USAGE \ +"Usage:\n%s [-P#] [-{f|C|K} file] [-v{dfimt}] [-ABceEhiknpqrsStTuVxX]\n" +#define USAGE2 \ +"%s [macro[*][+][:]=value ...] [target ...]\n" +#endif + +#ifdef GNO +# ifdef DEBUG +# include + void begin_stack_check(void); +# endif +#endif + +#if __STDC__ == 1 && !defined(__GNUC__) +void Fatal(char *fmt, ...); +void Warning(char *fmt, ...); +#endif + +static char *sccid = "Copyright (c) 1990,1991 by Dennis Vadura"; +#ifdef __ORCAC__ +char _warn = TRUE; /* warnings on by default */ +#else +static char _warn = TRUE; /* warnings on by default */ +#endif + +static void _do_VPATH(void); +static void _do_ReadEnvironment(void); +#if !defined(__GNUC__) +static void _do_f_flag ANSI((char, char *, char **)); +#else +static void _do_f_flag ANSI((int, char *, char **)); +#endif + +PUBLIC void +main(int argc, char **argv) +{ +#ifdef MSDOS + char* std_fil_name = NIL(char); +#endif +#ifdef USE_GETOPT + int _comd_flag; +#endif + + char* fil_name = NIL(char); + char* state_name = NIL(char); + char* cmdmacs; + char* targets; + FILE* mkfil; + int ex_val; + int m_export; + + DB_ENTER("main"); + +#ifdef GNO + /* make sure we're running Gno */ + if (needsgno() == 0) { + fprintf(stderr,"Requires Gno/ME\n"); + exit (-1); + } + +# ifdef DEBUG + /* check stack usage */ + if (getenv("CHECKSTACK")) begin_stack_check(); +# endif /* DEBUG */ + + /* + * dmake uses mucho memory ... do a purge + * Don't worry if the user doesn't have it; in that case it will + * do nothing. + */ + if (getenv("NOPURGE")==NULL) system("purge >.null"); + + /* initialize environment */ + if (initenv() !=0) { + fprintf(stderr,"Failed to initialize environment. dmake aborted.\n\n"); + exit (-1); + } +#endif /* GNO */ + + /* 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); + +#ifdef DEBUG + DebugLevel = 0; +#endif + + Verbose = V_NONE; + Transitive = TRUE; + Nest_level = 0; + Line_number = 0; + Suppress_temp_file = FALSE; + + /* + * parse the command line + */ + +#ifdef USE_GETOPT +#else + + 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 'k': Continue = TRUE; break; + case 'c': Comment = TRUE; break; + case 'p': Listing = TRUE; break; + case 'r': Rules = FALSE; break; + case 'n': Trace = TRUE; 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; + +#if defined(GNO) +# if defined(DEBUG) + case 'D': + argv++; + DebugLevel = atoi(*argv); + --argc; + if ((DebugLevel==0) && (errno == ERANGE)) Usage(TRUE); + fprintf(stderr,"parse cmd line: value of DebugLevel is %d\n", + DebugLevel); + break; +# endif /* DEBUG */ + + case 'V': Version(); Quit(); break; +#else /* not GNO */ + case 'V': Version(); Quit(NIL(CELL)); break; +#endif /* not GNO */ + 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 'v': + if( p[-1] != '-' ) Usage(TRUE); + while( p[1] ) switch( *++p ) { + case 'd': Verbose |= V_PRINT_DIR; 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; + + 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 = _stradd( cmdmacs, _strdup2(p), TRUE ); + Parse_macro( p, (q[-1]!='+')?M_PRECIOUS:M_DEFAULT ); + } + else { + register CELLPTR cp; + targets = _stradd( targets, _strdup(p), TRUE ); + Add_prerequisite(Root, cp = Def_cell(p), FALSE, FALSE); + cp->ce_flag |= F_TARGET; + cp->ce_attr |= A_FRINGE; + Target = TRUE; + } + } +#endif + /* finished parsing command line */ + + 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 ); + mkfil = NIL(FILE); + } + 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; + register LINKPTR lp; + + cp = Def_cell( ".MAKEFILES" ); + + if( (lp = cp->CE_PRQ) != 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; + } + } + + if( mkfil != NIL(FILE) ) { + char *f = Filename(); + char *p; + + if( strcmp(f, "stdin") == 0 ) f = "-"; + p = _stradd( "-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(); + } + + Push_dir( Start_dir, ".SETDIR", (int)(Glob_attr & A_IGNORE )); + + if( m_export ) { + int i; + + for( i=0; iht_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(); + + Pop_dir( (Glob_attr & A_IGNORE) != 0 ); + Clear_signals(); + Epilog(ex_val); /* Does not return -- EVER */ +} + + +#if defined(__GNUC__) +static void +_do_f_flag(int flag, char *name, char **fname ) +#else +static void +_do_f_flag(char flag, char *name, char **fname ) +#endif +{ + 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(void) +{ + t_attr saveattr = Glob_attr; + + Glob_attr |= A_SILENT; + ReadEnvironment(); + Glob_attr = saveattr; +} + +static void +_do_VPATH(void) +{ + HASHPTR hp; + char *_rl[2]; + + 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. + */ +static void +_set_inc_depth(void) +{ + char buf[10]; + sprintf( buf, "%d", next_file_slot ); + Def_macro( "INCDEPTH", buf, M_MULTI|M_NOEXPORT ); +} + + +PUBLIC FILE * +Openfile(char *name, int mode, int 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. */ +{ + 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: Opening [%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 = _strdup(name); + Line_number = 0; + _set_inc_depth(); + } + + DB_RETURN(fil); +} + + +PUBLIC FILE * +Closefile(void)/* +============= + 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( 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)) ) FREE(ename); + } + + if( fil == NIL(FILE) && hp != NIL(HASH) ) + fil = Openfile(fname=ename, FALSE, FALSE); + + if( rname ) *rname = fname; + + return(fil); +} + + +PUBLIC char * +Filename(void)/* +============ + Return name of file on top of stack */ +{ + return( next_file_slot==0 ? NIL(char) : ftab[next_file_slot-1].name ); +} + + +PUBLIC int +Nestlevel(void)/* +============= + Return the file nesting level */ +{ + return( next_file_slot ); +} + + +#ifndef __ORCAC__ /* extracted to va.c */ + +/* +** print error message from variable arg list +*/ + +static int errflg = TRUE; +static int warnflg = FALSE; + +static void +errargs(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 +*/ +#if __STDC__ == 1 && !defined(__GNUC__) +void +Fatal(char *fmt, ...) +#else +#if defined(_MPW) +Fatal(char *fmt, va_alist) +va_dcl +#else +int +Fatal(fmt, va_alist) +char *fmt; +va_dcl; +#endif +#endif +{ + va_list args; + + va_start(args, fmt); + Continue = FALSE; + errargs(fmt, args); + va_end(args); +} + +/* +** error message and exit (unless -k) +*/ +#if __STDC__ == 1 && !defined(__GNUC__) +void +Error (char *fmt, ...) +#else +#if defined(_MPW) +Error(char *fmt, va_alist) +va_dcl +#else +int +Error(fmt, va_alist) +char* fmt; +va_dcl; +#endif +#endif +{ + va_list args; + + va_start(args, fmt); + errargs(fmt, args); + va_end(args); +} + + +/* +** non-fatal message +*/ +#if __STDC__ == 1 && !defined(__GNUC__) +void +Warning(char *fmt, ...) +#else +#if defined(_MPW) +Warning(char *fmt, va_alist) +va_dcl +#else +int +Warning(fmt, va_alist) +char *fmt; +va_dcl; +#endif +#endif +{ + va_list args; + + va_start(args, fmt); + warnflg = TRUE; + errflg = FALSE; + errargs(fmt, args); + errflg = TRUE; + warnflg = FALSE; + va_end(args); +} + +#endif /* not __ORCAC__ -- for extracted va.c */ + +PUBLIC void +No_ram(void) +{ + Fatal( "No more memory" ); +} + + +PUBLIC int + +Usage( int eflag ) +{ + register char *p; + char *fill; + + fill = _strdup(Pname); + for(p=fill; *p; p++) *p=' '; + + if( eflag ) { + fprintf(stderr, USAGE, Pname); + fprintf(stderr, USAGE2, fill); + } + else { + printf(USAGE, Pname); + fprintf(stderr, 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 +#if defined(GNO) && defined(DEBUG) + puts(" -D level - invoke debugging with status level"); +#endif + puts(" -K file - use file as the .KEEP_STATE file"); + puts(" -v{dfimt} - verbose, indicate what we are doing, (-v => -vdimt)"); + 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\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(" -E - define environment strings as macros"); + puts(" -e - same as -E but done after parsing makefile"); + 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"); + } +#ifdef __ORCAC__ + Quit(); +#else + Quit(NIL(CELL)); +#endif + return 0; +} + + +PUBLIC int +Version(void) +{ + char **p; + + printf("%s - %s, ", Pname, sccid); + +#if !defined (GNO) + printf("Version %s, PL %d\n\n", VERSION, PATCHLEVEL); +#else + printf("Version %s, PL %d\n\tApple IIgs Port Version %s\n\n", VERSION, + PATCHLEVEL, IIGSVERSION); +#endif + + puts("Default Configuration:"); + for (p=Rule_tab; *p != NIL(char); p++) + printf("\t%s\n", *p); + return 0; +} diff --git a/dmake/unix/gno/dmake.h b/dmake/unix/gno/dmake.h new file mode 100644 index 0000000..9e07135 --- /dev/null +++ b/dmake/unix/gno/dmake.h @@ -0,0 +1,183 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/dmake.h,v 1.1 1992/01/24 03:26:50 dvadura Exp $ +-- SYNOPSIS -- global defines for dmake. +-- +-- DESCRIPTION +-- All the interesting bits and flags that dmake uses are defined here. +-- +-- 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. +-- +-- LOG +-- $Log: dmake.h,v $ + * Revision 1.1 1992/01/24 03:26:50 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 \ */ +#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_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 MAX_ATTR A_NOSTATE /* highest valid attribute */ +#define A_LIBRARYM 0x10000 /* target is an archive member */ +#define A_FRINGE 0x20000 /* cell is on the fringe */ +#define A_COMPOSITE 0x40000 /* member of lib(targ) name */ +#define A_FFNAME 0x80000 /* if set, free ce_fname in stat*/ +#define A_UPDATED 0x100000 /* Used to mark cell as updated */ +#define A_ROOT 0x200000 /* True if it is a root prereq */ + + +/* 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 releparse.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 '=' */ +#define M_OP_CL 2 /* macro operation is ':=' */ +#define M_OP_PL 3 /* macro operation is '+=' */ +#define M_OP_PLCL 4 /* macro operation is '+:='*/ +#define M_OP_DF 5 /* macro operation is '*=' */ +#define M_OP_DFCL 6 /* macro operation is '*:='*/ + +/* 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 ':-' */ + +/* 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 + +/* 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 + +/* Flags for controling use of -v switch */ +#define V_NONE 0x00 +#define V_LEAVE_TMP 0x01 +#define V_PRINT_DIR 0x02 +#define V_INFER 0x04 +#define V_MAKE 0x08 +#define V_FILE_IO 0x10 +#define V_ALL (V_LEAVE_TMP | V_PRINT_DIR | V_INFER | V_MAKE |\ + V_FILE_IO) + +/* 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')) + +#endif + diff --git a/dmake/unix/gno/dmdump.c b/dmake/unix/gno/dmdump.c new file mode 100644 index 0000000..f40c8b2 --- /dev/null +++ b/dmake/unix/gno/dmdump.c @@ -0,0 +1,207 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/dmdump.c,v 1.2 1992/04/07 04:42:46 dvadura 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@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. +-- +-- LOG +-- $Log: dmdump.c,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Deleted define of unused variable. + * + * Revision 1.1 1992/01/24 03:28:51 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +#define M_TEST (M_PRECIOUS | M_VAR_MASK) + +static void dump_name ANSI((HASHPTR, int)); +static void dump_normal_target ANSI((CELLPTR, int)); +static void dump_prerequisites ANSI((LINKPTR, int, int, int)); + + +PUBLIC void +Dump(void)/* +======== 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; iht_next ) { + int flag = hp->ht_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' ); + } + + puts( "\n#====================================" ); + puts( "# Dump of targets:\n" ); + + for( i=0; iht_next ) + if( !(hp->CP_OWNR->ce_flag & F_PERCENT) ) { + if( Root->ce_prq && hp->CP_OWNR == Root->ce_prq->cl_prq ) + puts( "# ******* FIRST TARGET ********" ); + dump_normal_target( hp->CP_OWNR, hp->CP_OWNR->ce_flag ); + } + + puts( "\n#====================================" ); + puts( "# Dump of inference graph\n" ); + + for( i=0; iht_next ) + if( (hp->CP_OWNR->ce_flag & F_PERCENT) && + !(hp->CP_OWNR->ce_flag & F_MAGIC) ) + dump_normal_target( hp->CP_OWNR, hp->CP_OWNR->ce_flag ); + + DB_VOID_RETURN; +} + + + +PUBLIC void +Dump_recipe( STRINGPTR sp )/* +=================== + Given a string pointer print the recipe line out */ +{ + 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" }; + +static void +dump_normal_target( CELLPTR cp, int flag )/* +================================ + Dump in makefile like format the dag information */ +{ + register STRINGPTR sp; + t_attr attr; + unsigned int k; + + DB_ENTER( "dump_normal_target" ); + + if( !(cp->ce_flag & F_TARGET) && !cp->ce_attr ) { 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_prerequisites(cp->ce_prq, FALSE, TRUE, tflag); + } + else { + dump_name( cp->ce_name, FALSE ); + + 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, FALSE, FALSE, F_DEFAULT); + dump_prerequisites( cp->ce_indprq, 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' ); + } + + DB_VOID_RETURN; +} + + +static void +dump_prerequisites( +LINKPTR lp, +int quote, +int recurse, +int flag) +{ + for( ; lp; lp=lp->cl_next ) + if( recurse ) + dump_normal_target(lp->cl_prq, flag); + else if( lp->cl_prq ) + dump_name(lp->cl_prq->ce_name, quote); +} + + +static void +dump_name( HASHPTR hp, int quote )/* +======================== + print out a name */ +{ + if( quote ) putchar('\''); + printf( "%s", hp->ht_name ); + if( quote ) putchar('\''); + putchar(' '); +} diff --git a/dmake/unix/gno/dmstring.c b/dmake/unix/gno/dmstring.c new file mode 100644 index 0000000..07f0a27 --- /dev/null +++ b/dmake/unix/gno/dmstring.c @@ -0,0 +1,298 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/dmstring.c,v 1.1 1992/01/24 03:29:38 dvadura 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@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. +-- +-- LOG +-- $Log: dmstring.c,v $ + * Revision 1.1 1992/01/24 03:29:38 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +PUBLIC char * +_strjoin( + +/* +============================== + 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( "_strjoin" ); + + 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 * +_stradd( char *src, char *data, int 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 *t; + int l; + int sflag; + int dflag; + + DB_ENTER( "_stradd" ); + + 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 * +_strapp( char *src1, char *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. */ +{ + src2 = _stradd( src1, src2, FALSE ); + if( src1 != NIL(char) ) FREE( src1 ); + return( src2 ); +} + + + +#ifdef DBUG +#ifdef _strdup +#undef _strdup +#endif +#endif +PUBLIC char * +_strdup( char *str )/* +================ Duplicate the contents of a string, by using malloc */ +{ + 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 * +_strdup2( char *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 *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("_strdup2 invoked without argument of form x=y\n"); + + *dest++ = '"'; + *dest = 0; + + return t; +} + + + +PUBLIC char * +_strpbrk( char *s1, char *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. */ + +{ + 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 * +_strspn( char *s1, char *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. "" ) */ + +{ + register char *t; +#ifdef GNO + static char empty='\0'; + + /* this is bad; it's only one byte, but it is still unallocated memory */ + if( s1 == NIL(char) || s2 == NIL(char) ) return( &empty ); +#else + if( s1 == NIL(char) || s2 == NIL(char) ) return( "" ); +#endif + + for( t=s1; *t && (strchr( s2, *t ) != NIL(char)); t++ ); + return( t ); +} + + + + +PUBLIC char * +_strstr( char *s1, char *s2 )/* +================== find first occurrence in s1 of 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 * +_substr( char *s, char *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 save; + int len = e-s; + + if( len < 0 || len > strlen(s) ) + Fatal( "Internal Error: _substr fails consistency test" ); + + save = *e; + *e = '\0'; + s = _strdup( s ); + *e = save; + + return( s ); +} diff --git a/dmake/unix/gno/expand.c b/dmake/unix/gno/expand.c new file mode 100644 index 0000000..fd90cff --- /dev/null +++ b/dmake/unix/gno/expand.c @@ -0,0 +1,926 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/expand.c,v 1.1 1992/01/24 03:27:03 dvadura 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 +-- +-- 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@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. +-- +-- LOG +-- $Log: expand.c,v $ + * Revision 1.1 1992/01/24 03:27:03 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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_token ANSI((char*, char**)); +static char* _scan_macro ANSI((char*, char**)); +static char* _scan_brace ANSI((char*, char**, int*)); +static char* _cross_prod ANSI((char*, char*)); + + +PUBLIC char * +Expand( char *src ) /* pointer to source string */ + +/* +=============== + This is the driver routine for the expansion, it identifies non-white + space tokens and gets the _scan_token routine to figure out if they should + be treated in a special way. */ + +{ + 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 = _strdup( "" ); + 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. */ + + start = _strspn( src, " \t\n" ); + res = _strjoin( res, src, start-src, TRUE ); + if( !(*start) ) break; + + /* START <+...+> KLUDGE */ + if( (ks=_strstr(start,"<+")) && (ke=_strstr(ks,"+>")) ){ + char *t1, *t2; + + res = _strjoin( res, t2=Expand(t1=_substr(start,ks)), -1, TRUE); + FREE(t1); FREE(t2); + + t1 = _substr(ks+2, ke+1); t1[ke-ks-2] = ')'; + t2 = _strjoin( "$(mktmp ", t1, -1,FALSE); + FREE(t1); + res = _strjoin( res, t2=Expand(t2), -1, TRUE); + FREE(t2); + src = ke+2; + } + /* END <+...+> KLUDGE */ + else { + res = _strjoin( res, tmp = _scan_token( start, &src ), -1, TRUE ); + FREE( tmp ); + } + } + + DB_PRINT( "exp", ("Returning [%s]", res) ); + DB_RETURN( res ); +} + + +PUBLIC char * +Apply_edit( + +/* +=========================================== + 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 = _strstr( s, pat )) != NIL(char) ) { + res = _strdup( "" ); + do { + if( anchor ) + if( !*(p+l) || (strchr(" \t", *(p+l)) != NIL(char)) ) + res = _strjoin( _strjoin( res, s, p-s, TRUE ), subst, -1, TRUE ); + else + res = _strjoin( res, s, p+l-s, TRUE ); + else + res = _strjoin( _strjoin( res, s, p-s, TRUE ), subst, -1, TRUE ); + + s = p + l; + } + while( (p = _strstr( s, pat )) != NIL(char) ); + + res = _strjoin( res, s, -1, TRUE ); + if( fr ) FREE( src ); + } + else + res = src; + + + DB_PRINT( "mod", ("Result [%s]", res) ); + DB_RETURN( res ); +} + + +PUBLIC void +Map_esc( char *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. */ +{ + 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( int mod, char *src )/* +============================= + This routine applies the appropriate modifiers to the string src + and returns the proper result string */ + +{ + char *s; + char *e; + TKSTR str; + + DB_ENTER( "Apply_modifiers" ); + + if( 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( char *src, char *separator )/* +============================ + Tokenize the input of src and join each token found together with + the next token separated by the separator string. + + When doing the tokenization, , , , and \ all + constitute white space. */ + +{ + TKSTR tokens; + char *tok; + char *res; + int first = TRUE; + + DB_ENTER( "Tokenize" ); + + SET_TOKEN( &tokens, src ); + + + /* map the escape codes in the separator string first */ + + for(tok=separator; (tok = strchr(tok,ESCAPE_CHAR)) != NIL(char); tok++) + Map_esc( tok ); + + DB_PRINT( "exp", ("Separator [%s]", separator) ); + + /* Build the token list */ + res = _strdup( "" ); + while( *(tok = Get_token( &tokens, "", FALSE )) != '\0' ) { + DB_PRINT( "exp", ("Tokenizing [%s]", tok) ); + + if( first ) { + FREE( res ); + res = _strdup( tok ); + first = FALSE; + } + else { + char *x; + res = _strjoin(res, x =_strjoin(separator, tok, -1, FALSE), -1, TRUE); + FREE( x ); + } + } + + FREE( src ); + DB_RETURN( res ); +} + + +static char* +_scan_token( + +/* +====================== + 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 */ +{ + char *res; /* pointer to result */ + char *start; /* pointer to start of prefix */ + int crossproduct = 0; /* if 1 then computing X-prod */ + + start = s; + res = _strdup( "" ); + 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 = _strjoin( res, start, (s-start), TRUE ); + else + { + tmp = _substr( 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 = _substr( start, s ); /* save the prefix */ + + if( *s == '$' ) { + start = _scan_macro( s+1, &s ); + + if( crossproduct ) + res = _cross_prod( res, _strjoin( tmp, start, -1, TRUE ) ); + else { + res = _strjoin(res,tmp = _strjoin(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 ) { + res = _cross_prod( res, _cross_prod(tmp, start) ); + crossproduct = TRUE; + } + else { + res =_strjoin(res,tmp=_strjoin(tmp,start,-1,TRUE),-1,TRUE); + FREE( start ); + FREE( tmp ); + } + } + else { /* handle the {{ case */ + res = _strjoin( 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 = _strjoin( res, start, (s-start+1), TRUE ); + s += 2; + start = s; + } + break; + + default: s++; + } +} + + +static char* +_scan_macro( + +/* +====================== + 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: + + $$ - 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 */ +{ + 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 the simple $ at end of line case */ + if( !*s ) { + *ps = s; + DB_RETURN( _strdup("") ); + } + + if( *s == '$' ) { /* Take care of the simple $$ case. */ + *ps = s+1; + DB_RETURN( _strdup("$") ); + } + + 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 ) { + done = TRUE; + mflag = 1; + } + break; + + case ' ': + case '\t': + case '\n': + fflag = 1; + break; + + case '\0': /* check for null */ + *ps = s; + if( lev ) { + done = TRUE; + bflag = 0; + s = start; + } + break; + + case ')': /* close macro brace */ + case '}': + if( *s == edelim && lev ) --lev; + /*FALLTHROUGH*/ + + 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 = _substr( start+1, s-1 ); + else + macro_name = _substr( start, s ); + + /* 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. */ + if( fflag ) + 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 ); + + /* for M_MULTI macro variable assignments */ + If_multi = hp->ht_flag & M_MULTI; + + 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 = _strdup( hp->ht_value ); + else + result = _strdup( "" ); + + /* + * 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 = _strdup( "" ); + } + + 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 == '=' ) { + pat1 = _substr( s, p ); + for( s=p=p+1; (*p != edelim); p++ ); + + pat2 = _substr( s, p ); + + if( !Augmake ) { + char *tmp = pat2; + pat2 = Expand(pat2); + 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 */ + switch( *s++ ) { + 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 '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 = _substr( s, p ); + for(s=p=p+1; (*p != separator) && (*p != edelim); p++ ); + pat2 = _substr( 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': + if( modifier_list ) { + Warning( "Tokenize modifier must appear alone, ignored"); + modifier_list = 0; + } + else { + char *msg = "Separator string must be quoted"; + + separator = *s++; + + if( separator != '\"' ) + Warning( msg ); + else { + /* 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 = _substr( s, p ); + result = Tokenize( result, pat1 ); + FREE( pat1 ); + } + 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 ':': + 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( + +/* +============================ + 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 = _substr( start, (lev) ? s : s-1 ); + + if( lev ) { + /* Braces were not ballanced so just return the string. + * Do not expand it. */ + + res = _strjoin( "{", start, -1, FALSE ); + *flag = 0; + } + else { + *flag = 1; + res = Expand( start ); + + if( (t = _strspn( res, " \t" )) != res ) strcpy( res, t ); + } + + FREE( start ); /* this is ok! start is assigned a _substr above */ + *ps = s; + + DB_RETURN( res ); +} + + +static char* +_cross_prod( char *x, char *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) */ + +{ + static char *buf; + static int buf_siz = 0; + char *brkx; + char *brky; + char *cy; + char *cx; + char *res; + int i; + + if( *x && *y ) { + res = _strdup( "" ); cx = x; + while( *cx ) { + cy = y; + brkx = _strpbrk( cx, " \t\n" ); + if( (brkx-cx == 2) && *cx == '\"' && *(cx+1) == '\"' ) cx = brkx; + + while( *cy ) { + brky = _strpbrk( 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 = _strjoin( res, buf, -1, TRUE ); + cy = _strspn( brky, " \t\n" ); + } + cx = _strspn( brkx, " \t\n" ); + } + + FREE( x ); + res[ strlen(res)-1 ] = '\0'; + } + else + res = _strjoin( x, y, -1, TRUE ); + + FREE( y ); + return( res ); +} diff --git a/dmake/unix/gno/extern.h b/dmake/unix/gno/extern.h new file mode 100644 index 0000000..936d178 --- /dev/null +++ b/dmake/unix/gno/extern.h @@ -0,0 +1,131 @@ +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/extern.h,v 1.2 1992/04/07 04:42:46 dvadura 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@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. +-- +-- LOG +-- $Log: extern.h,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Changed namemax.h to posix.h. + * + * Revision 1.1 1992/01/24 03:26:52 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#ifndef EXTERN_h +#define EXTERN_h + +/* this is for testing only */ +#if defined(__GNUC__) +#define __ORCAC__ +#endif + +/* 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 +#include +#include +#include +#include +#if defined(__GNUC__) +# include +#else +# include +#endif +#if defined (_MPW) +# include +# include +#else +# include +# include +#endif +#include +#include +#if defined(GNO) +# if !defined(__GNUC__) +# include +# include +# endif +#endif +#include "itypes.h" +#include "stdmacs.h" +#include "alloc.h" +#include "db.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" + +#if defined(__ORCAC__) + + /* show some declarations for porting purposes */ +int Push_dir (char *dir, char *name, int ignore ); /* from make.c */ +void Error (char *fmt, ...); +void Fatal (char *fmt, ...); +void Warning (char *fmt, ...); +int Make (CELLPTR cp, CELLPTR setdirroot); +int _explode_graph(CELLPTR cp, LINKPTR parent, CELLPTR setdirroot ); +int touch_arch (char *name, char *lib); +void void_lcache (char *lib, char *member ); +int unlink (char *path); + +#endif + +#if defined(__GNUC__) +#define SYSERR -1 +int needsgno(void); +int fprintf(FILE *, char *, ...); +int printf(char *, ...); +int system (char *); +int setvbuf(FILE *, char *, int, int); +int fclose(FILE *); +int vfprintf(FILE *, char *, va_list); +int initenv(void); +int puts(char *); +int fputs(char *, FILE *); +int fread(char *, int, int, FILE *); +int fseek(FILE *, long, int); +int dup(int); +int close(int); +int rewind(FILE *); +int fflush(FILE *); +int fputc(char, FILE *); +int getpid(void); +int chdir(char *); +char *mktemp(char *); +#endif +#endif diff --git a/dmake/unix/gno/function.c b/dmake/unix/gno/function.c new file mode 100644 index 0000000..135c145 --- /dev/null +++ b/dmake/unix/gno/function.c @@ -0,0 +1,352 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/function.c,v 1.1 1992/01/24 03:27:00 dvadura 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@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. +-- +-- LOG +-- $Log: function.c,v $ + * Revision 1.1 1992/01/24 03:27:00 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include +#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_shell ANSI((char *)); +static int _mystrcmp ANSI((CONST PVOID, CONST PVOID)); + + +PUBLIC char * +Exec_function( char *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 *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 functions is called in the first place. */ + fname = _substr(buf, args=_strpbrk(buf," \t\n")); + + if( (mod1 = strchr(fname,',')) != NIL(char) ){ + *mod1 = '\0'; + mod1++; + + if( (mod2 = strchr(mod1,',')) != NIL(char) ){ + *mod2 = '\0'; + mod2++; + } + } + + switch( *fname ) { + case 'e': + if(strncmp(fname,"eq",2) == 0) res = _exec_iseq(mod1,mod2,args,TRUE); + break; + + case 'm': + if( strncmp(fname,"mktmp", 5) == 0 ) res = _exec_mktmp(mod1,mod2,args); + break; + + case 'n': + if( strncmp(fname,"null", 4) == 0 ) + res = _exec_iseq(mod1,NIL(char),args,TRUE); + break; + + case '!': + if(strncmp(fname,"!null",5) == 0) + res = _exec_iseq(mod1,NIL(char),args,FALSE); + if(strncmp(fname,"!eq",3) == 0) res = _exec_iseq(mod1,mod2,args,FALSE); + break; + + case 's': + if(strncmp(fname,"sort",4) == 0) res = _exec_sort(args); + else if(strncmp(fname,"shell",5)==0) res = _exec_shell(args); + else if(strncmp(fname,"strip",5)==0) res = Tokenize(Expand(args)," "); + else if(strncmp(fname,"subst",5)==0) res = _exec_subst(mod1,mod2,args); + break; + + default: + Warning( "Function '%s' not implemented at this time", fname ); + } + + if( res == NIL(char) ) res = _strdup(""); + + FREE(fname); + return(res); +} + + +static char * +_exec_mktmp( 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(_strspn(data, " \t\n")); + + for(p=strchr(data,'\n'); p; p=strchr(p,'\n')) { + char *q = _strspn(++p," \t"); + strcpy(p,q); + } + + Append_line( data, FALSE, tmpfile, name, FALSE, TRUE ); + Close_temp( Current_target, tmpfile ); + FREE(data); + + return( Expand(text) ); +} + + +static char * +_exec_iseq( char *lhs, char *rhs, char *data, int eq ) +{ + char *l, *r, *i, *e, *res; + int val; + + l = Expand(lhs); + r = Expand(rhs); + i = _strspn(data, " \t\n"); + e = strchr(i, ' '); + res = NIL(char); + val = strcmp(l,r); + + if( (!val && eq) || (val && !eq) ) { + if( e != NIL(char) ) *e = '\0'; + res = Expand(i); + } + else if( e != NIL(char) ) { + e = _strspn(e," \t\n"); + if( *e ) res = Expand(e); + } + + FREE(l); + FREE(r); + return(res); +} + + +static char * +_exec_sort( char *args ) +{ + char *res = NIL(char); + char *data = Expand(args); + char **tokens = NIL(char *); + char *p; + char *white = " \t\n"; + int j; + int i = 0; + + for( i=0,p=_strspn(data,white); *p; p=_strspn(_strpbrk(p,white),white),i++); + + if( i != 0 ) { + TALLOC(tokens, i, char *); + + for( i=0,p=_strspn(data,white); *p; p=_strspn(p,white),i++){ + tokens[i] = p; + p = _strpbrk(p,white); + if( *p ) *p++ = '\0'; + } + + qsort( tokens, i, sizeof(char *), _mystrcmp ); + + for( j=0; j +#endif +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/getinp.c,v 1.2 1992/04/07 04:42:46 dvadura 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 +-- 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 <\>. +-- +-- 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@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. +-- +-- LOG +-- $Log: getinp.c,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Minor clean up and a check for -X flag on the execution of #! lines. + * + * Revision 1.1 1992/01/24 03:27:56 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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( char *buf, FILE *fil )/* +====================== + Read a line of input from the file stripping + off comments. The routine returns TRUE if EOF */ +{ + register char *p; + register char *c; + char *q; + char *buf_org; + static int ignore = FALSE; + int cont = FALSE; + int pos = 0; + int res; + + DB_ENTER( "Get_line" ); + + 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 ); + + Line_number++; + + /* ignore input if ignore flag set and line ends in a continuation + character. */ + q = p+strlen(p)-2; + if( q

) + * 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" ); + + + /* 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 = _strspn(buf, " \t\r\n")) == CONDSTART ) { + TKSTR token; + + SET_TOKEN( &token, p ); + + p = Get_token( &token, "", FALSE ); + + if( (res = _is_conditional( p )) ) /* 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( char *str, char **pend, int 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 *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( TKSTRPTR string, char *brk, int 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. */ + +{ + register char *s; + register char *curp; + register char *t; + int done = FALSE; + char space[10]; + + 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] = (char) 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 = _strspn( 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 = _strpbrk(t, space); + + if( anchor && *curp && !IS_WHITE( *curp ) ) + if( ((anchor == 1)?*curp:_strspn(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( char *tg )/* +======================= + Look at tg and return it's value if it is a conditional identifier + otherwise return 0. */ +{ + DB_ENTER( "_is_conditional" ); + + tg++; + switch( *tg ) { + case 'I': if( !strcmp( tg, "IF" )) DB_RETURN( ST_IF ); 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( int opcode, TKSTRPTR tg )/* +=================================== + Perform the necessary processing for .IF conditinal targets. + Someday this should be modified to do bracketted expressions ala + CPP... sigh */ +{ + static short action[MAX_COND_DEPTH]; + static char ifcntl[MAX_COND_DEPTH]; + char *tok, *lhs, *rhs, *op, *expr; + int result; + + 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" ); + /* FALLTHROUGH */ + + case ST_IF: + if( opcode == ST_IF && (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 = _strspn( expr, " \t" ); + if( !*lhs ) lhs = NIL(char); + + if( (op = _strstr( lhs, "==" )) == NIL(char) ) + op = _strstr( lhs, "!=" ); + + if( op == NIL(char) ) + result = (lhs != NIL(char)); + else { + op[1] = op[0]; + if( lhs != op ) { + for( tok = op-1; (tok != lhs) && ((*tok == ' ')||(*tok == '\t')); + tok-- ); + tok[1] = '\0'; + } + else + lhs = NIL(char); + + op++; + rhs = _strspn( op+1, " \t" ); + if( !*rhs ) rhs = NIL(char); + + 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 == '!' ) result = !result; + } + + if( expr != NIL(char) ) FREE( expr ); + + if( opcode == ST_IF ) { + Nest_level++; + action[Nest_level] = 1; + } + ifcntl[Nest_level] |= (opcode==ST_IF)?SEEN_IF:SEEN_ELIF; + + if( result ) { + if( !(ifcntl[Nest_level] & (ACCEPT_IF|ACCEPT_ELIF)) ) { + action[ Nest_level ] = action[ Nest_level-1 ]; + ifcntl[Nest_level] |= (opcode==ST_IF)?ACCEPT_IF:ACCEPT_ELIF; + } + 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 ] ); +} diff --git a/dmake/unix/gno/hash.c b/dmake/unix/gno/hash.c new file mode 100644 index 0000000..a72b1ca --- /dev/null +++ b/dmake/unix/gno/hash.c @@ -0,0 +1,61 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/hash.c,v 1.1 1992/01/24 03:27:06 dvadura 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@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. +-- +-- LOG +-- $Log: hash.c,v $ + * Revision 1.1 1992/01/24 03:27:06 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +PUBLIC uint16 +Hash( char *id, uint32 *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) */ + +{ + 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/unix/gno/imacs.c b/dmake/unix/gno/imacs.c new file mode 100644 index 0000000..8b91311 --- /dev/null +++ b/dmake/unix/gno/imacs.c @@ -0,0 +1,172 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/imacs.c,v 1.1 1992/01/24 03:29:55 dvadura 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@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. +-- +-- LOG +-- $Log: imacs.c,v $ + * Revision 1.1 1992/01/24 03:29:55 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.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(void) +{ + 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(void) +{ + static char* switchar; + char swchar[2]; + + swchar[0] = Get_switch_char(), swchar[1] = '\0'; + _set_string_var("SWITCHAR", swchar, M_PRECIOUS, &switchar); + _set_string_var("DIRSEPSTR", (*swchar=='/')?"\\":"/",M_PRECIOUS,&DirSepStr); + _set_string_var("DIRBRKSTR", DirBrkStr, M_PRECIOUS, &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 ); + + 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("PREP", "0", M_DEFAULT, &Prep ); + _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(".SETDIR", "", M_DEFAULT|M_NOEXPORT, &Start_dir ); + _set_string_var("MAKEDIR",Get_current_dir(),M_PRECIOUS|M_NOEXPORT,&Makedir); + _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 ); + (void) Def_macro("MAXLINELENGTH", "0", 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 ); +} + + +/* +** Define an integer variable value, and set up the macro. +*/ +static void +_set_int_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; + hp->MV_IVAR = var; + *var = atoi(val); +} + + +/* +** Define a string variables value, and set up the macro. +*/ +static void +_set_string_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; + hp->MV_SVAR = var; + *var = hp->ht_value; +} + + +/* +** Define a bit variable value, and set up the macro. +*/ +static void +_set_bit_var(char *name, char *val, int mask) +{ + HASHPTR hp; + + hp = Def_macro(name, val, M_FLAG); + hp->ht_flag |= M_VAR_BIT | M_MULTI; + hp->MV_MASK = mask; + hp->MV_BVAR = &Glob_attr; +} diff --git a/dmake/unix/gno/infer.c b/dmake/unix/gno/infer.c new file mode 100644 index 0000000..355bcba --- /dev/null +++ b/dmake/unix/gno/infer.c @@ -0,0 +1,815 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/infer.c,v 1.1 1992/01/24 03:27:21 dvadura 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@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. +-- +-- LOG +-- $Log: infer.c,v $ + * Revision 1.1 1992/01/24 03:27:21 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 * _build_name 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)); + +static int _prep = -1; /* Integer value of Prep variable */ + +#ifdef DBUG +void _dump_iset(char *name, ICELLPTR iset); +void _dump_dfa_stack(DFALINKPTR dfas, DFASETPTR dfa_stack); +#endif + +PUBLIC void +Infer_recipe( CELLPTR cp, CELLPTR setdirroot )/* +================================ + Perform a breadth-first search of the inference graph and return if + possible an inferred set of prerequisites for making the current target. +*/ +{ + ICELLPTR nomatch, match; + + DB_ENTER("Infer_recipe"); + + if( cp->ce_attr & A_NOINFER ) {DB_VOID_RETURN;} + if( _prep == -1 ) _prep = atoi(Prep); /* _dfa_subset needs _prep */ + + match = NIL(ICELL); + nomatch = _add_iset( NIL(ICELL), NIL(ICELL), NIL(CELL), NIL(DFALINK), + setdirroot, _prep+_count_dots(cp->CE_NAME), 0, + _strdup(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 ambigous 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. + * + * NOTE: May turn this around at some point. + */ + + /* 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; + } + + 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=_strdup(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 = _build_name( 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( ICELLPTR ic, ICELLPTR *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 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 + * decuce 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 = _build_name( 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))) { + 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); + } + + + /* 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 * +_build_name( + 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 = _strdup( name ); + + return(name); +} + + +static DFALINKPTR +_dfa_subset(DFALINKPTR pdfa, register DFASETPTR 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. */ +{ + register DFALINKPTR element; + DFALINKPTR nelement; + + DB_ENTER( "_dfa_subset" ); + + 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 ); + + if((subset = (subel != NIL(DFALINK)))) 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(DFALINKPTR 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. */ +{ + 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(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( + 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 = _strdup(dir); + icell->ic_name = _strdup(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(void) +{ + 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( +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( +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 = _strjoin(tmp, "(", -1, TRUE); + tmp = _strjoin(tmp, ip->ic_meta->CE_NAME, -1, TRUE); + + if( ip->ic_dir && !*ip->ic_dir ) { + tmp = _strjoin(tmp, "[", -1, TRUE); + if( strncmp(Makedir,ip->ic_dir, strlen(Makedir)) ) + tmp = _strjoin(tmp, ip->ic_dir, -1, TRUE); + else + tmp = _strjoin(tmp, ip->ic_dir+strlen(Makedir)+1, -1, TRUE); + tmp = _strjoin(tmp, "]", -1, TRUE); + } + tmp = _strjoin(tmp, (ip->ic_name)?") -->":")", -1, TRUE); + } + + if( ip->ic_name ) tmp = _strapp( tmp, ip->ic_name ); + + if( flag && ip->ic_meta->ce_prq) { + tmp = _strjoin(tmp, "(", -1, TRUE); + tmp = _strjoin(tmp, ip->ic_meta->ce_prq->cl_prq->CE_NAME, -1, TRUE); + tmp = _strjoin(tmp, ")", -1, TRUE); + } + + if( print ) { + fprintf( stderr, "%s: %2d. %s\n", Pname, print, tmp ); + FREE(tmp); + tmp = NIL(char); + } + + return(tmp); +} + + +#ifdef DBUG +void _dump_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 = _strapp( tmp, pdfa->dl_meta->CE_NAME ); + + tmp = _strapp( tmp, ":: {" ); + for( ds = dfa_stack; ds != NIL(DFASET); ds = ds->df_next ) { + tmp = _strapp( tmp, "[" ); + for( pdfa = ds->df_set; pdfa != NIL(DFALINK); pdfa = pdfa->dl_next ) + tmp = _strapp( tmp, pdfa->dl_meta->CE_NAME ); + tmp = _strapp( tmp, "]" ); + } + tmp = _strapp( tmp, "}" ); + + printf( "DFA set and stack contents:\n%s\n", tmp ); + FREE(tmp); +} + + +void _dump_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/unix/gno/install b/dmake/unix/gno/install new file mode 100644 index 0000000..8fa4bcd --- /dev/null +++ b/dmake/unix/gno/install @@ -0,0 +1,8 @@ +#!/bin/sh +/bin/cp dmake /usr/local/bin +/bin/cp GS.startup.mk /usr/local/lib/startup.mk +/bin/cp ../../man/dmake.nc /usr/man/cat1/dmake.1 +/bin/cp ../../../rmroot/rmroot.1 /usr/man/man1/rmroot.1 +/bin/cp ../../../rmroot/rmroot /usr/local/bin +echo Ensure you delete any dmake and startup.mk file you may have in +echo /usr/bin from a previous install. diff --git a/dmake/unix/gno/itypes.h b/dmake/unix/gno/itypes.h new file mode 100644 index 0000000..b9d4774 --- /dev/null +++ b/dmake/unix/gno/itypes.h @@ -0,0 +1,55 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/itypes.h,v 1.1 1992/01/24 03:29:40 dvadura Exp $ +-- SYNOPSIS -- type declarations for common types +-- +-- DESCRIPTION +-- portable type declarations. +-- +-- 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. +-- +-- LOG +-- $Log: itypes.h,v $ + * Revision 1.1 1992/01/24 03:29:40 dvadura + * dmake Version 3.8, Initial revision + * +*/ + + +#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 signed 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/unix/gno/macparse.c b/dmake/unix/gno/macparse.c new file mode 100644 index 0000000..9391228 --- /dev/null +++ b/dmake/unix/gno/macparse.c @@ -0,0 +1,166 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/macparse.c,v 1.1 1992/01/24 03:27:52 dvadura 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@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. +-- +-- LOG +-- $Log: macparse.c,v $ + * Revision 1.1 1992/01/24 03:27:52 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +PUBLIC int +Parse_macro( char *buffer, int 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. */ +{ + register char *tok1; /* temporary place to keep a token */ + register char *tok2; /* temporary place to keep a token */ + 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 */ + + DB_ENTER( "Parse_macro" ); + + SET_TOKEN( &input, buffer ); + tok1 = Get_token( &input, "=+:*", 0 ); + + if( Macro_op( tok1 ) ) { + Error( "No macro name" ); + CLEAR_TOKEN( &input ); + DB_RETURN( 1 ); + } + + tok1 = _strdup( tok1 ); + tok2 = Get_token( &input, "=+:*", 2 ); + if( !(operator = Macro_op(tok2)) || + (!strcmp(tok1, ".SETDIR") && + ((operator != M_OP_CL) || (operator != M_OP_PLCL) || + (operator != M_OP_DFCL))) ) { + CLEAR_TOKEN( &input ); + FREE( tok1 ); + DB_RETURN( 0 ); + } + + tok2 = Expand(tok1); FREE(tok1); tok1 = tok2; + tok2 = Get_token( &input, NIL( char ), FALSE ); + + 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 = _stradd( 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) ) + break; + /* else FALLTHRU */ + + case M_OP_EQ: + Def_macro( tok1, tok2, flag ); + break; + + case M_OP_DFCL: + if( (hv = GET_MACRO(tok1)) != NIL(HASH) ) + break; + /* else FALLTHRU */ + + case M_OP_CL: + /* If the macro we are assigning from is a single control + * macro with nothing else, then we propagate the M_MULTI + * flag to the macro we are assigning the value to so that + * the same macro can be used to do this over and over. */ + If_multi = 0; + tok2 = Expand( tok2 ); + Def_macro( tok1, tok2, M_EXPANDED | flag | If_multi ); + FREE( tok2 ); + break; + } + + FREE( tok1 ); + + DB_RETURN( 1 ); +} + + + +PUBLIC int +Macro_op( char *op )/* +================ + Check the passed in op string and map it to one of the macro operators */ +{ + int ret = 0; + + DB_ENTER( "macro_op" ); + + switch( *op ) { + case '=': ret = M_OP_EQ; break; + case ':': ret = M_OP_CL; op++; break; + + case '+': + ret = M_OP_PL; op++; + if( *op == ':' ) { ret = M_OP_PLCL; op++; } + break; + + case '*': + ret = M_OP_DF; op++; + if( *op == ':' ) { ret = M_OP_DFCL; op++; } + break; + } + + if( *op++ != '=' ) + ret = 0; + else if( *op != '\0' ) + ret = 0; + + DB_RETURN( ret ); +} diff --git a/dmake/unix/gno/make.c b/dmake/unix/gno/make.c new file mode 100644 index 0000000..a296ceb --- /dev/null +++ b/dmake/unix/gno/make.c @@ -0,0 +1,1028 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/make.c,v 1.2 1992/04/07 04:42:46 dvadura 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 $< +-- {{ - expands to { +-- }} - expands to } +-- \# - expands to # +-- +-- 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. +-- +-- LOG +-- $Log: make.c,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Minor change to variable name to remove "redefined warning from compiler". + * + * Revision 1.1 1992/01/24 03:26:51 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +static void _drop_mac ANSI((HASHPTR)); +static void _set_recipe ANSI((char*, int)); +static void _set_tmd ANSI((void)); +static void _append_file ANSI((STRINGPTR, FILE*, char*, int)); +static LINKPTR _dup_prq ANSI((LINKPTR)); +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 ]; + + +PUBLIC int +Make_targets(void)/* +================ + 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 ); + + Root->ce_flag |= F_RULES|F_TARGET|F_STAT; + Root->ce_attr |= A_NOSTATE; + Root->ce_time = Do_time(); + TALLOC( Root->ce_recipe, 1, STRING ); + Root->ce_recipe->st_string = ""; + + for( lp = Root->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 = Root->ce_prq; lp != NIL(LINK); lp = lp->cl_next ) { + CELLPTR root = lp->cl_prq; + if( !(root->ce_attr & A_UPDATED) ) + printf( "`%s' is up to date\n", root->CE_NAME ); + } + + DB_RETURN( 0 ); +} + + + +int +Make(CELLPTR cp, CELLPTR setdirroot)/* +======================== Make a specified target */ +{ + register LINKPTR dp; + register CELLPTR tcp; + CELLPTR nsetdirroot; + char *name, *lib; + HASHPTR m_at, m_q, m_b, m_g, m_l, m_bb, m_up; + 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()) ); + + m_q = m_b = m_g = m_l = m_bb = m_up = m_at = NIL(HASH); + + /* 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); + + 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)) ) + 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; + } + } + + tcp = cp; + do { + if( push ) { + if( tcp->ce_dir ) FREE( tcp->ce_dir ); + tcp->ce_dir = _pool_lookup(Pwd); + tcp->ce_attr |= A_SETDIR; + } + tcp->ce_setdir = nsetdirroot; + tcp = tcp->ce_all; + } + while( tcp != NIL(CELL) && tcp != cp ); + + 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; + Stat_target( cp, TRUE ); + + if( cp->ce_time == (time_t)0L ) { + if( cp->ce_flag & F_INFER ) + cp->ce_time = itime; + } + else + cp->ce_attr |= A_PRECIOUS; /* File exists so don't remove it later. */ + + if( Verbose & V_MAKE ) + printf("%s: Time stamp of [%s] is %ld\n",Pname,cp->CE_NAME, + cp->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)||(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)"; + + for( dp = cp->ce_prq; dp != NIL(LINK); dp = dp->cl_next ) { + int seq; + + /* 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. */ + + 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; + + if( strchr(tcp->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. */ + + m_at = Def_macro( "@", cp->ce_fname, M_MULTI ); + name = Expand( tcp->CE_NAME ); + if( strcmp(name,cp->CE_NAME) == 0 ) + Fatal( "Circular dynamic dependency generated '%s'", name ); + + tcp = dp->cl_prq = Def_cell( name ); + FREE( name ); + } + + 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 parents F_REMOVE and F_INFER attribute to children. + * Make certain you 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); + + 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 *) ); + if( mtime < tcp->ce_time ) tcp->ce_time = cp->ce_time+1L; + } + + if( tcp->ce_time > otime ) otime = tcp->ce_time; + + all = _strapp( all, name ); + if((tgflg = (dp->cl_flag & F_TARGET))) inf = _strapp( inf, name ); + + if((cp->ce_timece_time) || ((tcp->ce_flag & F_TARGET) && Force)) { + outall = _strapp( outall, name ); + if( tgflg ) imm = _strapp( imm, name ); + } + } + + 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_EXPANDED ); + 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 ) + 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 ) + if( Do_touch( name, lib, + (cp->ce_attr & A_SYMBOL) ? &name : NIL(char *) ) != 0 ) + printf( " not touched - non-existant" ); + + 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 */ + tcp = cp; + do { + 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 *nname = Build_path(_prefix(dir,tcp->ce_dir), tcp->ce_fname); + + if( (tcp->ce_attr & A_FFNAME) && (tcp->ce_fname != NIL(char)) ) + FREE( tcp->ce_fname ); + + tcp->ce_fname = _strdup(nname); + tcp->ce_attr |= A_FFNAME; + } + + tcp = tcp->ce_all; + } + while( tcp != NIL(CELL) && tcp != cp ); + +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 ); + + while( push-- ) Pop_dir(FALSE); + + if( inf != NIL(char) ) FREE( inf ); + if( all != NIL(char) ) FREE( all ); + if( imm != NIL(char) ) FREE( imm ); + if( outall != NIL(char) ) FREE( outall ); + + DB_PRINT( "mem", ("%s:-< mem %ld", cp->CE_NAME, (long) coreleft()) ); + DB_RETURN( rval ); +} + + +static char * +_prefix( +char *pfx, +char *pat) +{ + char *opat = pat; + while( *pfx && *pat && *pfx++ == *pat++ ); + + return( !*pfx ? _strspn(pat,DirBrkStr) : opat ); +} + + +static LINKPTR +_dup_prq(LINKPTR lp ) +{ + LINKPTR tlp; + + if( lp == NIL(LINK) ) return(lp); + + TALLOC(tlp, 1, LINK); + *tlp = *lp; + tlp->cl_next = _dup_prq( lp->cl_next ); + + return(tlp); +} + + +static void +_drop_mac(HASHPTR hp )/* +================ set a macro value to zero. */ +{ + if( hp && hp->ht_value != NIL(char) ) { + FREE( hp->ht_value ); + hp->ht_value = NIL(char); + } +} + + + +int +_explode_graph( + CELLPTR cp, + LINKPTR parent, + CELLPTR 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. */ +{ + /* 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( 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 ) { + if( parent == NIL(LINK) ) + Fatal( "Internal Error: NIL parent in Make()" ); + + TALLOC(parent->cl_prq, 1, CELL); + *parent->cl_prq = *cp; + cp = parent->cl_prq; + cp->ce_prq = _dup_prq(cp->ce_prq); + } + 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(CELLPTR 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. */ +{ + 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 ) { + char *ecmnd = cmnd; + cmnd = _strdup(_strspn(cmnd, " \t\n+-@%")); + FREE(ecmnd); + } + + /* 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 && *(p = _strpbrk(cmnd, " \t\n")) ) { + char *cname = cmnd; + + *p = '\0'; + (void) Def_macro("CMNDNAME",cname,M_MULTI|M_EXPANDED); + (void) Def_macro("CMNDARGS",p+1,M_MULTI|M_EXPANDED); + + cmnd = Expand("$(COMMAND)"); + FREE(cname); /* cname == cmnd at this point. */ + } + + Swap_on_exec = ((l_attr & A_SWAP) != 0); /* Swapping for DOS only */ + do_it = !Trace; + + if( !group && Trace && _strstr(rp->st_string,"$(MAKE)") ) { + Wait_for_completion |= Trace; + do_it = TRUE; + } + + if( group ) + Append_line( cmnd, TRUE, tmpfile, cp->CE_NAME, trace, 0 ); + else { + int kludge_int1, kludge_int2; /* kludge variables for below */ + + if( *_strspn(cmnd, " \t") != '\0' ) + Print_cmnd(cmnd, !(do_it && (l_attr & A_SILENT)), 0); + else + do_it = FALSE; + +/* this section is kludge for other commented out part */ + kludge_int1 = (l_attr&A_IGNORE) ? 1:0; + kludge_int2 = (rp->st_next == NIL(STRING)) ? 1:0; +/* rval=Do_cmnd(cmnd,FALSE,do_it,cp, kludge_int1, FALSE, kludge_int2); */ + rval=Do_cmnd(cmnd,FALSE,do_it,cp, kludge_int1, shell, kludge_int2); +/* end kludge */ + +/* + 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 ) { + if( attr & A_EPILOG ) /* emit epilog */ + _append_file( _recipes[RP_GPEPILOG], tmpfile, cp->CE_NAME, trace ); + + if( trace ) fputs("]\n", stdout); + + if((do_it = !Trace)) Close_temp( cp, tmpfile ); + rval = Do_cmnd(groupfile, TRUE, do_it, cp, (attr & A_IGNORE)!=0, + TRUE, TRUE); + } + + Wait_for_completion = FALSE; + _recipes[ RP_RECIPE ] = orp; + DB_RETURN( rval ); +} + + +PUBLIC void +Print_cmnd(char *cmnd, int echo, int 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. */ +{ + 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 = _strpbrk(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); + +int +Push_dir(char *dir, char *name, int 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.*/ +{ + STRINGPTR new_dir; + + DB_ENTER( "Push_dir" ); + + if( dir == NIL(char) || *dir == '\0' ) dir = Pwd; + if( *dir == '\'' && dir[strlen(dir)-1] == '\'' ) { + dir = _strdup(dir+1); + dir[strlen(dir)-1]='\0'; + } + else + dir = Expand(dir); + + if( Set_dir(dir) ) { + if( !ignore ) + Fatal( "Unable to change to directory `%s', target is [%s]", + dir, name ); + FREE(dir); + DB_RETURN( 0 ); + } + + DB_PRINT( "dir", ("Push: [%s]", dir) ); + if( Verbose & V_PRINT_DIR ) + printf( "%s: Changed to directory [%s]\n", Pname, dir ); + + FREE( dir ); + TALLOC( new_dir, 1, STRING ); + new_dir->st_next = dir_stack; + dir_stack = new_dir; + new_dir->st_string = _strdup( Pwd ); + + Def_macro( "PWD", Get_current_dir(), M_MULTI | M_EXPANDED ); + _set_tmd(); + + DB_RETURN( 1 ); +} + + + +PUBLIC void +Pop_dir(int ignore)/* +================= + Change the current working directory to the previous saved dir. */ +{ + 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_PRINT_DIR ) + 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(void)/* +============ + 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 = _strdup( "" ); + + 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 = _strdup( 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( char *target, int ind )/* +============================ + Set up the _recipes static variable so that the slot passed in points + at the rules corresponding to the target supplied. */ +{ + 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( + 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( + 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( char *str )/* +===================== + Scan down the list of chained strings and see if one of them matches + the string we are looking for. */ +{ + 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 = _strdup(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/unix/gno/make.sh b/dmake/unix/gno/make.sh new file mode 100644 index 0000000..f2df0a1 --- /dev/null +++ b/dmake/unix/gno/make.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# This is a shell script for making a new build of dmake +# +occ -c -a0 -w -i -O -DGNO -s4096 -SMain______ dmake.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SLibrary___ arlib.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SString____ basename.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SDAG_______ dag.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SGSSpecific dirbrk.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SIO________ dmdump.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SString____ dmstring.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SMacro_____ expand.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SMacro_____ function.c +occ -c -a0 -w -i -r -O31 -DGNO -s4096 -SIO________ getinp.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SMake______ hash.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SMacro_____ imacs.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SMake______ infer.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SMacro_____ macparse.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SMake______ make.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SIO________ parse.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SString____ path.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SMake______ percent.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SMain______ quit.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SMain______ rmprq.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -DNO_CASE -SMain______ ruletab.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SDAG_______ rulparse.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SGSSpecific runargv.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SIO________ stat.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SIO________ state.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SGSSpecific sysintf.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SGSSpecific tempnam.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SGSSpecific utime.c +occ -c -a0 -w -i -r -O -DGNO -s4096 -SMain______ va.c +occ -o dmake dmake.o arlib.o basename.o dag.o dirbrk.o dmdump.o dmstring.o expand.o function.o getinp.o hash.o imacs.o infer.o macparse.o make.o parse.o path.o percent.o quit.o rmprq.o ruletab.o rulparse.o runargv.o stat.o state.o sysintf.o tempnam.o utime.o va.o -l/usr/lib/stack -l/usr/lib/lenviron diff --git a/dmake/unix/gno/makefile.mk b/dmake/unix/gno/makefile.mk new file mode 100644 index 0000000..15ee75b --- /dev/null +++ b/dmake/unix/gno/makefile.mk @@ -0,0 +1,225 @@ +# Makefile.mk generated by makedmake (Gno) v1.1.1 for Dennis Vadura's dmake + +# +# Configuration Information. Use '/', not ':'. +# + +BINDIR = /usr/local/bin +LIBDIR = /usr/local/lib +MANDIR = /usr/man + +# +# YOU SHOULD NOT HAVE TO CHANGE ANYTHING BELOW THIS LINE +# + +# +# BUILD should either be "distribution", "development", or "debug" +# + +BUILD = distribution + +# +# Define all the flags, definitions, and libraries +# + +STACK = -s4096 + +.IF $(BUILD) == distribution + +DEFINES = -DGNO +CFLAGS = $(__OFLAG) -w -i -r -O $(DEFINES) $(STACK) +# Orca/C has a problem with loop-invariant optimization on getinp.c +GETINPFLG = $(__OFLAG) -w -i -r -O31 $(DEFINES) $(STACK) +FORKFLAGS = $(__OFLAG) -w -i -r -O $(DEFINES) $(STACK) +VAFLAGS = $(__OFLAG) -w -i -r -O $(DEFINES) $(STACK) +MAINFLAGS = $(__OFLAG) -w -i -O $(DEFINES) $(STACK) +LDFLAGS = +LDLIBS = -l/usr/lib/stack -l/usr/lib/lenviron + +.ELSE + +DEFINES = -DGNO -DDEBUG +CFLAGS = $(__OFLAG) -w -i -r -G25 $(DEFINES) $(STACK) +GETINPFLG = $(__OFLAG) -w -i -r -G25 $(DEFINES) $(STACK) +FORKFLAGS = $(__OFLAG) -w -i -r -O25 $(DEFINES) $(STACK) +VAFLAGS = $(__OFLAG) -w -i -r -O8 $(DEFINES) $(STACK) +MAINFLAGS = $(__OFLAG) -w -i -G25 $(DEFINES) $(STACK) +LDFLAGS = -v +LDLIBS = -l/usr/lib/stack -l/usr/lib/lenviron + +.END + +# +# These are the segment names required for Orca/C's segment directive. +# We use the small memory model with segmentation. These have been assigned +# at random and should be reassigned, and with more informative names. +# + +SEGMENT1 = -SMain______ +SEGMENT2 = -SIO________ +SEGMENT3 = -SString____ +SEGMENT4 = -SMake______ +SEGMENT5 = -SGSSpecific +SEGMENT6 = -SMacro_____ +SEGMENT7 = -SLibrary___ +SEGMENT8 = -SDAG_______ + +.IF $(BUILD) != debug +SPARESEG1 = $(SEGMENT4) +SPARESEG2 = $(SEGMENT4) +SPARESEG3 = $(SEGMENT4) +SPARESEG4 = $(SEGMENT4) +.ELSE +SPARESEG1 = -SSpare1____ +SPARESEG2 = -SSpare2____ +SPARESEG3 = -SSpare3____ +SPARESEG4 = -SSpare4____ +.END + +OBJS = dmake.o arlib.o basename.o dag.o dirbrk.o dmdump.o dmstring.o\ + expand.o function.o getinp.o hash.o imacs.o infer.o macparse.o make.o\ + parse.o path.o percent.o quit.o rmprq.o ruletab.o rulparse.o\ + runargv.o stat.o state.o sysintf.o tempnam.o utime.o va.o + +# +# Targets +# + +all: dmake ../../../rmroot/rmroot + +dmake: $(OBJS) + $(CC) $(LDFLAGS) -o dmake $(OBJS) $(LDLIBS) + +../../../rmroot/rmroot: ../../../rmroot/rmroot.c + $(CC) -O -o $@ $< + +arlib.o: arlib.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h sysintf.h + $(CC) -c $(CFLAGS) $(SEGMENT7) arlib.c + +basename.o: basename.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h\ + struct.h vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SEGMENT3) basename.c + +dag.o: dag.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SEGMENT8) dag.c + +dirbrk.o: dirbrk.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SEGMENT5) dirbrk.c + +dmake.o: dmake.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h patchlvl.h version.h + $(CC) -c $(MAINFLAGS) $(SEGMENT1) dmake.c + +dmdump.o: dmdump.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SEGMENT2) dmdump.c + +dmstring.o: dmstring.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h\ + struct.h vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SEGMENT3) dmstring.c + +expand.o: expand.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SEGMENT6) expand.c + +function.o: function.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h\ + struct.h vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SEGMENT6) function.c + +getinp.o: getinp.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h + $(CC) -c $(GETINPFLG) $(SEGMENT2) getinp.c + +hash.o: hash.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SPARESEG1) hash.c + +imacs.o: imacs.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SEGMENT6) imacs.c + +infer.o: infer.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SPARESEG2) infer.c + +macparse.o: macparse.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h\ + struct.h vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SEGMENT6) macparse.c + +make.o: make.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SPARESEG3) make.c + +parse.o: parse.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SEGMENT2) parse.c + +path.o: path.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SEGMENT3) path.c + +percent.o: percent.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SPARESEG4) percent.c + +quit.o: quit.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SEGMENT1) quit.c + +rmprq.o: rmprq.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SEGMENT1) rmprq.c + +ruletab.o: ruletab.c startup.h + $(CC) -c $(CFLAGS) -DNO_CASE $(SEGMENT1) ruletab.c + +rulparse.o: rulparse.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h\ + struct.h vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SEGMENT8) rulparse.c + +runargv.o: runargv.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h sysintf.h + $(CC) -c $(FORKFLAGS) $(SEGMENT5) runargv.c + +stat.o: stat.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SEGMENT2) stat.c + +state.o: state.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h + $(CC) -c $(CFLAGS) $(SEGMENT2) state.c + +sysintf.o: sysintf.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h\ + vextern.h public.h config.h posix.h sysintf.h + $(CC) -c $(CFLAGS) $(SEGMENT5) sysintf.c + +tempnam.o: tempnam.c + $(CC) -c $(CFLAGS) $(SEGMENT5) tempnam.c + +utime.o: utime.c + $(CC) -c $(CFLAGS) $(SEGMENT5) utime.c + +va.o: va.c extern.h itypes.h stdmacs.h alloc.h db.h dmake.h struct.h vextern.h\ + public.h config.h posix.h patchlvl.h version.h + $(CC) -c $(VAFLAGS) $(SEGMENT1) va.c + +# +# Housekeeping +# + +clean: + $(RM) $(OBJS) dmake.root + +install: +# dump old files +# install the new ones + $(CP) dmake $(BINDIR) + $(CP) GS.startup.mk $(LIBDIR)/startup.mk + $(CP) ../../man/dmake.nc $(MANDIR)/cat1/dmake.1 + $(CP) ../../../rmroot/rmroot.1 $(MANDIR)/man1/rmroot.1 + $(CP) ../../../rmroot/rmroot $(BINDIR) + @echo Ensure you delete any dmake and startup.mk file you may have in + @echo /usr/bin from a previous install. diff --git a/dmake/unix/gno/parse.c b/dmake/unix/gno/parse.c new file mode 100644 index 0000000..bf5b9c7 --- /dev/null +++ b/dmake/unix/gno/parse.c @@ -0,0 +1,157 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/parse.c,v 1.1 1992/01/24 03:26:53 dvadura 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@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. +-- +-- LOG +-- $Log: parse.c,v $ + * Revision 1.1 1992/01/24 03:26:53 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + + +PUBLIC void +Parse( FILE *fil )/* +============== Parse the makefile input */ +{ + int rule = FALSE; /* have seen a recipe line */ + char *p; /* termporary pointer into Buffer */ + + 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 { + 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 = _strspn( 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( Buffer, TRUE, TRUE ); + rule = TRUE; + } + else + State = NORMAL_SCAN; + } + else { + if( *Buffer == '\t' || (Notabs && *Buffer == ' ') ) { + Add_recipe_to_list( Buffer, FALSE, FALSE ); + rule = TRUE; + } + else if( *p == ']' ) + Fatal( "Found unmatched ']'" ); + else if( (*Buffer && *p) || (Notabs && !*Buffer && !*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 , so lets + * try to scan the thing as a macro or rule definition. */ + + case NORMAL_SCAN: + if( !*Buffer ) 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", Buffer, 7 ) && + (Buffer[7] == ' ' || Buffer[7] == '\t') ) + { + char *tmp; + + tmp = _strjoin( ".INCLUDE:", Buffer+7, -1, FALSE ); + strcpy( Buffer, 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(Buffer, 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( *_strspn( 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/unix/gno/patchlvl.h b/dmake/unix/gno/patchlvl.h new file mode 100644 index 0000000..91a8737 --- /dev/null +++ b/dmake/unix/gno/patchlvl.h @@ -0,0 +1,3 @@ +/* dmake patch level, reset to 0 for each new version release. */ + +#define PATCHLEVEL 1 diff --git a/dmake/unix/gno/path.c b/dmake/unix/gno/path.c new file mode 100644 index 0000000..a70e963 --- /dev/null +++ b/dmake/unix/gno/path.c @@ -0,0 +1,116 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/path.c,v 1.1 1992/01/24 03:27:54 dvadura Exp $ +-- SYNOPSIS -- pathname manipulation code +-- +-- DESCRIPTION +-- Pathname routines to handle building and pulling appart +-- pathnames. +-- +-- 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. +-- +-- LOG +-- $Log: path.c,v $ + * Revision 1.1 1992/01/24 03:27:54 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +/* +** Return the suffix portion of a filename, assumed to begin with a `.'. +*/ +PUBLIC char * +Get_suffix(char *name) +{ + char *suff; + + if(name == NIL(char) || (suff = strrchr(name, '.')) == NIL(char)) + suff = ".NULL"; + + return (suff); +} + + + +/* +** 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(char *dir, char *name) +{ + register char *p; + register char *q; + static char *path = NIL(char); + static unsigned int 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 int) (buflen*sizeof(char)) ); + } + + *path = '\0'; + + if( dlen ) { + strcpy( path, dir ); + if( *path && strchr(DirBrkStr, dir[dlen-1]) == NIL(char) ) + strcat( path, DirSepStr ); + } + strcat( path, name ); + + q=path; + while( *q ) { + char *t; + + p=_strpbrk(q,DirBrkStr); + t=_strpbrk(p+1,DirBrkStr); + if( !*p || !*t ) break; + + if( !(p-q == 2 && strncmp(q,"..",2) == 0) + && t-p-1 == 2 && strncmp(p+1,"..",2) == 0 ) { + t = _strspn(t,DirBrkStr); + strcpy(q,t); + } + else + q = p+1; + } + + return( path ); +} diff --git a/dmake/unix/gno/percent.c b/dmake/unix/gno/percent.c new file mode 100644 index 0000000..c7bb891 --- /dev/null +++ b/dmake/unix/gno/percent.c @@ -0,0 +1,257 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/percent.c,v 1.1 1992/01/24 03:29:34 dvadura 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@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. +-- +-- LOG +-- $Log: percent.c,v $ + * Revision 1.1 1992/01/24 03:29:34 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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( char *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 ) */ +{ + 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 = _substr( 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(void)/* +==================== + 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( char *name )/* +================= + Given name, build a DFA and add it to the NFA. The NFA is maintained as + a singly linked list of DFA's. */ +{ + NFAPTR nfa; + + TALLOC(nfa, 1, NFA); + nfa->dfa = _build_dfa(name); + + if( _nfa != NIL(NFA) ) nfa->next = _nfa; + + _nfa = nfa; +} + + +static DFAPTR +_build_dfa( char *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 know 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. +*/ +{ + 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( DFAPTR dfa, char *data )/* +========================= + Take a given dfa and advance it based on the current state, the shift + action in that state, and the current data value. */ +{ + 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(FAIL); + + return(NO_ACTION); +} diff --git a/dmake/unix/gno/posix.h b/dmake/unix/gno/posix.h new file mode 100644 index 0000000..ea8b39b --- /dev/null +++ b/dmake/unix/gno/posix.h @@ -0,0 +1,66 @@ +#ifndef _POSIX_NAME_MAX +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/posix.h,v 1.1 1992/04/07 04:42:46 dvadura 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@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. +-- +-- LOG +-- $Log: posix.h,v $ + * Revision 1.1 1992/04/07 04:42:46 dvadura + * Initial revision + * +*/ + +/* 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 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_MATH_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 + +#endif diff --git a/dmake/unix/gno/public.h b/dmake/unix/gno/public.h new file mode 100644 index 0000000..022f94f --- /dev/null +++ b/dmake/unix/gno/public.h @@ -0,0 +1,153 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +void Infer_recipe ANSI((CELLPTR, CELLPTR)); +int Make_targets ANSI((void)); +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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((void)); +FILE * Search_file ANSI((char *, char **)); +char * Filename ANSI((void)); +int Nestlevel ANSI((void)); +void No_ram ANSI((void)); +int Usage ANSI((int)); +int Version ANSI((void)); +char * Get_suffix ANSI((char *)); +char * Build_path ANSI((char *, char *)); +void Make_rules ANSI((void)); +void Create_macro_vars ANSI((void)); +time_t Do_stat ANSI((char *, char *, char **)); +int Do_touch ANSI((char *, char *, char **)); +void Void_lib_cache ANSI((char *, char *)); +time_t Do_time ANSI((void)); +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)); +#if defined(GNO) +void Catch_signals ANSI((void (*)(void))); +#else +void Catch_signals ANSI((void (*)())); +#endif +void Clear_signals ANSI((void)); +void Prolog ANSI((int, char* [])); +void Epilog ANSI((int)); +char * Get_current_dir ANSI((void)); +int Set_dir ANSI((char*)); +char Get_switch_char ANSI((void)); +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)); +void Read_state ANSI((void)); +void Write_state ANSI((void)); +int Check_state ANSI((CELLPTR, STRINGPTR *, int)); +char* basename ANSI((char *)); +void Dump ANSI((void)); +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)); +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((void)); + +#endif diff --git a/dmake/unix/gno/quit.c b/dmake/unix/gno/quit.c new file mode 100644 index 0000000..f0ed329 --- /dev/null +++ b/dmake/unix/gno/quit.c @@ -0,0 +1,89 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/quit.c,v 1.1 1992/01/24 03:27:53 dvadura Exp $ +-- SYNOPSIS -- end the dmake session. +-- +-- DESCRIPTION +-- Handles dmake termination. +-- +-- 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. +-- +-- LOG +-- $Log: quit.c,v $ + * Revision 1.1 1992/01/24 03:27:53 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#if defined (__ORCAC__) +# pragma databank 1 +#endif + +#include "extern.h" + +static void _handle_quit ANSI((char*)); +static int _dont_quit = 0; + + +PUBLIC void +Quit(void)/* +======== 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( char *err_target )/* +============================ + Called by quit and the others to handle the execution of termination code + from within make */ +{ + 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) ); + } +} + +#if defined (__ORCAC__) +# pragma databank 0 +#endif diff --git a/dmake/unix/gno/rmprq.c b/dmake/unix/gno/rmprq.c new file mode 100644 index 0000000..8ef23da --- /dev/null +++ b/dmake/unix/gno/rmprq.c @@ -0,0 +1,109 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/unix/rmprq.c,v 1.1 1992/01/24 03:28:28 dvadura 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@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. +-- +-- LOG +-- $Log: rmprq.c,v $ + * Revision 1.1 1992/01/24 03:28:28 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +PUBLIC void +Remove_prq( 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); + + /* original version + Make( tlp->cl_prq, tlp, NIL(CELL) ); */ + Make (tlp->cl_prq, NIL(CELL)); + 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/gno/ruletab.c b/dmake/unix/gno/ruletab.c new file mode 100644 index 0000000..8a1aa6f --- /dev/null +++ b/dmake/unix/gno/ruletab.c @@ -0,0 +1,57 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/unix/ruletab.c,v 1.1 1992/01/24 03:28:29 dvadura 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@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. +-- +-- LOG +-- $Log: ruletab.c,v $ + * Revision 1.1 1992/01/24 03:28:29 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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", +#ifdef NO_CASE /* for case insensitive filesystems */ + ".MAKEFILES : makefile.mk Makefile", +#else + ".MAKEFILES : makefile.mk Makefile makefile", +#endif + ".SOURCE : .NULL", +#include "startup.h" + 0 }; + +char **Rule_tab = _rules; /* for sundry reasons in Get_environment() */ diff --git a/dmake/unix/gno/rulparse.c b/dmake/unix/gno/rulparse.c new file mode 100644 index 0000000..55ebb99 --- /dev/null +++ b/dmake/unix/gno/rulparse.c @@ -0,0 +1,1315 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/rulparse.c,v 1.1 1992/01/24 03:27:57 dvadura 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@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. +-- +-- LOG +-- $Log: rulparse.c,v $ + * Revision 1.1 1992/01/24 03:27:57 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + +/* prototypes for local functions */ +static void _add_global_prereq ANSI((CELLPTR)); +static int _add_root ANSI((CELLPTR)); +static void _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( int *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. + */ +{ + 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 = _strspn( 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 ))) { + /* 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 = _strdup( tok ); + + attr |= at; + } + else { + int tmp; + + tmp = _is_special( tok ); + if( _is_percent( tok ) ) percent++; + + if( percent ) + if( targets != NIL(CELL) ) + Fatal( "Multiple targets are not allowed in %% rules" ); + else + cp->ce_flag |= F_PERCENT; + + if( special ) + Fatal( "Special target must appear alone", tok ); + else if( !(cp->ce_flag & F_MARK) ) { + cp->ce_link = targets; /* targets are stacked in this list*/ + cp->ce_flag |= F_MARK | F_EXPLICIT; + targets = cp; + + special = tmp; + } + else if( !(cp->ce_attr & A_LIBRARY) ) + Warning("Duplicate entry [%s] in target list",cp->CE_NAME); + } + } + 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) ) + Warning("Duplicate entry [%s] in prerequisite list",cp->CE_NAME); + } + + /* endwhile */ + + /* 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( char *op )/* +================ + Check the passed in op string and map it to one of the rule operators */ +{ + 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; + + default : ret = 0; /* an invalid modifier, chuck whole string */ + } + + if( *op != '\0' ) ret = 0; + } + + DB_RETURN( ret ); +} + + +PUBLIC void +Add_recipe_to_list( char *rule, int white_too, int 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. */ +{ + 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( int 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) */ +{ + 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); + + 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; + + /* 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) ); + + /* 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( char *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. */ +{ + int res = (*_strspn(list,"@-%+ \t") == '['); + if( res ) _sv_attr |= Rcp_attribute(list); + return(res); +} + + +static void +_do_special( + +/* +================================================================== + 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; + + 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 ignore = (((Glob_attr | attr) & A_IGNORE) != 0); + int pushed = FALSE; + 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; + + 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( fil != NIL(FILE) ) + Parse( fil ); + else if( !((Glob_attr | attr) & A_IGNORE) ) + Fatal( "Include file %s, not found", name ); + } + + if( pushed ) Pop_dir(FALSE); + attr &= ~(A_IGNORE|A_SETDIR); + } + 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( +/*================================================= */ +int op, +t_attr attr, +char *set_dir, +CELLPTR targets, +CELLPTR prereq) +{ + CELLPTR tg1; /* temporary target pointer */ + CELLPTR tp1; /* temporary prerequisite pointer */ + char *p; /* temporary char pointer */ + CELLPTR prev_cell; /* pointer for .UPDATEALL processing */ + CELLPTR first_cell; /* pointer for .UPDATEALL processing */ + int update; /* A_UPDATEALL attribute flag */ + int smagic = 0; /* collective amount of magic :-) */ + int tflag = FALSE; /* set to TRUE if we add target to root */ + + DB_ENTER( "_do_targets" ); + + if((update = ((attr & A_UPDATEALL) != 0)) ) + if( targets == NIL(CELL) ) + Fatal( ".UPDATEALL attribute requires non-empty list of targets" ); + + first_cell = prev_cell = 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); + smagic |= magic; + + if( !(op & R_OP_DCL ) && (tg1->ce_flag & F_MULTI) && !magic ) + Fatal( "Inconsistency in inference rules for %s", tg1->CE_NAME ); + + if( magic ) + do { + _build_graph( op, tg1, prereq ); + if( prereq != NIL(CELL) ) prereq = prereq->ce_link; + } while( prereq != NIL(CELL) ); + else if( !(tg1->ce_flag & F_SPECIAL) && + (prereq == NIL(CELL)) && + (p = _is_magic( tg1->CE_NAME )) != NIL(char)) + smagic |= _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 ); + + if( update ) { + if( smagic ) Fatal( ".UPDATEALL attribute not legal in meta rule" ); + + /* Check this as it would break another circular .UPATEALL list if + * we blindly assign it and it is part of another list already. */ + if( tg1->ce_all != NIL(CELL) ) + Fatal( "Target [%s] appears on multiple .UPDATEALL lists" ); + + tg1->ce_all = prev_cell; + if( prev_cell == NIL(CELL) ) first_cell = tg1; + prev_cell = 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; + if( first_cell != NIL(CELL) ) first_cell->ce_all = prev_cell; + + + /* 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. + * Cannot happen for F_PERCENT targets. (ie. in that case targets is always + * not NIL) */ + + 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 ); + + /* Fix up the ce_link pointers so that when we go to attach a recipe in + * Bind_targets to rules we get the right thing if it's an .UPDATEALL :: + * recipe */ + if( update ) { + for( tp1=NIL(CELL),tg1=prev_cell; tg1!=first_cell; tg1=tg1->ce_all ) { + tg1->ce_link = tp1; + tp1 = tg1; + } + tg1->ce_link = tp1; + targets = first_cell; + } + + /* 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( +/* +===================================================== + This function takes a magic target of the form .. or + . 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 = _substr( 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( 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( char *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 *tmp; + int test = Augmake ? name[strlen(name)-1] == '~' : 0; + + tmp = _strjoin( test ? "s.%" : "%", name, -1, FALSE); + if( test ) tmp[ strlen(tmp)-1 ] = '\0'; + + return(tmp); +} + + + +static void +_build_graph( int op, CELLPTR target, CELLPTR 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. + + It also assumes that target cell has F_PERCENT set already. */ +{ + LINKPTR edl; + CELLPTR edge; + int match; + + DB_ENTER( "_build_graph" ); + DB_PRINT( "%", ("Building graph for [%s : %s]", target->CE_NAME, + (prereq == NIL(CELL)) ? "" : prereq->CE_NAME) ); + + if( prereq != NIL(CELL) ) { + char *name = prereq->CE_NAME; + int len = strlen(name); + + if( *name == '\'' && name[len-1]=='\'' ){ + _add_global_prereq( prereq ); + name[len-1] = '\0'; + strcpy(name, name+1); + DB_VOID_RETURN; + } + } + + /* Search the list of prerequisites for the current target and see if + * any of them match the current %-meta : prereq pair. NOTE that %-metas + * are built as if they were F_MULTI targets. */ + + match = FALSE; + for( edl=target->ce_prq; edl != NIL(LINK); edl=edl->cl_next ) { + edge = edl->cl_prq; + + DB_PRINT( "%", ("Trying to match [%s]", edge?edge->CE_NAME:"(nil)") ); + + if( (!edge->ce_prq && !prereq) + || ( edge->ce_prq + && (edge->ce_prq->cl_prq == prereq) + && ( (edge->ce_dir == _sv_setdir) + || ( edge->ce_dir + && _sv_setdir + && !strcmp(edge->ce_dir,strchr(_sv_setdir,'=')+1) + ) + ) + ) + ) { + match = TRUE; + break; + } + } + + if( match ) { + /* match is TRUE hence, we found an edge joining the target and the + * prerequisite so reset the new edge's how values to reflect the new + * recipe etc. */ + 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") ); + + if( !(target->ce_flag & F_DFA) ) { + Add_nfa( target->CE_NAME ); + target->ce_flag |= F_DFA; + } + edge = _make_multi(target); + if( prereq ) Add_prerequisite(edge, prereq, 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_VOID_RETURN; +} + + +static CELLPTR +_make_multi( CELLPTR tg ) +{ + CELLPTR cp; + + /* This first handle 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; + + 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); + } + else { + cp->ce_flag &= ~(F_RULES|F_MULTI); + cp->ce_attr &= ~A_SEQ; + cp->ce_prq = NIL(LINK); + cp->ce_index = 0; + } + cp->ce_count = ++tg->ce_index; + cp->ce_flag |= F_TARGET; + + Add_prerequisite(tg, cp, FALSE, TRUE); + return(cp); +} + + +static void +_add_global_prereq( CELLPTR pq )/* +========================== + Prerequisite is a non-% prerequisite for a %-rule target, add it to + the target's list of global prerequsites to add on match */ +{ + register LINKPTR ln; + + TALLOC( ln, 1, LINK ); + ln->cl_next = _sv_glb_prq; + ln->cl_prq = pq; + _sv_glb_prq = ln; +} + + + +static void +_set_attributes( +/* +====================================== + 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 ) { + dir = strchr( set_dir, '=' ) + 1; + + if( cp->ce_dir ) + Warning( "Multiple .SETDIR for %s ignored", cp->CE_NAME ); + else + if( *dir ) cp->ce_dir = _strdup(dir); + } + cp->ce_attr |= attr; /* set rest of attributes for target */ + + DB_VOID_RETURN; +} + + + +static void +_set_global_attr( t_attr attr )/* +========================== + Handle the setting of the global attribute functions based on + The attribute flags set in 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( +/* +========================== + 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( char *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 + + 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. */ +{ + t_attr attr = 0; + + DB_ENTER( "_is_attribute" ); + + if( *name++ == '.' ) + switch( *name ) + { + case 'E': attr = (strcmp(name, "EPILOG")) ? 0 : A_EPILOG; break; + case 'I': attr = (strcmp(name, "IGNORE")) ? 0 : A_IGNORE; break; + case 'L': attr = (strcmp(name, "LIBRARY")) ? 0 : A_LIBRARY; break; + case 'M': attr = (strcmp(name, "MKSARGS")) ? 0 : A_MKSARGS; 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( char *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 + .INCLUDEDIRS .MAKEFILES .REMOVE .KEEP_STATE +*/ +{ + DB_ENTER( "_is_special" ); + + if( *tg++ != '.' ) DB_RETURN( 0 ); + + switch( *tg ) + { + 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 'M': + if( !strcmp( tg, "MAKEFILES" ) ) DB_RETURN( ST_REST ); + break; + + case 'E': + if( !strcmp( tg, "ERROR" ) ) DB_RETURN( ST_REST ); + else if( !strcmp( tg, "EXPORT" ) ) DB_RETURN( ST_EXPORT ); + break; + + case 'G': + if( !strcmp( tg, "GROUPPROLOG" )) DB_RETURN( ST_REST ); + else if( !strcmp( tg, "GROUPEPILOG" )) DB_RETURN( ST_REST ); + break; + + case 'K': + if( !strcmp( tg, "KEEP_STATE" ) ) DB_RETURN( ST_KEEP ); + 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( char *np )/* +=================== + return TRUE if np points at a string containing a % sign */ +{ + return( (strchr(np,'%') && (*np != '\'' && np[strlen(np)-1] != '\'')) ? + TRUE : FALSE ); +} + + +static char * +_is_magic( char *np )/* +================= + return TRUE if np points at a string of the form + .. or . + where chars are only alpha characters. + + NOTE: reject target if it begins with ./ or ../ */ +{ + 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( !Augmake ) + return( NIL(char) ); + + /* np points at the second . of .. string. + * if the special target is of the form . then np points at the + * first . in the token. */ + + return( np ); +} + + +static int +_add_root( CELLPTR tg) +{ + int res = FALSE; + + if( !Target && !(tg->ce_flag & (F_SPECIAL|F_PERCENT)) ) { + Add_prerequisite( Root, tg, FALSE, TRUE ); + + tg->ce_flag |= F_TARGET; + tg->ce_attr |= A_FRINGE; + res = TRUE; + } + + return(res); +} diff --git a/dmake/unix/gno/runargv.c b/dmake/unix/gno/runargv.c new file mode 100644 index 0000000..3584980 --- /dev/null +++ b/dmake/unix/gno/runargv.c @@ -0,0 +1,193 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif + +/* if gsh $PATH parsing ever gets straighted out, remove this */ +#define BACKWARDS + +#include +#include +#include "extern.h" +#include "sysintf.h" + +static int _abort_flg = FALSE; +static void _add_child ANSI((CELLPTR, int)); +static void _finished_child ANSI((int)); + +static int child_status; /* the exit value of the child process */ + +/* These two are from lenviron */ +extern char *build_cmd (char *const *argv); +extern char *build_path (const char *file); + +#pragma databank 1 + +static void child_process(char *path, char *comd) { + _execve(path, comd); + return; +} +#pragma databank 0 + +/* + * static int execp(const char *file, char *const argv[]); + * + * This is like the Gno/ME exec(2) routine in that it waits for the child + * to exit before returning. The difference is that it will find + * if it is in the $PATH, and expects an array of strings (vice a single + * string) as the second argument. + * + * This is very much a _non_ standard function ... + * + * returns: + * -1 and errno set if execp call failed (child_status undefined) + * otherwise return 0, errno=0, and child_status is the return value + * of the called program + */ + +static int execp(const char *file, char *const argv[]) { + char *comd; + char *path; + int result; + int w_result; + union wait w_status; + int terrno; + + /* errno = 0; (This is set in runargv() just before calling execp()) */ + + /* + * Are we using a full or partial pathname? If partial, then we have + * to build it. + */ + + if (If_root_path(file)) { + /* full pathname */ + path = strdup(file); + if (!path) return -1; + } else { + /* partial pathname: is $PATH defined in the environment? */ + path = getenv("PATH"); + if (path) { /* PATH exists; good start ... */ + path = build_path (file); + if (path == NULL) return -1; + } else { /* no PATH; use default */ +#ifdef BACKWARDS + if (setenv("PATH","/usr/bin /bin",1) != 0) return -1; +#else + if (setenv("PATH","/bin /usr/bin",1) != 0) return -1; +#endif + path = build_path (file); + result = (path == NULL) ? -1 : 0; + terrno = errno; /* unsetenv may affect errno */ + unsetenv("PATH"); + errno = terrno; + if (result!=0) return -1; + } + } + + /* build the command line */ + comd = build_cmd (argv); + if (comd == NULL) { + terrno = errno; + free(path); + errno = terrno; + return -1; + } + + /* execute it */ + result = fork2(child_process, 1536, 0, "forked child of dmake", 4, + path, comd); + + /* the parent has to wait for the child to exit so we can get the status */ + if (result != -1) { + + /* this method will only work if there are no other children! */ + for (;;) { + w_result = wait (&w_status); + if (w_result == -1) { + result = -1; + break; + } + /* + * we can ignore WIFSIGNALLED in the following test because we + * have a signal handler installed + */ + if (WIFEXITED(w_status) || WIFSIGNALED(w_status)) { + child_status = w_status.w_retcode; + result = 0; + break; + } + } + } + + /* + * At this point, "result" has been set under all conditions, and there + * is no child process left. + */ + + /* free the memory */ + terrno = errno; + free(path); + free(comd); + errno = terrno; + + return result; +} + +PUBLIC int +runargv(CELLPTR target, int ignore, int group, int last, int shell, char *cmd) +{ + char **argv; + int pid; + + argv = Pack_argv( group, shell, cmd ); + _add_child(target, ignore); + + errno = 0; + if (execp (*argv, argv) == -1) + Error("%s: %s", argv[0], strerror(errno)); + + _finished_child(child_status); + if( last && !Doing_bang ) Update_time_stamp( target ); + + return 0; /* means: all children exited */ +} + + +PUBLIC void +Clean_up_processes(void) +{ + _abort_flg = TRUE; + _finished_child(-1); +} + + +PUBLIC int +Wait_for_child( int abort_flg, int pid ) +{ + return(1); +} + + +static int _valid = -1; +static CELLPTR _tg; +static int _ignore; + +static void +_add_child( CELLPTR target, int ignore ) +{ + _tg = target; + _ignore = ignore; + _valid = 0; + + Current_target = NIL(CELL); +} + + +static void +_finished_child( int status) +{ + if( _valid == -1 ) return; + Unlink_temp_files( _tg ); + _valid = -1; + Handle_result( status, _ignore, _abort_flg, _tg ); +} diff --git a/dmake/unix/gno/startup.h b/dmake/unix/gno/startup.h new file mode 100644 index 0000000..a8bd876 --- /dev/null +++ b/dmake/unix/gno/startup.h @@ -0,0 +1,7 @@ +/* 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/startup.mk", diff --git a/dmake/unix/gno/stat.c b/dmake/unix/gno/stat.c new file mode 100644 index 0000000..bb0f325 --- /dev/null +++ b/dmake/unix/gno/stat.c @@ -0,0 +1,243 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/stat.c,v 1.1 1992/01/24 03:27:58 dvadura 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@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. +-- +-- LOG +-- $Log: stat.c,v $ + * Revision 1.1 1992/01/24 03:27:58 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" + + +static int _check_dir_list ANSI((CELLPTR, CELLPTR, int)); + +#ifdef DBUG + /* Just a little ditty for debugging this thing */ + static time_t + _do_stat( char *name, char *lib, char **sym ) + { + time_t res; + DB_ENTER( "_do_stat" ); + + res = Do_stat(name, lib, sym); + DB_PRINT( "stat", ("Statted [%s,%s,%d,%ld]", name, lib, sym, res) ); + + DB_RETURN( res ); + } +#define DO_STAT(A,B,C) _do_stat(A,B,C) +#else +#define DO_STAT(A,B,C) Do_stat(A,B,C) +#endif + +static char *_first; /* local storage of first attempted path */ + +PUBLIC void +Stat_target( CELLPTR cp, int setfname )/* +============================= + 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. */ + +{ + 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 ); + + 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 _strdup */ + + 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 = _strjoin( ".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 ); + + /* Check just .SOURCE */ + if( !res && (srchp != NIL(HASH)) ) + res = _check_dir_list( cp, srchp->CP_OWNR, setfname ); + + /* 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 *)); + + if( !cp->ce_time && Tmd && *Tmd && cp->ce_lib ) { + cp->ce_lib=Build_path(Tmd,cp->ce_lib); + cp->ce_time = DO_STAT(name, cp->ce_lib, NIL(char *)); + } + + 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) ) { + 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; + } + } + 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; + + DB_VOID_RETURN; +} + + + +static int +_check_dir_list( CELLPTR cp, CELLPTR sp, int setfname )/* +===================================== + 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. */ + +{ + register 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 and 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 = Build_path( dir, name ); + + res = ((cp->ce_time = DO_STAT(path,NIL(char),NIL(char *))) != (time_t)0L); +#if 0 +I think this will break a lot of things! + /* It didn't work and TMD macro has a value so try to stat it + * relative to the original MAKEDIR directory. */ + if( Tmd && !*Tmd && !res ) { + char *p = _strdup(path); + path = Build_path(Tmd,p); FREE(p); + res = ((cp->ce_time = DO_STAT(path,NIL(char),NIL(char *))) != (time_t)0L); + } +#endif + + /* Have to use _strdup 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 ); + _first = nodup ? NIL(char) : _strdup(path); + fset = 1; + } + + DB_PRINT( "stat", ("_first [%s], path [%s]", _first, path) ); + if( dir != lp->cl_prq->CE_NAME ) FREE(dir); + } + } + + DB_PRINT( "mem", ("%s:-< mem %ld", cp->CE_NAME, (long) coreleft()) ); + DB_RETURN( res ); +} diff --git a/dmake/unix/gno/state.c b/dmake/unix/gno/state.c new file mode 100644 index 0000000..66cf3d7 --- /dev/null +++ b/dmake/unix/gno/state.c @@ -0,0 +1,233 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/state.c,v 1.2 1992/04/07 04:42:46 dvadura 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@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. +-- +-- LOG +-- $Log: state.c,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Removed a parameter to call of Closefile(), it doesn't need one. + * + * Revision 1.1 1992/01/24 03:27:05 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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(void) +{ + 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 = _strdup(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(void) +{ + 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( +CELLPTR cp, +STRINGPTR *recipes, +int maxrcp) +{ + KSTATEPTR st; + STRINGPTR sp; + int i; + uint32 thkey; + uint32 hkey; + uint32 nkey; + uint32 dkey; + int update = 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 ; ist_next ) { + char *cmnd = Expand(sp->st_string); + + (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( +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/unix/gno/stdmacs.h b/dmake/unix/gno/stdmacs.h new file mode 100644 index 0000000..d2f49ac --- /dev/null +++ b/dmake/unix/gno/stdmacs.h @@ -0,0 +1,68 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/stdmacs.h,v 1.1 1992/01/24 03:29:36 dvadura 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@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. +-- +-- LOG +-- $Log: stdmacs.h,v $ + * Revision 1.1 1992/01/24 03:29:36 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#ifndef MACROS_h +#define MACROS_h + +/* stupid AIX and Mac MPW define __STDC__ as special, but defined(__STDC__) is false, and + * it's value is nothing */ +#if !defined(__STDC__) && !defined(_AIX) && !defined(_MPW) +#define __STDC__ 0 +#endif + +#if __STDC__ || defined(__TURBOC__) +#define ANSI(x) x +#else +#define ANSI(x) () +#endif + +#ifdef __ORCAC__ +# undef NIL +#endif + +#define NIL(p) ((p*)NULL) + +#if !defined(atarist) +#define offsetof(type,id) ((size_t)&((type*)NULL)->id) +#endif + +#define FALSE 0 +#define TRUE 1 + +#define PUBLIC + +#endif diff --git a/dmake/unix/gno/struct.h b/dmake/unix/gno/struct.h new file mode 100644 index 0000000..cd659cd --- /dev/null +++ b/dmake/unix/gno/struct.h @@ -0,0 +1,259 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/struct.h,v 1.1 1992/01/24 03:29:32 dvadura 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@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. +-- +-- LOG +-- $Log: struct.h,v $ + * Revision 1.1 1992/01/24 03:29:32 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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 */ + char *ht_name; /* name of this cell */ + char *ht_value; /* cell value if and */ + uint32 ht_hash; /* actual hash_value 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; + + + +/* 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 tcell *ce_all; /* link for grouping UPDATEALL cells*/ + struct tcell *ce_setdir; /* SETDIR ROOT pointer for this cell*/ + struct tcell *ce_link; /* link for temporary list making */ + + struct lcell *ce_prq; /* list of prerequisites for cell */ + 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 */ + + 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 + + +/* 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; + + +/* 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; + + + +/* 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/unix/gno/sysintf.c b/dmake/unix/gno/sysintf.c new file mode 100644 index 0000000..c02b3dd --- /dev/null +++ b/dmake/unix/gno/sysintf.c @@ -0,0 +1,694 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/sysintf.c,v 1.2 1992/04/07 04:42:46 dvadura 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() -- from unix/arlib.c +-- touch_arch() -- from unix/arlib.c +-- void_lcache() -- from unix/arlib.c +-- runargv() -- from unix/runargv.c +-- STAT() +-- Remove_prq() +-- +-- C-LIB SPECIFIC: (should be present in your C-lib) +-- utime() +-- time() -- orcalib +-- getenv() -- lenviron, orcalib +-- putenv() -- lenviron +-- getcwd() +-- signal() -- libgno, orcalib +-- chdir() -- lbsd +-- tempnam() +-- +-- 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. +-- +-- LOG +-- $Log: sysintf.c,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Replaced the use of _POSIX_NAME_MAX and MAX_PATH_LEN by NAME_MAX and + * PATH_MAX respectively. + * + * Revision 1.1 1992/01/24 03:27:08 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include "extern.h" +#include "sysintf.h" + +#if defined(__GNUC__) +void (*signal(int sig, void(*func)()))(); +#endif + +/* +** 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 _strdup the name and return make the +** pointer pointed at by sym point at it. Not handled for now! +*/ +PUBLIC time_t +Do_stat( + char *name, + char *lib, + char **member) +{ + struct stat buf; + +#if !defined(GNO) + time_t seek_arch(); +#endif + + 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( strlen(basename(name)) > NAME_MAX ) + return((time_t)0L); + else + return( (STAT(name,&buf)==-1 || (Augmake && (buf.st_mode & S_IFDIR))) + ? (time_t)0L + : (time_t) buf.st_mtime + ); +} + + + +/* Touch existing file to force modify time to present. + */ +PUBLIC int +Do_touch( + 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 + return( utime(name, NIL(struct utimbuf)) ); +} + + + +PUBLIC void +Void_lib_cache( char *lib_name, char *member_name )/* +========================================= + Void the library cache for lib lib_name, and member member_name. */ +{ + VOID_LCACHE( lib_name, member_name ); +} + + + +/* +** return the current time +*/ +PUBLIC time_t +Do_time(void) +{ +#if !defined(GNO) + extern time_t time(); +#endif + 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( + 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( Max_proc == 1 ) Wait_for_completion = TRUE; + + i = runargv(target, ignore, group, last, shell, cmd); + + if (i == -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( 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; + } + + if( (Packed_shell = shell||group||(*_strpbrk(cmd, Shell_metas)!='\0')) ) { + 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(char *ename) +{ +#if !defined(_MSC_VER) || _MSC_VER < 600 +#if !defined (GNO) + extern char *getenv(); +#endif /* GNO */ +#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(char *ename, char *value) +{ +#if !defined(GNO) + extern int putenv(); +#endif + char* p; + char* envstr = _stradd(ename, value, FALSE); + + p = envstr+strlen(ename); /* Don't change this code, _stradd 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) ); +} + +#if defined(__GNUC__) || defined(__ORCAC__) +extern char **environ; +#endif + +PUBLIC void +ReadEnvironment(void) +{ + 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(void (*fn)(void)) +{ + if( signal(SIGINT, SIG_IGN) != SIG_IGN ) + signal( SIGINT, fn ); + if( signal(SIGQUIT, SIG_IGN) != SIG_IGN ) + signal( SIGQUIT, fn ); +} + + + +/* +** Clear any previously set signals +*/ +PUBLIC void +Clear_signals(void) +{ + if( signal(SIGINT, SIG_IGN) != SIG_IGN ) + signal( SIGINT, SIG_DFL ); + if( signal(SIGQUIT, SIG_IGN) != SIG_IGN ) + signal( SIGQUIT, SIG_DFL ); +} + + + +/* +** Set program name +*/ +PUBLIC void +Prolog(int argc, char *argv[]) +{ + char buf[50]; + + Pname = (argc == 0) ? DEF_MAKE_PNAME : argv[0]; + sprintf( buf, "dmake-%d-root", GETPID ); + Root = Def_cell( buf ); + tzset(); +} + +#if defined (DEBUG) +int end_stack_check(void); +#endif + +/* +** Do any clean up for exit. +*/ +PUBLIC void +Epilog(int ret_code) +{ + Write_state(); + Unlink_temp_files(Root); + Hook_std_writes(NIL(char)); /* For MSDOS tee (-F option) */ + +#if defined(DEBUG) + if(getenv("CHECKSTACK")) printf("dmake stack usage = %d bytes\n", + end_stack_check()); +#endif + + exit( ret_code ); +} + + + +/* +** Use the built-in functions of the operating system to get the current +** working directory. +*/ +PUBLIC char * +Get_current_dir(void) +{ +#if defined (GNO) +#define PATH_MAX2 66 +#if ((PATH_MAX + 2) != PATH_MAX2 ) +#error "sysintf.c: ensure PATH_MAX2 is same as PATH_MAX + 2" +#endif + + static char buf[PATH_MAX2]; /* must be identical to PATH_MAX + 2 */ +#else + static char buf[PATH_MAX+2]; +#endif + return(getcwd(buf, sizeof(buf))); +} + + + +/* +** change working directory +*/ +PUBLIC int +Set_dir(char *path) +{ + if (strlen(path)) { + return( chdir(path) ); + } else { + return( chdir(".")); + } +} + + + +/* +** return switch char +*/ +PUBLIC char +Get_switch_char(void) +{ + 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(char **path, char *suff, int op) +{ +#if !defined (GNO) + extern char *tempnam(); +#endif + + *path = _strjoin( 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( 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( 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( 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(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( CELLPTR 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. */ +{ + 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 ) + printf( "%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(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 ) { + fprintf( stderr, "%s: Error code %d, while making '%s'", + Pname, status, target->ce_fname ); + + if( ignore || Continue ) { + fputs( " (Ignored)\n", stderr ); + } + else { + fputc( '\n', stderr ); + + if( !(target->ce_attr & A_PRECIOUS) ) + 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) ) + Remove_file( target->ce_fname ); +} + + +PUBLIC void +Update_time_stamp( CELLPTR cp ) +{ + HASHPTR hp; + CELLPTR tcp; + int phony = ((cp->ce_attr&A_PHONY) != 0); + + tcp = cp; + do { + 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 ) + Stat_target(tcp, -1); + + 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 %ld\n", + Pname, tcp->CE_NAME, tcp->ce_time ); + + Unlink_temp_files( tcp ); + tcp->ce_flag |= F_MADE; + tcp->ce_attr |= A_UPDATED; + tcp = tcp->ce_all; + } + while( tcp != NIL(CELL) && tcp != cp ); + + + /* 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) && + !Force; + + if( rem ) { + CELLPTR tmp = prq; + do { + (Add_prerequisite(tcp,prq,FALSE,FALSE))->cl_flag |= F_TARGET; + prq->ce_flag &= ~F_REMOVE; + prq = prq->ce_all; + } + while( prq != NIL(CELL) && prq != tmp ); + flag = TRUE; + } + } + + if( flag ) { + Remove_prq( tcp ); + + 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( 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/unix/gno/sysintf.h b/dmake/unix/gno/sysintf.h new file mode 100644 index 0000000..5f57946 --- /dev/null +++ b/dmake/unix/gno/sysintf.h @@ -0,0 +1,31 @@ +/* +** assorted bits of system interface, for common routines inside dmake. +** System specific code can be found in the config.h files for each +** of the system specifications. +*/ +#define STAT stat +#define VOID_LCACHE(l,m) (void) void_lcache(l,m) +#define Hook_std_writes(A) +#define GETPID getpid() + +/* +** standard C items +*/ + +/* +** Gno/ME items +*/ + +#ifdef GNO +#include +#endif + +/* +** DOS interface standard items +*/ +#define getswitchar() '-' + +/* +** make parameters +*/ +#define MAX_PATH_LEN 1024 diff --git a/dmake/unix/gno/tempnam.c b/dmake/unix/gno/tempnam.c new file mode 100644 index 0000000..1543c39 --- /dev/null +++ b/dmake/unix/gno/tempnam.c @@ -0,0 +1,95 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/*LINTLIBRARY*/ + +#include +#include +#include +#include + +#define max(A,B) (((A)<(B))?(B):(A)) + +#if !defined(GNO) +extern char *mktemp(); +extern int access(); +#endif + +#if defined(__GNUC__) +char *mktemp(char *); +#endif + +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 + + +static char * +cpdir(char *buf, char *str) +{ + char *p; + + if(str != NULL) + { + (void) strcpy(buf, str); + p = buf - 1 + strlen(buf); + if(*p == '/') *p = '\0'; + } + + return(buf); +} + + +char * +tempnam( +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 int)(max(max(dl,tl),pl)+16))) == NULL ) + return(NULL); + + *p = '\0'; + +#if defined (GNO) + if( (tl == 0) || (access( cpdir(p, tmpdir), W_OK) != 0) ) + if( (dl == 0) || (access( cpdir(p, dir), W_OK) != 0) ) + if( access( cpdir(p, P_tmpdir), W_OK) != 0 ) + if( access( cpdir(p, "/tmp"), W_OK) != 0 ) + return(NULL); + +#else /* not GNO */ + 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); +#endif /* not GNO */ + + (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); +} diff --git a/dmake/unix/gno/utime.c b/dmake/unix/gno/utime.c new file mode 100644 index 0000000..87f4047 --- /dev/null +++ b/dmake/unix/gno/utime.c @@ -0,0 +1,60 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif +/* +** change access and modify times of file +*/ +/* + * Notes about this GS version: Only sets the modification time, + * access time is not used. Assumes that timep[1] contains mod + * time and timep[0] access time. + * Does not create the file if it does not exist. Assumes that the + * file exists, is fine and healthy etc. + */ + +#include +#include +#if !defined(__GNUC__) +# include +# include +#endif + +int +utime(char *name, time_t timep[2]) +{ + static GSString255 gst; + static FileInfoRecGS fir = { 8, &gst }; + struct tm *the_time; + time_t current_time; + + /* first get the File Info */ + fir.pathname->length = strlen (name); + strcpy (fir.pathname->text, name); + GetFileInfoGS (&fir); + if (toolerror()) return (-1); + + /* if timep is null, set the time to the current time, otherwise */ + /* use timep[1], which is the modification time */ + if (timep == NULL) { + current_time = time ((time_t) NULL); + if (current_time == -1) return -1; /* there is no system time */ + the_time = localtime (¤t_time); + } else + the_time = localtime (&timep[1]); + + /* Access time does not exist on the GS, therefore only change */ + /* the modification time. */ + + fir.modDateTime.second = the_time->tm_sec; + fir.modDateTime.minute = the_time->tm_min; + fir.modDateTime.hour = the_time->tm_hour; + fir.modDateTime.year = the_time->tm_year; + fir.modDateTime.day = the_time->tm_mday - 1; + fir.modDateTime.month = the_time->tm_mon; + fir.modDateTime.weekDay = the_time->tm_wday; + + SetFileInfoGS (&fir); /* set again with modified time and date */ + if (toolerror()) return (-1); + + return (0); +} diff --git a/dmake/unix/gno/va.c b/dmake/unix/gno/va.c new file mode 100644 index 0000000..b3228ad --- /dev/null +++ b/dmake/unix/gno/va.c @@ -0,0 +1,119 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif + +#include "extern.h" +#include "patchlvl.h" +#include "version.h" + +extern char _warn; + +/* +** print error message from variable arg list +*/ + +static int errflg = TRUE; +static int warnflg = FALSE; + +/* +** Print error message and abort +*/ + +void Fatal (char *fmt, ...) { + va_list args; + int warn; + + va_start(args, fmt); + Continue = FALSE; + + /* start errargs code */ + 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(); + } + /* end errargs code */ + + va_end(args); +} + +/* +** error message and exit (unless -k) +*/ +void Error (char *fmt, ...) { + va_list args; + int warn; + + va_start(args, fmt); + + /* start errargs code */ + 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(); + } + /* end errargs code */ + + va_end(args); +} + + +/* +** non-fatal message +*/ +void Warning (char *fmt, ...) { + va_list args; + int warn; + + va_start(args, fmt); + warnflg = TRUE; + errflg = FALSE; + + /* start errargs code */ + 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(); + } + /* end errargs code */ + + errflg = TRUE; + warnflg = FALSE; + va_end(args); +} diff --git a/dmake/unix/gno/version.h b/dmake/unix/gno/version.h new file mode 100644 index 0000000..5628453 --- /dev/null +++ b/dmake/unix/gno/version.h @@ -0,0 +1,7 @@ +/* dmake version number. */ + +#define VERSION "3.80" + +#if defined (GNO) +#define IIGSVERSION "1.0" +#endif diff --git a/dmake/unix/gno/vextern.h b/dmake/unix/gno/vextern.h new file mode 100644 index 0000000..3e7d82c --- /dev/null +++ b/dmake/unix/gno/vextern.h @@ -0,0 +1,117 @@ +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/vextern.h,v 1.2 1992/04/07 04:42:46 dvadura 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@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. +-- +-- LOG +-- $Log: vextern.h,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Added the No_exec variable for -X flag. + * + * Revision 1.1 1992/01/24 03:27:19 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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* Prep; /* Value of macro PREP */ +EXTERN char* Makedir; /* pointer to macro value for MAKEDIR */ +EXTERN char* Start_dir; /* cell for macro value for .SETDIR */ +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 int Target; /* TRUE if target found in makefile */ +EXTERN int If_expand; /* TRUE if calling Expand from getinp.c */ +EXTERN int If_multi; /* M_MULTI for expand of single MULTI macs*/ +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 Def_targets; /* TRUE if defining targets */ + +EXTERN CELLPTR Root; /* Root of the make graph */ + +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 Macs[HASH_TABLE_SIZE]; /* hash table for macro defs */ +EXTERN HASHPTR Defs[HASH_TABLE_SIZE]; /* hash table for other defs */ + +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 */ + +#if defined(GNO) && defined(DEBUG) +EXTERN int DebugLevel; /* value of arg to -D */ +#endif diff --git a/dmake/unix/rmprq.c b/dmake/unix/rmprq.c new file mode 100644 index 0000000..737d230 --- /dev/null +++ b/dmake/unix/rmprq.c @@ -0,0 +1,105 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/unix/rmprq.c,v 1.1 1992/01/24 03:28:28 dvadura 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@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. +-- +-- LOG +-- $Log: rmprq.c,v $ + * Revision 1.1 1992/01/24 03:28:28 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#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, tlp, NIL(CELL) ); + 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 0000000..2c777be --- /dev/null +++ b/dmake/unix/ruletab.c @@ -0,0 +1,50 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/unix/ruletab.c,v 1.1 1992/01/24 03:28:29 dvadura 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@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. +-- +-- LOG +-- $Log: ruletab.c,v $ + * Revision 1.1 1992/01/24 03:28:29 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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/unix/runargv.c b/dmake/unix/runargv.c new file mode 100644 index 0000000..01ada4f --- /dev/null +++ b/dmake/unix/runargv.c @@ -0,0 +1,299 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/unix/runargv.c,v 1.1 1992/01/24 03:28:50 dvadura Exp $ +-- SYNOPSIS -- invoke a sub process. +-- +-- DESCRIPTION +-- Use the standard methods of executing a sub process. +-- +-- 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. +-- +-- LOG +-- $Log: runargv.c,v $ + * Revision 1.1 1992/01/24 03:28:50 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include +#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; + 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" ); + + 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; ipr_valid = 1; + pp->pr_pid = pid; + pp->pr_target = target; + pp->pr_ignore = ignore; + pp->pr_last = last; + pp->pr_dir = _strdup(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; iprp_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); + + 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; iprp_cmd = _strdup(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/startup.h b/dmake/unix/startup.h new file mode 100644 index 0000000..74ea12e --- /dev/null +++ b/dmake/unix/startup.h @@ -0,0 +1,7 @@ +/* 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/software/dmake/data/startup.mk", diff --git a/dmake/unix/sysintf.h b/dmake/unix/sysintf.h new file mode 100644 index 0000000..b0b99da --- /dev/null +++ b/dmake/unix/sysintf.h @@ -0,0 +1,23 @@ +/* +** assorted bits of system interface, for common routines inside dmake. +** System specific code can be found in the config.h files for each +** of the system specifications. +*/ +#define STAT stat +#define VOID_LCACHE(l,m) (void) void_lcache(l,m) +#define Hook_std_writes(A) +#define GETPID getpid() + +/* +** standard C items +*/ + +/* +** DOS interface standard items +*/ +#define getswitchar() '-' + +/* +** make parameters +*/ +#define MAX_PATH_LEN 1024 diff --git a/dmake/unix/sysvr1/config.h b/dmake/unix/sysvr1/config.h new file mode 100644 index 0000000..97d4c27 --- /dev/null +++ b/dmake/unix/sysvr1/config.h @@ -0,0 +1,54 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/unix/sysvr1/config.h,v 1.1 1992/01/24 03:28:18 dvadura 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@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. +-- +-- LOG +-- $Log: config.h,v $ + * Revision 1.1 1992/01/24 03:28:18 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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 + +/* Define the getcwd function that is used in the code, since BSD does + * not have getcwd, but call it getwd instead. */ +extern char *getcwd ANSI((char *, int)); + +/* Define setvbuf, SysV doesn't have one */ +#define setvbuf(fp, bp, type, len) setbuf( fp, NULL ); + +/* We don't care about CONST */ +#define CONST + +/* a small problem with pointer to voids on some unix machines needs this */ +#define PVOID void * diff --git a/dmake/unix/sysvr1/config.mk b/dmake/unix/sysvr1/config.mk new file mode 100644 index 0000000..d1cd2d8 --- /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 0000000..ee8995e --- /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 basename.c +mv basename.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/sysvr1/vfprintf.c +mv vfprintf.o objects +cc -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/basename.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/vfprintf.o +cp unix/sysvr1/startup.mk startup.mk diff --git a/dmake/unix/sysvr1/public.h b/dmake/unix/sysvr1/public.h new file mode 100644 index 0000000..796aa7a --- /dev/null +++ b/dmake/unix/sysvr1/public.h @@ -0,0 +1,149 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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(()); + +#endif diff --git a/dmake/unix/sysvr1/putenv.c b/dmake/unix/sysvr1/putenv.c new file mode 100644 index 0000000..80d4397 --- /dev/null +++ b/dmake/unix/sysvr1/putenv.c @@ -0,0 +1,87 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/unix/sysvr1/putenv.c,v 1.1 1992/01/24 03:28:26 dvadura 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@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. +-- +-- LOG +-- $Log: putenv.c,v $ + * Revision 1.1 1992/01/24 03:28:26 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +#include +#include + +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/startup.mk b/dmake/unix/sysvr1/startup.mk new file mode 100644 index 0000000..68a74e2 --- /dev/null +++ b/dmake/unix/sysvr1/startup.mk @@ -0,0 +1,137 @@ +# Generic UNIX DMAKE startup file. Customize to suit your needs. +# Should work for both SYSV, and BSD 4.3 +# 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 => RCS is installed. +_HAVE_SCCS := yes # yes => SCCS is installed. + +# Applicable suffix definitions +A := .a # Libraries +E := # Executables +F := .f # Fortran +O := .o # Objects +P := .p # Pascal +S := .s # Assembler sources +V := ,v # RCS suffix + +# Recipe execution configurations +SHELL := /bin/sh +SHELLFLAGS := -ce +GROUPSHELL := $(SHELL) +GROUPFLAGS := +SHELLMETAS := |();&<>?*][$$:\\#`'" +GROUPSUFFIX := + +# Standard C-language command names and flags + CPP := /lib/cpp # C-preprocessor + CC := cc # C-compiler and flags + CFLAGS = + + AS := as # Assembler and flags + ASFLAGS = + + LD = $(CC) # Loader and flags + LDFLAGS = + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(MFLAGS) + +# Definition of Print command for this system. + PRINT = lp + +# Language and Parser generation Tools and their flags + YACC := yacc # standard yacc + YFLAGS = + YTAB := y.tab # yacc output files name stem. + + LEX := lex # standard lex + LFLAGS = + LEXYY := lex.yy # lex output file + +# Other Compilers, Tools and their flags + PC := pc # pascal compiler + RC := f77 # ratfor compiler + FC := f77 # fortran compiler + + CO := co # check out for RCS + COFLAGS := -q + + AR := ar # archiver + ARFLAGS = -rv + + RM := /bin/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 : %$P ; $(PC) $(PFLAGS) -c $< + %$O : %$S ; $(AS) $(ASFLAGS) -o $@ $< + %$O : %.cl ; class -c $< + %$O : %.e %.r %.f %.F %$F + $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $< + +# Executables + %$E : %$O ; $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS) + %$E : %.sh; cp $< $@; chmod 0777 $@ + +# lex and yacc rules + %.c : %.y %.Y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@ + %.c : %.l %.L ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@ + +# This rule tells how to make *.out from it's immediate list of prerequisites +# UNIX only. + %.out :; $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +# RCS support +.IF $(_HAVE_RCS) + % : %$V $$(@:d)RCS/$$(@:f)$V;- $(CO) $(COFLAGS) $@ + .NOINFER : %$V $$(@:d)RCS/$$(@:f)$V +.END + +# SCCS support +.IF $(_HAVE_SCCS) + GET = get + GFLAGS = + % : s.% ; $(GET) $(GFLAGS) $< + .NOINFER : s.% +.END + +# Recipe to make archive files. +%$A : +[ + $(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) + +#endif + +#endif /* _STDLIB_INCLUDED_ */ diff --git a/dmake/unix/sysvr1/time.h b/dmake/unix/sysvr1/time.h new file mode 100644 index 0000000..b9fb543 --- /dev/null +++ b/dmake/unix/sysvr1/time.h @@ -0,0 +1,10 @@ +/* +** 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/sysvr1/vfprintf.c b/dmake/unix/sysvr1/vfprintf.c new file mode 100644 index 0000000..64cde0c --- /dev/null +++ b/dmake/unix/sysvr1/vfprintf.c @@ -0,0 +1,58 @@ +/* From: + * John Limpert johnl@gronk.UUCP uunet!n3dmc!gronk!johnl + */ + +#include +#include + +#ifndef BUFSIZ +#include +#endif + +#ifndef va_dcl +#include +#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.h b/dmake/unix/sysvr3/config.h new file mode 100644 index 0000000..e7baefb --- /dev/null +++ b/dmake/unix/sysvr3/config.h @@ -0,0 +1,61 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/unix/sysvr3/config.h,v 1.1 1992/01/24 03:28:30 dvadura 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@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. +-- +-- LOG +-- $Log: config.h,v $ + * Revision 1.1 1992/01/24 03:28:30 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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 + +/* Define the getcwd function that is used in the code, since BSD does + * not have getcwd, but call it getwd instead. */ +extern char *getcwd ANSI((char *, int)); + +#ifndef M_XENIX +/* Define setvbuf, SysV doesn't have one */ +#define setvbuf(fp, bp, type, len) setbuf( fp, NULL ); +#define tzset() +#endif + +#ifdef M_XENIX +#define ASCARCH 0 /* Use binary archive headers if Xenix */ +#endif + +/* We don't care about CONST */ +#define CONST + +/* some braindead compilers don't understand pointers to void. */ +#define PVOID char * diff --git a/dmake/unix/sysvr3/config.mk b/dmake/unix/sysvr3/config.mk new file mode 100644 index 0000000..75bcf3c --- /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/make.sh b/dmake/unix/sysvr3/make.sh new file mode 100644 index 0000000..1de97d5 --- /dev/null +++ b/dmake/unix/sysvr3/make.sh @@ -0,0 +1,60 @@ +mkdir objects +cc -c -I. -Iunix -Iunix/sysvr3 -O infer.c +mv infer.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O make.c +mv make.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O stat.c +mv stat.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O expand.c +mv expand.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O dmstring.c +mv dmstring.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O hash.c +mv hash.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O dag.c +mv dag.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O dmake.c +mv dmake.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O path.c +mv path.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O imacs.c +mv imacs.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O sysintf.c +mv sysintf.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O parse.c +mv parse.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O getinp.c +mv getinp.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O quit.c +mv quit.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O state.c +mv state.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O basename.c +mv basename.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O dmdump.c +mv dmdump.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O macparse.c +mv macparse.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O rulparse.c +mv rulparse.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O percent.c +mv percent.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O function.c +mv function.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O unix/arlib.c +mv arlib.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O unix/dirbrk.c +mv dirbrk.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O unix/rmprq.c +mv rmprq.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O unix/ruletab.c +mv ruletab.o objects +cc -c -I. -Iunix -Iunix/sysvr3 -O unix/runargv.c +mv runargv.o objects +cc -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/basename.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 +cp unix/sysvr3/startup.mk startup.mk diff --git a/dmake/unix/sysvr3/public.h b/dmake/unix/sysvr3/public.h new file mode 100644 index 0000000..796aa7a --- /dev/null +++ b/dmake/unix/sysvr3/public.h @@ -0,0 +1,149 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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(()); + +#endif diff --git a/dmake/unix/sysvr3/pwd/config.mk b/dmake/unix/sysvr3/pwd/config.mk new file mode 100644 index 0000000..86c535a --- /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 0000000..5467b1d --- /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 + 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 +#include + +#ifdef M_XENIX +# include +# define dirent direct +#else +# include +#endif + +#include +#include + +typedef char *pointer; /* (void *) if you have it */ + +extern void free(); +extern pointer malloc(); +extern int fstat(), stat(); + +extern int errno; /* normally done by */ + +#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 0000000..721fae4 --- /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 basename.c +mv basename.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/sysvr3/pwd/getcwd.c +mv getcwd.o objects +cc -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/basename.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/getcwd.o +cp unix/sysvr3/pwd/startup.mk startup.mk diff --git a/dmake/unix/sysvr3/pwd/public.h b/dmake/unix/sysvr3/pwd/public.h new file mode 100644 index 0000000..796aa7a --- /dev/null +++ b/dmake/unix/sysvr3/pwd/public.h @@ -0,0 +1,149 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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(()); + +#endif diff --git a/dmake/unix/sysvr3/pwd/startup.mk b/dmake/unix/sysvr3/pwd/startup.mk new file mode 100644 index 0000000..44f4e19 --- /dev/null +++ b/dmake/unix/sysvr3/pwd/startup.mk @@ -0,0 +1,136 @@ +# Generic UNIX DMAKE startup file. Customize to suit your needs. +# Should work for both SYSV, and BSD 4.3 +# 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 # yes => SCCS is installed. + +# Applicable suffix definitions +A := .a # Libraries +E := # Executables +F := .f # Fortran +O := .o # Objects +P := .p # Pascal +S := .s # Assembler sources +V := ,v # RCS suffix + +# Recipe execution configurations +SHELL := /bin/sh +SHELLFLAGS := -ce +GROUPSHELL := $(SHELL) +GROUPFLAGS := +SHELLMETAS := |();&<>?*][$$:\\#`'" +GROUPSUFFIX := +DIVFILE = $(TMPFILE) + +# Standard C-language command names and flags + CPP := /lib/cpp # C-preprocessor + CC := cc # C-compiler and flags + CFLAGS += + + AS := as # Assembler and flags + ASFLAGS += + + LD = $(CC) # Loader and flags + LDFLAGS += + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(MFLAGS) + +# Definition of Print command for this system. + PRINT = lpr + +# Language and Parser generation Tools and their flags + YACC := yacc # standard yacc + YFLAGS += + YTAB := y.tab # yacc output files name stem. + + LEX := lex # standard lex + LFLAGS += + LEXYY := lex.yy # lex output file + +# Other Compilers, Tools and their flags + PC := pc # pascal compiler + RC := f77 # ratfor compiler + FC := f77 # fortran compiler + + CO := co # check out for RCS + COFLAGS += -q + + AR := ar # archiver + ARFLAGS+= ruv + + RM := /bin/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 : %$P ; $(PC) $(PFLAGS) -c $< + %$O : %$S ; $(AS) $(ASFLAGS) $< + %$O : %.cl ; class -c $< + %$O : %.e %.r %.F %$F + $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $< + +# Executables + %$E : %$O ; $(LD) $(LDFLAGS) -o $@ $< $(LDLIBS) + +# lex and yacc rules + %.c : %.y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@ + %.c : %.l ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@ + +# This rule tells how to make *.out from it's immediate list of prerequisites +# UNIX only. + %.out :; $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +# RCS support +.IF $(_HAVE_RCS) + % : %$V $$(@:d)RCS/$$(@:f)$V;- $(CO) $(COFLAGS) $@ + .NOINFER : %$V $$(@:d)RCS/$$(@:f)$V +.END + +# SCCS support +.IF $(_HAVE_SCCS) + % : s.% ; get $< + .NOINFER : s.% +.END + +# Recipe to make archive files. +%$A : +[ + $(AR) $(ARFLAGS) $@ $? + $(RM) $(RMFLAGS) $? + ranlib $@ +] + +# 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) + RCS is installed. +_HAVE_SCCS := yes # yes => SCCS is installed. + +# Applicable suffix definitions +A := .a # Libraries +E := # Executables +F := .f # Fortran +O := .o # Objects +P := .p # Pascal +S := .s # Assembler sources +V := ,v # RCS suffix + +# Recipe execution configurations +SHELL := /bin/sh +SHELLFLAGS := -ce +GROUPSHELL := $(SHELL) +GROUPFLAGS := +SHELLMETAS := |();&<>?*][$$:\\#`'" +GROUPSUFFIX := + +# Standard C-language command names and flags + CPP := /lib/cpp # C-preprocessor + CC := cc # C-compiler and flags + CFLAGS = + + AS := as # Assembler and flags + ASFLAGS = + + LD = $(CC) # Loader and flags + LDFLAGS = + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(MFLAGS) + +# Definition of Print command for this system. + PRINT = lp + +# Language and Parser generation Tools and their flags + YACC := yacc # standard yacc + YFLAGS = + YTAB := y.tab # yacc output files name stem. + + LEX := lex # standard lex + LFLAGS = + LEXYY := lex.yy # lex output file + +# Other Compilers, Tools and their flags + PC := pc # pascal compiler + RC := f77 # ratfor compiler + FC := f77 # fortran compiler + + CO := co # check out for RCS + COFLAGS := -q + + AR := ar # archiver + ARFLAGS = -rv + + RM := /bin/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 : %$P ; $(PC) $(PFLAGS) -c $< + %$O : %$S ; $(AS) $(ASFLAGS) -o $@ $< + %$O : %.cl ; class -c $< + %$O : %.e %.r %.f %.F %$F + $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $< + +# Executables + %$E : %$O ; $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS) + %$E : %.sh; cp $< $@; chmod 0777 $@ + +# lex and yacc rules + %.c : %.y %.Y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@ + %.c : %.l %.L ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@ + +# This rule tells how to make *.out from it's immediate list of prerequisites +# UNIX only. + %.out :; $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +# RCS support +.IF $(_HAVE_RCS) + % : %$V $$(@:d)RCS/$$(@:f)$V;- $(CO) $(COFLAGS) $@ + .NOINFER : %$V $$(@:d)RCS/$$(@:f)$V +.END + +# SCCS support +.IF $(_HAVE_SCCS) + GET = get + GFLAGS = + % : s.% ; $(GET) $(GFLAGS) $< + .NOINFER : s.% +.END + +# Recipe to make archive files. +%$A : +[ + $(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) + +#define NAME_MAX pathconf(name,_PC_NAME_MAX) +#endif + +extern int errno; + +#ifndef EIO +# include +#endif + +#endif /* _STDLIB_INCLUDED_ */ diff --git a/dmake/unix/sysvr3/time.h b/dmake/unix/sysvr3/time.h new file mode 100644 index 0000000..b9fb543 --- /dev/null +++ b/dmake/unix/sysvr3/time.h @@ -0,0 +1,10 @@ +/* +** 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/sysvr4/config.h b/dmake/unix/sysvr4/config.h new file mode 100644 index 0000000..b11ca9f --- /dev/null +++ b/dmake/unix/sysvr4/config.h @@ -0,0 +1,55 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/unix/sysvr4/config.h,v 1.1 1992/01/24 03:28:35 dvadura 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@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. +-- +-- LOG +-- $Log: config.h,v $ + * Revision 1.1 1992/01/24 03:28:35 dvadura + * dmake Version 3.8, Initial revision + * +*/ +#define _TYPES_ + +/* 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 + +/* Define the getcwd function that is used in the code, since BSD does + * not have getcwd, but call it getwd instead. */ +extern char *getcwd ANSI((char *, int)); + +/* Define setvbuf, SysV doesn't have one */ +#define setvbuf(fp, bp, type, len) setbuf( fp, NULL ); + +/* We don't care about CONST */ +#define CONST + +/* a small problem with pointer to voids on some unix machines needs this */ +#define PVOID void * diff --git a/dmake/unix/sysvr4/config.mk b/dmake/unix/sysvr4/config.mk new file mode 100644 index 0000000..6443ff6 --- /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 0000000..c3995bd --- /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 basename.c +mv basename.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 -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/basename.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 +cp unix/sysvr4/startup.mk startup.mk diff --git a/dmake/unix/sysvr4/public.h b/dmake/unix/sysvr4/public.h new file mode 100644 index 0000000..796aa7a --- /dev/null +++ b/dmake/unix/sysvr4/public.h @@ -0,0 +1,149 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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(()); + +#endif diff --git a/dmake/unix/sysvr4/startup.mk b/dmake/unix/sysvr4/startup.mk new file mode 100644 index 0000000..68a74e2 --- /dev/null +++ b/dmake/unix/sysvr4/startup.mk @@ -0,0 +1,137 @@ +# Generic UNIX DMAKE startup file. Customize to suit your needs. +# Should work for both SYSV, and BSD 4.3 +# 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 => RCS is installed. +_HAVE_SCCS := yes # yes => SCCS is installed. + +# Applicable suffix definitions +A := .a # Libraries +E := # Executables +F := .f # Fortran +O := .o # Objects +P := .p # Pascal +S := .s # Assembler sources +V := ,v # RCS suffix + +# Recipe execution configurations +SHELL := /bin/sh +SHELLFLAGS := -ce +GROUPSHELL := $(SHELL) +GROUPFLAGS := +SHELLMETAS := |();&<>?*][$$:\\#`'" +GROUPSUFFIX := + +# Standard C-language command names and flags + CPP := /lib/cpp # C-preprocessor + CC := cc # C-compiler and flags + CFLAGS = + + AS := as # Assembler and flags + ASFLAGS = + + LD = $(CC) # Loader and flags + LDFLAGS = + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(MFLAGS) + +# Definition of Print command for this system. + PRINT = lp + +# Language and Parser generation Tools and their flags + YACC := yacc # standard yacc + YFLAGS = + YTAB := y.tab # yacc output files name stem. + + LEX := lex # standard lex + LFLAGS = + LEXYY := lex.yy # lex output file + +# Other Compilers, Tools and their flags + PC := pc # pascal compiler + RC := f77 # ratfor compiler + FC := f77 # fortran compiler + + CO := co # check out for RCS + COFLAGS := -q + + AR := ar # archiver + ARFLAGS = -rv + + RM := /bin/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 : %$P ; $(PC) $(PFLAGS) -c $< + %$O : %$S ; $(AS) $(ASFLAGS) -o $@ $< + %$O : %.cl ; class -c $< + %$O : %.e %.r %.f %.F %$F + $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $< + +# Executables + %$E : %$O ; $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS) + %$E : %.sh; cp $< $@; chmod 0777 $@ + +# lex and yacc rules + %.c : %.y %.Y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@ + %.c : %.l %.L ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@ + +# This rule tells how to make *.out from it's immediate list of prerequisites +# UNIX only. + %.out :; $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +# RCS support +.IF $(_HAVE_RCS) + % : %$V $$(@:d)RCS/$$(@:f)$V;- $(CO) $(COFLAGS) $@ + .NOINFER : %$V $$(@:d)RCS/$$(@:f)$V +.END + +# SCCS support +.IF $(_HAVE_SCCS) + GET = get + GFLAGS = + % : s.% ; $(GET) $(GFLAGS) $< + .NOINFER : s.% +.END + +# Recipe to make archive files. +%$A : +[ + $(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) + 4 ? ((int)list + 2*8 - 1) & -8 \ + : ((int)list + 2*4 - 1) & -4)))[-1] +#else +# define va_arg(list,mode) ((mode *)(list += sizeof(mode)))[-1] +#endif +#endif + diff --git a/dmake/unix/xenix/config.h b/dmake/unix/xenix/config.h new file mode 100644 index 0000000..89a8bfe --- /dev/null +++ b/dmake/unix/xenix/config.h @@ -0,0 +1,60 @@ +/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/unix/xenix/config.h,v 1.1 1992/01/24 03:28:45 dvadura 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@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. +-- +-- LOG +-- $Log: config.h,v $ + * Revision 1.1 1992/01/24 03:28:45 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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 + +/* Define the getcwd function that is used in the code, since BSD does + * not have getcwd, but call it getwd instead. */ +extern char *getcwd ANSI((char *, int)); + +#ifndef M_XENIX +/* Define setvbuf, SysV doesn't have one */ +#define setvbuf(fp, bp, type, len) setbuf( fp, NULL ); +#endif + +#ifdef M_XENIX +#define ASCARCH 0 /* Use binary archive headers if Xenix */ +#endif + +/* We don't care about CONST */ +#define CONST + +/* a small problem with pointer to voids on some unix machines needs this */ +#define PVOID void * diff --git a/dmake/unix/xenix/config.mk b/dmake/unix/xenix/config.mk new file mode 100644 index 0000000..a4f8f78 --- /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 0000000..6c6994d --- /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 basename.c +mv basename.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 -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/basename.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 +cp unix/xenix/startup.mk startup.mk diff --git a/dmake/unix/xenix/public.h b/dmake/unix/xenix/public.h new file mode 100644 index 0000000..796aa7a --- /dev/null +++ b/dmake/unix/xenix/public.h @@ -0,0 +1,149 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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(()); + +#endif diff --git a/dmake/unix/xenix/pwd/config.mk b/dmake/unix/xenix/pwd/config.mk new file mode 100644 index 0000000..095ff35 --- /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 0000000..5467b1d --- /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 + 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 +#include + +#ifdef M_XENIX +# include +# define dirent direct +#else +# include +#endif + +#include +#include + +typedef char *pointer; /* (void *) if you have it */ + +extern void free(); +extern pointer malloc(); +extern int fstat(), stat(); + +extern int errno; /* normally done by */ + +#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 0000000..f298bdf --- /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 basename.c +mv basename.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/xenix/pwd/getcwd.c +mv getcwd.o objects +cc -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/basename.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/getcwd.o -lx +cp unix/xenix/pwd/startup.mk startup.mk diff --git a/dmake/unix/xenix/pwd/public.h b/dmake/unix/xenix/pwd/public.h new file mode 100644 index 0000000..796aa7a --- /dev/null +++ b/dmake/unix/xenix/pwd/public.h @@ -0,0 +1,149 @@ +/* RCS -- $Header$ +-- 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@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. +-- +-- LOG +-- $Log$ +*/ + +#ifndef _DMAKE_PUBLIC_h +#define _DMAKE_PUBLIC_h + +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)); +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 * _strjoin ANSI((char *, char *, int, int)); +char * _stradd ANSI((char *, char *, int)); +char * _strapp ANSI((char *, char *)); +char * _strdup ANSI((char *)); +char * _strdup2 ANSI((char *)); +char * _strpbrk ANSI((char *, char *)); +char * _strspn ANSI((char *, char *)); +char * _strstr ANSI((char *, char *)); +char * _substr ANSI((char *, char *)); +uint16 Hash ANSI((char *, uint32 *)); +HASHPTR Get_name ANSI((char *, HASHPTR *, int)); +HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *)); +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(()); +void No_ram ANSI(()); +int Usage ANSI((int)); +int Version ANSI(()); +char * Get_suffix 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 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)); +char* basename ANSI((char *)); +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(()); + +#endif diff --git a/dmake/unix/xenix/pwd/startup.mk b/dmake/unix/xenix/pwd/startup.mk new file mode 100644 index 0000000..44f4e19 --- /dev/null +++ b/dmake/unix/xenix/pwd/startup.mk @@ -0,0 +1,136 @@ +# Generic UNIX DMAKE startup file. Customize to suit your needs. +# Should work for both SYSV, and BSD 4.3 +# 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 # yes => SCCS is installed. + +# Applicable suffix definitions +A := .a # Libraries +E := # Executables +F := .f # Fortran +O := .o # Objects +P := .p # Pascal +S := .s # Assembler sources +V := ,v # RCS suffix + +# Recipe execution configurations +SHELL := /bin/sh +SHELLFLAGS := -ce +GROUPSHELL := $(SHELL) +GROUPFLAGS := +SHELLMETAS := |();&<>?*][$$:\\#`'" +GROUPSUFFIX := +DIVFILE = $(TMPFILE) + +# Standard C-language command names and flags + CPP := /lib/cpp # C-preprocessor + CC := cc # C-compiler and flags + CFLAGS += + + AS := as # Assembler and flags + ASFLAGS += + + LD = $(CC) # Loader and flags + LDFLAGS += + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(MFLAGS) + +# Definition of Print command for this system. + PRINT = lpr + +# Language and Parser generation Tools and their flags + YACC := yacc # standard yacc + YFLAGS += + YTAB := y.tab # yacc output files name stem. + + LEX := lex # standard lex + LFLAGS += + LEXYY := lex.yy # lex output file + +# Other Compilers, Tools and their flags + PC := pc # pascal compiler + RC := f77 # ratfor compiler + FC := f77 # fortran compiler + + CO := co # check out for RCS + COFLAGS += -q + + AR := ar # archiver + ARFLAGS+= ruv + + RM := /bin/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 : %$P ; $(PC) $(PFLAGS) -c $< + %$O : %$S ; $(AS) $(ASFLAGS) $< + %$O : %.cl ; class -c $< + %$O : %.e %.r %.F %$F + $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $< + +# Executables + %$E : %$O ; $(LD) $(LDFLAGS) -o $@ $< $(LDLIBS) + +# lex and yacc rules + %.c : %.y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@ + %.c : %.l ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@ + +# This rule tells how to make *.out from it's immediate list of prerequisites +# UNIX only. + %.out :; $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +# RCS support +.IF $(_HAVE_RCS) + % : %$V $$(@:d)RCS/$$(@:f)$V;- $(CO) $(COFLAGS) $@ + .NOINFER : %$V $$(@:d)RCS/$$(@:f)$V +.END + +# SCCS support +.IF $(_HAVE_SCCS) + % : s.% ; get $< + .NOINFER : s.% +.END + +# Recipe to make archive files. +%$A : +[ + $(AR) $(ARFLAGS) $@ $? + $(RM) $(RMFLAGS) $? + ranlib $@ +] + +# 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) + RCS is installed. +_HAVE_SCCS := yes # yes => SCCS is installed. + +# Applicable suffix definitions +A := .a # Libraries +E := # Executables +F := .f # Fortran +O := .o # Objects +P := .p # Pascal +S := .s # Assembler sources +V := ,v # RCS suffix + +# Recipe execution configurations +SHELL := /bin/sh +SHELLFLAGS := -ce +GROUPSHELL := $(SHELL) +GROUPFLAGS := +SHELLMETAS := |();&<>?*][$$:\\#`'" +GROUPSUFFIX := + +# Standard C-language command names and flags + CPP := /lib/cpp # C-preprocessor + CC := cc # C-compiler and flags + CFLAGS = + + AS := as # Assembler and flags + ASFLAGS = + + LD = $(CC) # Loader and flags + LDFLAGS = + LDLIBS = + +# Definition of $(MAKE) macro for recursive makes. + MAKE = $(MAKECMD) $(MFLAGS) + +# Definition of Print command for this system. + PRINT = lp + +# Language and Parser generation Tools and their flags + YACC := yacc # standard yacc + YFLAGS = + YTAB := y.tab # yacc output files name stem. + + LEX := lex # standard lex + LFLAGS = + LEXYY := lex.yy # lex output file + +# Other Compilers, Tools and their flags + PC := pc # pascal compiler + RC := f77 # ratfor compiler + FC := f77 # fortran compiler + + CO := co # check out for RCS + COFLAGS := -q + + AR := ar # archiver + ARFLAGS = -rv + + RM := /bin/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 : %$P ; $(PC) $(PFLAGS) -c $< + %$O : %$S ; $(AS) $(ASFLAGS) -o $@ $< + %$O : %.cl ; class -c $< + %$O : %.e %.r %.f %.F %$F + $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $< + +# Executables + %$E : %$O ; $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS) + %$E : %.sh; cp $< $@; chmod 0777 $@ + +# lex and yacc rules + %.c : %.y %.Y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@ + %.c : %.l %.L ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@ + +# This rule tells how to make *.out from it's immediate list of prerequisites +# UNIX only. + %.out :; $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +# RCS support +.IF $(_HAVE_RCS) + % : %$V $$(@:d)RCS/$$(@:f)$V;- $(CO) $(COFLAGS) $@ + .NOINFER : %$V $$(@:d)RCS/$$(@:f)$V +.END + +# SCCS support +.IF $(_HAVE_SCCS) + GET = get + GFLAGS = + % : s.% ; $(GET) $(GFLAGS) $< + .NOINFER : s.% +.END + +# Recipe to make archive files. +%$A : +[ + $(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) + +#endif + +#endif /* _STDLIB_INCLUDED_ */ diff --git a/dmake/unix/xenix/time.h b/dmake/unix/xenix/time.h new file mode 100644 index 0000000..b9fb543 --- /dev/null +++ b/dmake/unix/xenix/time.h @@ -0,0 +1,10 @@ +/* +** 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/version.h b/dmake/version.h new file mode 100644 index 0000000..b8aab3b --- /dev/null +++ b/dmake/version.h @@ -0,0 +1,3 @@ +/* dmake version number. */ + +#define VERSION "3.80" diff --git a/dmake/vextern.h b/dmake/vextern.h new file mode 100644 index 0000000..4909782 --- /dev/null +++ b/dmake/vextern.h @@ -0,0 +1,113 @@ +/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/vextern.h,v 1.2 1992/04/07 04:42:46 dvadura 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@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. +-- +-- LOG +-- $Log: vextern.h,v $ + * Revision 1.2 1992/04/07 04:42:46 dvadura + * Added the No_exec variable for -X flag. + * + * Revision 1.1 1992/01/24 03:27:19 dvadura + * dmake Version 3.8, Initial revision + * +*/ + +/* 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* Prep; /* Value of macro PREP */ +EXTERN char* Makedir; /* pointer to macro value for MAKEDIR */ +EXTERN char* Start_dir; /* cell for macro value for .SETDIR */ +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 int Target; /* TRUE if target found in makefile */ +EXTERN int If_expand; /* TRUE if calling Expand from getinp.c */ +EXTERN int If_multi; /* M_MULTI for expand of single MULTI macs*/ +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 Def_targets; /* TRUE if defining targets */ + +EXTERN CELLPTR Root; /* Root of the make graph */ + +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 Macs[HASH_TABLE_SIZE]; /* hash table for macro defs */ +EXTERN HASHPTR Defs[HASH_TABLE_SIZE]; /* hash table for other defs */ + +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/rmroot/rmroot.1 b/rmroot/rmroot.1 new file mode 100644 index 0000000..b4cafba --- /dev/null +++ b/rmroot/rmroot.1 @@ -0,0 +1,48 @@ +.TH RMROOT 1 "Commands and Applications" "17 April 1994" "Version 1.0" +.SH NAME +rmroot - remove the corresponding .root file for .a or .o files. +.SH SYNOPSIS +.B rmroot +.I file1 +[ \fIfile2\fR ... ] +.SH DESCRIPTION +.B rmroot +takes as arguments file names ending in +.B .o +or +.B .a +and deletes the corresponding +.B .root +file. +.LP +If invoked with no arguments, or invoked with file names not ending in either +.B .o +or +.BR .a ", " rmroot +will do nothing. Where file names are mixed, +.B rmroot +will act only upon those with the proper suffixes. +.SH EXAMPLES +.B "rmroot file1.a file2.o" +will delete +.BR file1.root " and " file2.root . +.LP +.B "rmroot file3 file4.o file5.1" +will delete +.BR file4.root . +.LP +.B "rmroot" +will delete nothing. +.SH HISTORY +.B rmroot +first appeared with +.B dmake +Apple IIgs version 1.0 as a method of deleting intermediate targets produced +while building on an inference. +.SH SEE ALSO +.BR dmake (1) +.SH AUTHOR +.nf +Devin Reade glyn@cs.ualberta.ca + gdr@myrias.ab.ca +.fi diff --git a/rmroot/rmroot.c b/rmroot/rmroot.c new file mode 100644 index 0000000..ff149c4 --- /dev/null +++ b/rmroot/rmroot.c @@ -0,0 +1,40 @@ +#ifdef __CCFRONT__ +#include <14:pragma.h> +#endif + +#include +#include + +char buffer[256]; + +int main (int argc, char **argv) { + + int i; + size_t length; + char *p; + + for (i = 1; i