├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── bin └── .gitignore ├── container ├── Dockerfile ├── README.md ├── docker-compose.yml.example ├── server ├── server.dgd.example └── update ├── doc ├── builtin.md ├── compiling.md ├── extensions.md └── old │ ├── Changelog │ ├── Commercial │ └── Credits ├── mud.dgd └── src ├── Makefile ├── alloc.cpp ├── alloc.h ├── array.cpp ├── array.h ├── asn.h ├── call_out.cpp ├── call_out.h ├── comm.cpp ├── comm.h ├── comp ├── Makefile ├── codegen.cpp ├── codegen.h ├── comp.h ├── compile.cpp ├── compile.h ├── control.cpp ├── control.h ├── node.cpp ├── node.h ├── optimize.cpp ├── optimize.h └── parser.y ├── config.cpp ├── config.h ├── data.cpp ├── data.h ├── dgd.cpp ├── dgd.h ├── ed ├── Makefile ├── buffer.cpp ├── buffer.h ├── cmdsub.cpp ├── ed.cpp ├── ed.h ├── edcmd.cpp ├── edcmd.h ├── fileio.cpp ├── fileio.h ├── line.cpp ├── line.h ├── regexp.cpp ├── regexp.h ├── vars.cpp └── vars.h ├── editor.cpp ├── editor.h ├── error.cpp ├── error.h ├── ext.cpp ├── ext.h ├── hash.cpp ├── hash.h ├── host.h ├── host ├── Makefile ├── asn.cpp ├── crypt.cpp ├── hostfloat.cpp ├── simfloat.cpp ├── telnet.h ├── unix │ ├── connect.cpp │ ├── direct.cpp │ ├── dirent.cpp │ ├── dload.cpp │ ├── local.cpp │ ├── lrand48.cpp │ ├── random.cpp │ └── time.cpp └── win32 │ ├── README.md │ ├── connect.cpp │ ├── dgd.sln │ ├── dgd.vcxproj │ ├── dgd.vcxproj.filters │ ├── dload.cpp │ ├── dosfile.cpp │ ├── local.cpp │ ├── time.cpp │ └── windgd.cpp ├── interpret.cpp ├── interpret.h ├── kfun ├── Makefile ├── builtin.cpp ├── extra.cpp ├── file.cpp ├── kfun.h ├── math.cpp ├── std.cpp ├── table.cpp └── table.h ├── lex ├── Makefile ├── lex.cpp ├── lex.h ├── macro.cpp ├── macro.h ├── ppcontrol.cpp ├── ppcontrol.h ├── ppstr.cpp ├── ppstr.h ├── special.cpp ├── special.h ├── token.cpp └── token.h ├── object.cpp ├── object.h ├── parser ├── Makefile ├── dfa.cpp ├── dfa.h ├── grammar.cpp ├── grammar.h ├── parse.cpp ├── parse.h ├── srp.cpp └── srp.h ├── path.cpp ├── path.h ├── str.cpp ├── str.h ├── swap.cpp ├── swap.h ├── version.h └── xfloat.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | .vs 3 | bin/dgd 4 | bin/dgd.old 5 | src/a.out 6 | src/*/dgd 7 | src/comp/parser.cpp 8 | src/comp/parser.h 9 | src/lex/lex 10 | src/ed/ed 11 | src/host/local.cpp 12 | src/host/random.cpp 13 | src/host/lrand48.cpp 14 | src/host/dirent.cpp 15 | src/host/dload.cpp 16 | src/host/time.cpp 17 | src/host/connect.cpp 18 | src/host/xfloat.cpp 19 | src/host/win32/Debug 20 | src/host/win32/Release 21 | src/host/win32/x64 22 | src/host/win32/ipch 23 | src/host/win32/dgd.opensdf 24 | src/host/win32/dgd.sdf 25 | src/host/win32/dgd.suo 26 | src/host/win32/dgd.v11.suo 27 | src/host/win32/dgd.vcxproj.user 28 | src/host/win32/dgd.VC.db 29 | src/host/win32/dgd.VC.VC.opendb 30 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lpc-doc"] 2 | path = lpc-doc 3 | url = https://github.com/dworkin/lpc-doc.git 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DGD 2 | 3 | This file was written for release 1.7 of DGD, Dworkin's Game Driver. 4 | 5 | DGD is a rewrite from scratch of the LPMud server. It runs on Windows, MacOS 6 | and many versions of Unix. 7 | 8 | [DGD source repository](https://github.com/dworkin/dgd) 9 | 10 | [DGD's home page](https://www.dworkin.nl/dgd) 11 | 12 | DGD offers JIT compilation support. This requires the 13 | [JIT extension module](https://github.com/dworkin/lpc-ext). 14 | 15 | Alongside DGD, there is Hydra. Hydra is fully compatible with DGD, but offers 16 | acceleration for multi-core systems. Hydra also supports JIT compilation, 17 | using the same extension module as DGD. 18 | 19 | [Hydra's home page](https://www.dworkin.nl/hydra-tech) 20 | 21 | ### PLEASE NOTE 22 | 23 | DGD 1.7 is backward compatible with snapshots from DGD 1.5.9 and later, only. 24 | To upgrade to DGD 1.7, first upgrade to the latest 1.5.x version, recompile 25 | all objects, and create a non-incremental snapshot. 26 | 27 | 28 | This distribution is organized as follows: 29 | 30 | - bin 31 | Installation binaries will be created here (Unix). 32 | - container 33 | Example files for running DGD in a container. 34 | - doc 35 | Documentation on how to compile and run DGD. 36 | - lpc-doc 37 | LPC documentation, still very incomplete. 38 | - src 39 | Where the source code of DGD resides, and where you issue your `make` 40 | command on Unix. 41 | - src/host 42 | Subdirectories for various platform-dependent files. 43 | -------------------------------------------------------------------------------- /bin/.gitignore: -------------------------------------------------------------------------------- 1 | dgd 2 | dgd.old 3 | -------------------------------------------------------------------------------- /container/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.13 2 | ARG USER=1000 3 | 4 | RUN apk add g++ clang byacc make git zlib-dev openssl-dev 5 | RUN adduser -u $USER -H -D dgd 6 | 7 | WORKDIR /container 8 | 9 | ADD server update /container/ 10 | 11 | RUN git config --global pull.rebase false 12 | RUN git clone -b release https://github.com/dworkin/dgd.git 13 | RUN git clone -b release https://github.com/dworkin/lpc-ext.git 14 | RUN mkdir cache 15 | RUN chown dgd:dgd cache 16 | RUN ln -s lpc-ext/src/jit/jitcomp 17 | 18 | ENTRYPOINT [ "/container/server", "/container/config" ] 19 | -------------------------------------------------------------------------------- /container/README.md: -------------------------------------------------------------------------------- 1 | The files in this directory can be used to run DGD inside a docker 2 | container, which will contain the DGD binary and JIT object cache, but not 3 | the LPC source tree or the snapshot files. 4 | 5 | In contrast to the typical container setup, which depends on static images 6 | that have to be replaced to keep up with new releases and the disclosure 7 | of vulnerabilities, necessitating a restart of the container, this 8 | configuration is persistent and all components (including the base 9 | system) can be updated without restarting, and without service interruption 10 | even for connected clients. 11 | 12 | DGD is configured to be hotbooted into a new version after an update. The 13 | JIT compiler extension, gzip extension and crypto extension are included 14 | in the container. 15 | 16 | The container expects the following to be present in the current directory 17 | when started: 18 | 19 | - server.dgd 20 | a configuration file for DGD (see server.dgd.example) 21 | - src 22 | the LPC source tree 23 | - state 24 | where snapshots are stored 25 | 26 | First, modify `Dockerfile` and set the `USER` argument to the ID of the user 27 | who owns the source tree. Then, copy your DGD config file to `server.dgd`; 28 | lines marked with `PLACEHOLDER` in `server.dgd.example` will be replaced by 29 | the container with appropriate container-relative values. 30 | 31 | Then, copy `docker-compose.yml.example` to `docker-compose.yml` and change 32 | the ports to match those in the configuration file. 33 | 34 | Build and start the container with `docker-compose up`. Update the 35 | running container with `docker exec /container/update`. 36 | -------------------------------------------------------------------------------- /container/docker-compose.yml.example: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | dgd-server: 4 | build: . 5 | volumes: 6 | - ./server.dgd:/container/server.dgd:ro 7 | - ./src:/container/src 8 | - ./state:/container/state 9 | ports: 10 | - "8023:8023/tcp" 11 | - "8080:8080/tcp" 12 | -------------------------------------------------------------------------------- /container/server: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | /container/update 4 | 5 | snapshot=/container/state/snapshot 6 | snapshot2=/container/state/snapshot.old 7 | if [ \! -f $snapshot ] 8 | then 9 | snapshot= 10 | fi 11 | if [ \! -f $snapshot2 ] 12 | then 13 | snapshot2= 14 | fi 15 | 16 | ulimit -c 0 17 | exec su dgd -c "/container/dgd/bin/dgd $* $snapshot $snapshot2" # 2> /container/src/log/runtime 18 | -------------------------------------------------------------------------------- /container/server.dgd.example: -------------------------------------------------------------------------------- 1 | telnet_port = 8023; /* telnet port number */ 2 | binary_port = 8080; /* binary port number */ 3 | directory = PLACEHOLDER; /* base directory */ 4 | ed_tmpfile = PLACEHOLDER; /* proto editor tmpfile */ 5 | swap_file = PLACEHOLDER; /* swap file */ 6 | swap_size = 65535; /* # sectors in swap file */ 7 | sector_size = 1024; /* swap sector size */ 8 | swap_fragment = 256; /* fragment to swap out */ 9 | static_chunk = 64512; /* static memory chunk */ 10 | dynamic_chunk = 261120; /* dynamic memory chunk */ 11 | dump_file = PLACEHOLDER; /* snapshot file */ 12 | dump_interval = 3600; /* snapshot rebuild interval */ 13 | hotboot = PLACEHOLDER; 14 | modules = PLACEHOLDER; 15 | typechecking = 2; /* global typechecking */ 16 | include_file = "/include/std.h"; /* standard include file */ 17 | include_dirs = ({ "/include", "~/include", "~/api/include" }); 18 | /* include directories to search */ 19 | auto_object = "/kernel/lib/auto"; /* automatically inherited object */ 20 | driver_object = "/kernel/sys/driver"; /* driver object */ 21 | create = "_F_create"; /* low-level create function */ 22 | 23 | users = 255; /* max # of users */ 24 | editors = 10; /* max # of editor sessions */ 25 | objects = 10000; /* max # of objects */ 26 | call_outs = 10000; /* max # of call_outs */ 27 | array_size = 32767; /* max array size */ 28 | -------------------------------------------------------------------------------- /container/update: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | DEFINES='-DUINDEX_TYPE="unsigned int" -DUINDEX_MAX=UINT_MAX \ 4 | -DEINDEX_TYPE="unsigned short" -DEINDEX_MAX=USHRT_MAX' 5 | DEBUG=-O2 6 | 7 | apk update 8 | apk upgrade 9 | 10 | git -C /container/dgd pull 11 | make -C /container/dgd/src DEFINES="$DEFINES" DEBUG="$DEBUG" install 12 | git -C /container/lpc-ext pull 13 | make -C /container/lpc-ext/src DEFINES="$DEFINES" DEBUG="$DEBUG" ZLIB=1.2.12 jit zlib crypto 14 | EXT=`grep ^EXT /container/lpc-ext/src/Makefile | sed s/EXT=//` 15 | 16 | sed < /container/server.dgd > /container/config \ 17 | -e 's!^directory.*$!directory = "/container/src";!' \ 18 | -e 's!^swap_file.*$!swap_file = "/container/state/swap";!' \ 19 | -e 's!^dump_file.*$!dump_file = "/container/state/snapshot";!' \ 20 | -e 's!^ed_tmpfile.*$!ed_tmpfile = "/container/state/ed";!' \ 21 | -e 's!^hotboot.*$!hotboot = ({ "/container/dgd/bin/dgd", "/container/config", "/container/state/snapshot", "/container/state/snapshot.old" });!'\ 22 | -e 's!^modules.*$!modules = ([ "/container/lpc-ext/jit.'$EXT'" : "/container", "/container/lpc-ext/zlib.'$EXT'" : "", "/container/lpc-ext/crypto.'$EXT'" : "" ]);!' 23 | -------------------------------------------------------------------------------- /doc/builtin.md: -------------------------------------------------------------------------------- 1 | New types can be added using builtin light-weight objects. These types 2 | have a name that starts with "/builtin", like: "/builtin/type#-1" (this 3 | is configurable with the `BIPREFIX` define in `config.h`). 4 | 5 | To add a type, reserve a positive number for it in `object.h`, like 6 | ``` 7 | # define BUILTIN_TYPE 0 8 | ``` 9 | Then give it a name in `Object::builtinName()`: 10 | ``` 11 | const char *Object::builtinName(Int type) 12 | { 13 | switch (type) { 14 | case BUILTIN_TYPE: 15 | return BIPREFIX "type"; 16 | default: 17 | fatal("unknown builtin type %d", type); 18 | } 19 | } 20 | ``` 21 | A function to create a light-weight object of this type could look like this: 22 | ``` 23 | # ifdef FUNCDEF 24 | FUNCDEF("new_type", kf_new_type, pt_new_type, 0) 25 | # else 26 | char pt_new_type[] = { C_TYPECHECKED | C_STATIC, 0, 0, 0, 6, T_OBJECT }; 27 | 28 | /* 29 | * NAME: kfun->new_type() 30 | * DESCRIPTION: create a new type! 31 | */ 32 | int kf_new_type(Frame *f, int n, KFun *kf) 33 | { 34 | Array *a; 35 | Float flt; 36 | String *str; 37 | 38 | a = Array::create(f->data, 4); 39 | 40 | /* first element is the type as an integer */ 41 | PUT_INTVAL(&a->elts[0], BUILTIN_TYPE); 42 | /* second element must be Float 0.0 */ 43 | flt.high = 0; 44 | flt.low = 0; 45 | PUT_FLTVAL(&a->elts[1], flt); 46 | 47 | /* suggested third element: version number */ 48 | PUT_INTVAL(&a->elts[2], 0); 49 | /* fourth element: data */ 50 | str = String::create("some info", 9); 51 | PUT_STRVAL(&a->elts[3], str); 52 | 53 | /* push the return value on the stack */ 54 | PUSH_LWOVAL(f, a); 55 | return 0; 56 | } 57 | # endif 58 | ``` 59 | Ordinary light-weight objects will have an object as the first element of 60 | their array. For builtin types, the first element must be an integer, 61 | the type number; the second element is reserved and must be initialized 62 | to `Float` 0.0. 63 | 64 | For the third element, a version number for your type is suggested, in case 65 | you decide to change the way your type is build and want to convert old 66 | instances. The fourth and later elements can hold arbitrary LPC data. 67 | 68 | By default, builtin types have no functions callable from LPC, functions 69 | that can be probed with `function_object()`, or information about them that 70 | can be returned with `status()`. If you do want them to have any of that, 71 | edit the source code for the functions `Frame::call()`, `kf_function_object()`, 72 | `kf_status()` and `kf_statuso_idx()`. 73 | 74 | At compile time, a node of a builtin type should have modifier `T_CLASS`, and 75 | a class string built from the base name, as returned by `Object::builtinName()`. 76 | -------------------------------------------------------------------------------- /doc/compiling.md: -------------------------------------------------------------------------------- 1 | ## A few useful notes for compiling DGD 2 | 3 | DGD's build process is very simple, and doesn't have 4 | a configure script. Platforms are detected in 5 | `src/Makefile`. You will need a C++ compiler and yacc or 6 | a yacc-compatible parser generator. 7 | 8 | DGD can be compiled on Unix-like systems and on Windows. See 9 | `src/host/win32/README.md` for additional information regarding 10 | the Windows build. 11 | 12 | There are a few things you can enable/disable by adding the 13 | proper defines to the Makefile on Unix systems, or to your 14 | project on Visual Studio. 15 | 16 | - LARGENUM 17 | 64 bit integers and floats. 18 | - SLASHSLASH 19 | C++ style // comments in LPC code. 20 | - SIMFLOAT 21 | Simulated floats. Not a macro but a argument for `make`, `make SIMFLOAT=1`. 22 | - NOFLOAT 23 | Compile without using host floats (requires simulated floats). 24 | - CLOSURES 25 | Function pointers, implemented as a builtin type. See `doc/builtin.md` for 26 | information about adding builtin types. CLOSURES allows taking the 27 | address of a function with `&func()`, and calling the function that a 28 | function pointer refers to with `(*func)()`. When creating a pointer to 29 | a function, function arguments may be included: `&func("foo")`. More 30 | function arguments can be added when the function is called, or in 31 | constructing a new pointer: `&(*func)("bar")` 32 | -------------------------------------------------------------------------------- /doc/extensions.md: -------------------------------------------------------------------------------- 1 | A kfun module can be specified in the config file: 2 | ``` 3 | modules = ([ "kfun_module" : "module config" ]); 4 | ``` 5 | The kfun module must be an LPC extension, as specified 6 | [here](https://github.com/dworkin/lpc-ext). 7 | -------------------------------------------------------------------------------- /doc/old/Commercial: -------------------------------------------------------------------------------- 1 | From January 9, 1996 till March 29, 2001 the commercial rights to DGD were 2 | licensed exclusively to ichat, inc., which was later renamed to Acuity 3 | Corporation. 4 | 5 | As of March 29, 2001 DGD could again be licensed directly from BeeHive Internet 6 | Technologies. 7 | 8 | On August 6th, 2005, all rights to DGD were acquired by Dworkin B.V. in the 9 | Netherlands. BeeHive Internet Technologies, Inc. is still a license holder 10 | and value-added reseller of the software. 11 | 12 | On February 3rd, 2010, DGD 1.4 was released under the GNU Affero General Public 13 | License. 14 | -------------------------------------------------------------------------------- /doc/old/Credits: -------------------------------------------------------------------------------- 1 | DGD was written by Felix A. Croes (felix@dworkin.nl) 2 | 3 | DGD != LPmud, but without LPmud DGD could not have existed. My effusive 4 | thanks to Lars Pensjö for putting me on the right track. 5 | 6 | Many valuable suggestions were provided by Johan Andersson, Jacob Hallen 7 | and especially Pär Winzell, who convinced me that objects do not require 8 | builtin inventories or actions. 9 | 10 | Richard Braakman showed me in practise that using hashing for object symbol 11 | tables is very worthwhile. 12 | 13 | Many bugs were reported, and suggestions made by Thomas Bopp, Adam David, 14 | Erwin Harte, Kris Van Hees, Robert Leslie, Sampsa Ranta and Haijo Schipper. 15 | -------------------------------------------------------------------------------- /mud.dgd: -------------------------------------------------------------------------------- 1 | telnet_port = 6047; /* telnet port number */ 2 | binary_port = 6048; /* binary port number */ 3 | directory = "/home/dworkin/kernellib/src"; 4 | /* base directory */ 5 | users = 40; /* max # of users */ 6 | editors = 40; /* max # of editor sessions */ 7 | ed_tmpfile = "../state/ed"; /* proto editor tmpfile */ 8 | swap_file = "../state/swap"; /* swap file */ 9 | swap_size = 1024; /* # sectors in swap file */ 10 | sector_size = 512; /* swap sector size */ 11 | swap_fragment = 32; /* fragment to swap out */ 12 | static_chunk = 64512; /* static memory chunk */ 13 | dynamic_chunk = 261120; /* dynamic memory chunk */ 14 | dump_file = "../state/snapshot"; /* snapshot file */ 15 | dump_interval = 3600; /* snapshot interval in seconds */ 16 | 17 | typechecking = 2; /* highest level of typechecking */ 18 | include_file = "/include/std.h"; /* standard include file */ 19 | include_dirs = ({ "/include", "~/include" }); /* directories to search */ 20 | auto_object = "/kernel/lib/auto"; /* auto inherited object */ 21 | driver_object = "/kernel/sys/driver"; /* driver object */ 22 | create = "_F_create"; /* name of create function */ 23 | 24 | array_size = 1000; /* max array size */ 25 | objects = 500; /* max # of objects */ 26 | call_outs = 100; /* max # of call_outs */ 27 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of DGD, https://github.com/dworkin/dgd 3 | # Copyright (C) 1993-2010 Dworkin B.V. 4 | # Copyright (C) 2010-2025 DGD Authors (see the commit log for details) 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as 8 | # published by the Free Software Foundation, either version 3 of the 9 | # License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | # 19 | OS=$(shell uname -s) 20 | ifeq ($(OS),Darwin) 21 | HOST=DARWIN 22 | endif 23 | ifeq ($(OS),Linux) 24 | HOST=LINUX 25 | endif 26 | ifeq ($(OS),FreeBSD) 27 | HOST=FREEBSD 28 | endif 29 | ifeq ($(OS),NetBSD) 30 | HOST=FREEBSD 31 | endif 32 | ifeq ($(OS),OpenBSD) 33 | HOST=FREEBSD 34 | endif 35 | ifeq ($(OS),SunOS) 36 | HOST=SOLARIS 37 | endif 38 | ifndef HOST 39 | $(error HOST is undefined) 40 | endif 41 | 42 | DEFINES= # -DLARGENUM -DSLASHSLASH -DNOFLOAT -DCLOSURES 43 | DEBUG= -g -DDEBUG 44 | CCFLAGS=-D$(HOST) $(DEFINES) $(DEBUG) 45 | CXXFLAGS=-I. -Icomp -Ilex -Ied -Iparser -Ikfun $(CCFLAGS) 46 | LDFLAGS= 47 | LIBS= -ldl 48 | CXX= c++ 49 | LD= $(CXX) 50 | YACC= yacc 51 | BIN= ../bin 52 | 53 | ifeq ($(HOST),LINUX) 54 | DEFINES+=-D_FILE_OFFSET_BITS=64 55 | CXX+=-pthread 56 | endif 57 | ifeq ($(HOST),FREEBSD) 58 | LIBS= 59 | CXX+=-pthread 60 | endif 61 | ifeq ($(HOST),SOLARIS) 62 | DEFINES+=-D_FILE_OFFSET_BITS=64 63 | LIBS+=-lsocket -lnsl 64 | CXX=CC -mt -std=c++11 65 | endif 66 | 67 | SRC= alloc.cpp error.cpp hash.cpp swap.cpp str.cpp array.cpp object.cpp \ 68 | data.cpp path.cpp editor.cpp comm.cpp call_out.cpp interpret.cpp \ 69 | config.cpp ext.cpp dgd.cpp 70 | OBJ= alloc.o error.o hash.o swap.o str.o array.o object.o data.o path.o \ 71 | editor.o comm.o call_out.o interpret.o config.o ext.o dgd.o 72 | 73 | a.out: $(OBJ) comp/dgd lex/dgd ed/dgd parser/dgd kfun/dgd host/dgd 74 | $(LD) $(DEBUG) $(LDFLAGS) -o $@ $(OBJ) `cat comp/dgd` `cat lex/dgd` \ 75 | `cat ed/dgd` `cat parser/dgd` `cat kfun/dgd` `cat host/dgd` \ 76 | $(LIBS) 77 | 78 | comp/dgd:: 79 | $(MAKE) -C comp 'CXX=$(CXX)' 'CCFLAGS=$(CCFLAGS)' 'YACC=$(YACC)' dgd 80 | 81 | lex/dgd:: 82 | $(MAKE) -C lex 'CXX=$(CXX)' 'CCFLAGS=$(CCFLAGS)' dgd 83 | 84 | ed/dgd:: 85 | $(MAKE) -C ed 'CXX=$(CXX)' 'CCFLAGS=$(CCFLAGS)' dgd 86 | 87 | parser/dgd:: 88 | $(MAKE) -C parser 'CXX=$(CXX)' 'CCFLAGS=$(CCFLAGS)' dgd 89 | 90 | kfun/dgd:: 91 | $(MAKE) -C kfun 'CXX=$(CXX)' 'CCFLAGS=$(CCFLAGS)' dgd 92 | 93 | 94 | host/dgd:: 95 | $(MAKE) -C host 'CXX=$(CXX)' 'HOST=$(HOST)' 'CCFLAGS=$(CCFLAGS)' dgd 96 | 97 | all: a.out 98 | 99 | $(BIN)/dgd: a.out 100 | -mv $(BIN)/dgd $(BIN)/dgd.old 101 | cp a.out $(BIN)/dgd 102 | 103 | install: $(BIN)/dgd 104 | 105 | comp/parser.h: comp/parser.y 106 | $(MAKE) -C comp 'YACC=$(YACC)' parser.h 107 | 108 | ed/ed:: 109 | $(MAKE) -C ed 'CXX=$(CXX)' 'HOST=$(HOST)' 'CCFLAGS=$(CCFLAGS)' \ 110 | 'LD=$(LD)' 'LDFLAGS=$(LDFLAGS)' ed 111 | 112 | lex/lex:: 113 | $(MAKE) -C lex 'CXX=$(CXX)' 'HOST=$(HOST)' 'CCFLAGS=$(CCFLAGS)' \ 114 | 'LD=$(LD)' 'LDFLAGS=$(LDFLAGS)' lex 115 | 116 | clean: 117 | rm -f a.out $(OBJ) 118 | $(MAKE) -C comp clean 119 | $(MAKE) -C lex clean 120 | $(MAKE) -C ed clean 121 | $(MAKE) -C parser clean 122 | $(MAKE) -C kfun clean 123 | $(MAKE) -C host 'HOST=$(HOST)' clean 124 | 125 | 126 | path.o config.o dgd.o: comp/node.h comp/compile.h 127 | config.o: comp/parser.h 128 | array.o object.o data.o config.o interpret.o ext.o: comp/control.h 129 | 130 | path.o config.o: lex/ppcontrol.h 131 | 132 | editor.o: ed/edcmd.h 133 | 134 | data.o: parser/parse.h 135 | 136 | interpret.o config.o ext.o: kfun/table.h 137 | 138 | $(OBJ): dgd.h config.h host.h alloc.h error.h 139 | error.o str.o array.o object.o data.o: str.h array.h object.h hash.h swap.h 140 | path.o comm.o editor.o call_out.o: str.h array.h object.h hash.h swap.h 141 | interpret.o config.o ext.o dgd.o: str.h array.h object.h hash.h swap.h 142 | array.o error.o str.o object.o data.o comm.o call_out.o interpret.o: xfloat.h 143 | path.o config.o ext.o dgd.o: xfloat.h 144 | error.o array.o object.o data.o path.o editor.o comm.o: interpret.h 145 | call_out.o interpret.o config.o ext.o dgd.o: interpret.h 146 | error.o str.o array.o object.o data.o path.o comm.o call_out.o: data.h 147 | interpret.o config.o ext.o dgd.o: data.h 148 | path.o config.o: path.h 149 | hash.o: hash.h 150 | swap.o: hash.h swap.h 151 | editor.o config.o dgd.o: editor.h 152 | data.o call_out.o config.o dgd.o: call_out.h 153 | error.o comm.o config.o ext.o dgd.o: comm.h 154 | object.o data.o interpret.o config.o dgd.o: ext.h 155 | comm.o config.o: version.h 156 | -------------------------------------------------------------------------------- /src/array.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2022 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class Array : public ChunkAllocated { 21 | public: 22 | class Backup; /* array backup chunk */ 23 | 24 | Array(unsigned short size); 25 | Array() { 26 | prev = next = this; /* alist sentinel */ 27 | } 28 | virtual ~Array() { } 29 | 30 | void ref() { 31 | refCount++; 32 | } 33 | void del(); 34 | void freelist(); 35 | virtual bool trim(); 36 | virtual void canonicalize(); 37 | Uint put(Uint idx); 38 | void backup(Backup **ac); 39 | virtual Array *add(Dataspace *data, Array *a2); 40 | virtual Array *sub(Dataspace *data, Array *a2); 41 | virtual Array *intersect(Dataspace *data, Array *a2); 42 | Array *setAdd(Dataspace *data, Array *a2); 43 | Array *setXAdd(Dataspace *data, Array *a2); 44 | unsigned short index(LPCint l); 45 | void checkRange(LPCint l1, LPCint l2); 46 | Array *range(Dataspace *data, LPCint l1, LPCint l2); 47 | 48 | static void init(unsigned int size); 49 | static Array *alloc(unsigned short size); 50 | static Array *create(Dataspace *data, LPCint size); 51 | static Array *createNil(Dataspace *data, LPCint size); 52 | static void freeall(); 53 | static void merge(); 54 | static void clear(); 55 | static void commit(Backup **ac, Dataplane *plane, bool merge); 56 | static void discard(Backup **ac); 57 | 58 | unsigned short size; /* number of elements */ 59 | Uint refCount; /* number of references */ 60 | Uint tag; /* used in sorting */ 61 | Uint objDestrCount; /* last destructed object count */ 62 | Value *elts; /* elements */ 63 | struct ArrRef *primary; /* primary reference */ 64 | Array *prev, *next; /* per-object linked list */ 65 | 66 | protected: 67 | virtual void deepDelete(); 68 | virtual void shallowDelete(); 69 | 70 | friend class ArrBak; 71 | }; 72 | 73 | class Mapping : public Array { 74 | public: 75 | Mapping(unsigned short size); 76 | virtual ~Mapping() { } 77 | 78 | void sort(); 79 | virtual bool trim(); 80 | virtual void canonicalize(); 81 | unsigned short msize(Dataspace *data); 82 | virtual Array *add(Dataspace *data, Array *a2); 83 | virtual Array *sub(Dataspace *data, Array *a2); 84 | virtual Array *intersect(Dataspace *data, Array *a2); 85 | Value *index(Dataspace *data, Value *val, Value *elt, Value *verify); 86 | Mapping *range(Dataspace *data, Value *v1, Value *v2); 87 | Array *indices(Dataspace *data); 88 | Array *values(Dataspace *data); 89 | 90 | static Mapping *alloc(unsigned short size); 91 | static Mapping *create(Dataspace *data, LPCint size); 92 | 93 | protected: 94 | virtual void deepDelete(); 95 | virtual void shallowDelete(); 96 | 97 | private: 98 | void dehash(Dataspace *data, bool clean); 99 | void compact(Dataspace *data); 100 | 101 | bool hashmod; /* hashed part contains new elements */ 102 | class MapHash *hashed; /* hashed mapping elements */ 103 | 104 | friend class MapHash; 105 | }; 106 | 107 | class LWO : public Array { 108 | public: 109 | LWO(unsigned short size) : Array(size) { } 110 | virtual ~LWO() { } 111 | 112 | LWO *copy(Dataspace *data); 113 | 114 | static LWO *alloc(unsigned short size); 115 | static LWO *create(Dataspace *data, Object *obj); 116 | }; 117 | -------------------------------------------------------------------------------- /src/asn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2021 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class ASN { 21 | public: 22 | static String *add(Frame *f, String *s1, String *s2, String *s3); 23 | static String *sub(Frame *f, String *s1, String *s2, String *s3); 24 | static int cmp(Frame *f, String *s1, String *s2); 25 | static String *mult(Frame *f, String *s1, String *s2, String *s3); 26 | static String *div(Frame *f, String *s1, String *s2, String *s3); 27 | static String *mod(Frame *f, String *s1, String *s2); 28 | static String *pow(Frame *f, String *s1, String *s2, String *s3); 29 | static String *modinv(Frame *f, String *s1, String *s2); 30 | static String *lshift(Frame *f, String *s1, LPCint shift, String *s2); 31 | static String *rshift(Frame *f, String *s, LPCint shift); 32 | static String *_and(Frame *f, String *s1, String *s2); 33 | static String *_or(Frame *f, String *s1, String *s2); 34 | static String *_xor(Frame *f, String *s1, String *s2); 35 | 36 | private: 37 | static bool ticks(Frame *f, LPCuint ticks); 38 | }; 39 | -------------------------------------------------------------------------------- /src/call_out.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class CallOut { 21 | public: 22 | static bool init(unsigned int max); 23 | static Uint check(unsigned int n, LPCint delay, unsigned int mdelay, 24 | Uint *tp, unsigned short *mp, cindex **qp); 25 | static void create(unsigned int oindex, unsigned int handle, Uint t, 26 | unsigned int m, cindex *q); 27 | static LPCint remaining(Uint t, unsigned short *m); 28 | static void del(unsigned int oindex, unsigned int handle, Uint t, 29 | unsigned int m); 30 | static void list(Array *a); 31 | static void call(Frame *f); 32 | static void info(cindex *n1, cindex *n2); 33 | static Uint cotime(unsigned short *mtime); 34 | static Uint delay(Uint rtime, unsigned short rmtime, unsigned short *mtime); 35 | static void swapcount(unsigned int count); 36 | static long swaprate1(); 37 | static long swaprate5(); 38 | static bool save(int fd); 39 | static void restore(int fd, Uint t, bool conv16); 40 | 41 | private: 42 | static CallOut *enqueue(Uint t, unsigned short m); 43 | static void dequeue(cindex i); 44 | static CallOut *newcallout(cindex *list, Uint t); 45 | static void freecallout(cindex *cyc, cindex j, cindex i, Uint t); 46 | static bool rmshort(cindex *cyc, uindex i, uindex handle, Uint t); 47 | static void expire(); 48 | 49 | union { 50 | Time time; /* when to call */ 51 | struct { 52 | cindex count; /* # in list */ 53 | cindex prev; /* previous in list */ 54 | cindex next; /* next in list */ 55 | } r; 56 | }; 57 | uindex handle; /* callout handle */ 58 | uindex oindex; /* index in object table */ 59 | }; 60 | 61 | # define CO1_LAYOUT "[l|fff]uu" 62 | # define CO2_LAYOUT "[fff|l]uu" 63 | -------------------------------------------------------------------------------- /src/comm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # define P_TCP 6 21 | # define P_UDP 17 22 | # define P_TELNET 1 23 | 24 | class Connection { 25 | public: 26 | virtual bool attach() = 0; 27 | virtual bool udp(char *challenge, unsigned int len) = 0; 28 | virtual void del() = 0; 29 | virtual void block(int flag) = 0; 30 | virtual void stop() = 0; 31 | virtual bool udpCheck() = 0; 32 | virtual int read(char *buf, unsigned int len) = 0; 33 | virtual int readUdp(char *buf, unsigned int len) = 0; 34 | virtual int write(char *buf, unsigned int len) = 0; 35 | virtual int writeUdp(char *buf, unsigned int len) = 0; 36 | virtual bool wrdone() = 0; 37 | virtual void ipnum(char *buf) = 0; 38 | virtual void ipname(char *buf) = 0; 39 | virtual int checkConnected(int *errcode) = 0; 40 | virtual bool cexport(int *fd, char *addr, unsigned short *port, short *at, 41 | int *npkts, int *bufsz, char **buf, char *flags) = 0; 42 | 43 | static bool init(int maxusers, char **thosts, char **bhosts, char **dhosts, 44 | unsigned short *tports, unsigned short *bports, 45 | unsigned short *dports, int ntports, int nbports, 46 | int ndports); 47 | static void clear(); 48 | static void finish(); 49 | static void listen(); 50 | static int select(Uint t, unsigned int mtime); 51 | static void *host(char *addr, unsigned short port, int *len); 52 | static int fdcount(); 53 | static void fdlist(int *list); 54 | static void fdclose(int *list, int n); 55 | 56 | static Connection *createTelnet6(int port); 57 | static Connection *createTelnet(int port); 58 | static Connection *create6(int port); 59 | static Connection *create(int port); 60 | static Connection *createDgram6(int port); 61 | static Connection *createDgram(int port); 62 | static Connection *connect(void *addr, int len); 63 | static Connection *connectDgram(int uport, void *addr, int len); 64 | static Connection *import(int fd, char *addr, unsigned short port, short at, 65 | int npkts, int bufsz, char *buf, char flags, 66 | bool telnet); 67 | }; 68 | 69 | class Comm { 70 | public: 71 | static bool init(int n, int p, char **thosts, char **bhosts, char **dhosts, 72 | unsigned short *tports, unsigned short *bports, 73 | unsigned short *dports, int ntelnet, int nbinary, 74 | int ndatagram); 75 | static void clear(); 76 | static void finish(); 77 | static void listen(); 78 | static int send(Object *obj, String *str); 79 | static int udpsend(Object *obj, String *str); 80 | static bool echo(Object *obj, int echo); 81 | static void challenge(Object *obj, String *str); 82 | static void flush(); 83 | static void block(Object *obj, int block); 84 | static void stop(Object *obj); 85 | static void receive(Frame*, Uint, unsigned int); 86 | static String *ipNumber(Object*); 87 | static String *ipName(Object*); 88 | static void close(Frame*, Object*); 89 | static Object *user(); 90 | static void connect(Frame *f, Object *obj, char *addr, unsigned short port); 91 | static void connectDgram(Frame *f, Object *obj, int uport, char *addr, 92 | unsigned short port); 93 | static eindex numUsers(); 94 | static Array *listUsers(Dataspace*); 95 | static bool isConnection(Object*); 96 | static bool save(int); 97 | static bool restore(int); 98 | 99 | private: 100 | static void acceptTelnet(Frame *f, Connection *conn, int port); 101 | static void accept(Frame *f, Connection *conn, int port); 102 | static void acceptDgram(Frame *f, Connection *conn, int port); 103 | }; 104 | -------------------------------------------------------------------------------- /src/comp/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of DGD, https://github.com/dworkin/dgd 3 | # Copyright (C) 1993-2010 Dworkin B.V. 4 | # Copyright (C) 2010-2023 DGD Authors (see the commit log for details) 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as 8 | # published by the Free Software Foundation, either version 3 of the 9 | # License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | # 19 | CXXFLAGS=-I. -I.. -I../lex -I../parser -I../kfun $(CCFLAGS) 20 | 21 | SRC= node.cpp parser.cpp control.cpp optimize.cpp codegen.cpp compile.cpp 22 | OBJ= node.o parser.o control.o optimize.o codegen.o compile.o 23 | 24 | all: 25 | @echo Please run make from the src directory. 26 | 27 | dgd: $(OBJ) 28 | @for i in $(OBJ); do echo comp/$$i; done > dgd 29 | 30 | parser.cpp parser.h: parser.y 31 | $(YACC) -d parser.y 32 | mv y.tab.c parser.cpp 33 | mv y.tab.h parser.h 34 | 35 | clean: 36 | rm -f dgd a.out $(OBJ) 37 | 38 | 39 | $(OBJ): ../dgd.h ../config.h ../host.h ../error.h ../alloc.h ../str.h 40 | $(OBJ): ../array.h ../object.h ../hash.h ../swap.h ../xfloat.h ../interpret.h 41 | node.o parser.o control.o optimize.o codegen.o compile.o: ../data.h 42 | compile.o: ../path.h 43 | codegen.o: ../ext.h 44 | 45 | node.o parser.o compile.o: ../lex/ppcontrol.h 46 | 47 | parser.o control.o optimize.o codegen.o: ../kfun/table.h 48 | 49 | $(OBJ): comp.h node.h 50 | parser.o control.o optimize.o codegen.o compile.o: control.h 51 | codegen.o compile.o: codegen.h 52 | parser.o control.o optimize.o codegen.o compile.o: compile.h 53 | optimize.o compile.o: optimize.h 54 | -------------------------------------------------------------------------------- /src/comp/codegen.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2021 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class Codegen { 21 | public: 22 | static void init(int inherited); 23 | static char *function(String *fname, Node *n, int nvar, int npar, 24 | unsigned int depth, unsigned short *size); 25 | static int nfuncs(); 26 | static void clear(); 27 | 28 | private: 29 | static int type(Node *n, long *l); 30 | static void cast(Node *n); 31 | static int lvalue(Node *n, int fetch); 32 | static void store(Node *n); 33 | static void assign(Node *n, int op); 34 | static int aggr(Node *n); 35 | static int mapAggr(Node *n); 36 | static int lvalAggr(Node **l); 37 | static void storeAggr(Node *n); 38 | static int sumargs(Node *n); 39 | static int funargs(Node **l, int *nargs, bool *spread); 40 | static void storearg(Node *n); 41 | static void storeargs(Node *n); 42 | static int math(const char *name); 43 | static void expr(Node *n, int pop); 44 | static void cond(Node *n, int jmptrue); 45 | static void switchStart(Node *n); 46 | static void switchInt(Node *n); 47 | static void switchRange(Node *n); 48 | static void switchStr(Node *n); 49 | static void stmt(Node *n); 50 | }; 51 | -------------------------------------------------------------------------------- /src/comp/comp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "dgd.h" 21 | -------------------------------------------------------------------------------- /src/comp/compile.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class Compile { 21 | public: 22 | static void init(char *a, char *d, char *i, char **p, int tc); 23 | static bool typechecking(); 24 | static bool inherit(char *file, Node *label, int priv); 25 | static Object *compile(Frame *f, char *file, Object *obj, int nstr, 26 | int iflag); 27 | static int autodriver(); 28 | static String *objecttype(Node *n); 29 | static void global(unsigned int sclass, Node *type, Node *n); 30 | static void function(unsigned int sclass, Node *type, Node *n); 31 | static void funcbody(Node *n); 32 | static void local(unsigned int sclass, Node *type, Node *n); 33 | static void startCond(); 34 | static void startCond2(); 35 | static void endCond(); 36 | static void saveCond(); 37 | static void matchCond(); 38 | static bool nil(Node *n); 39 | static Node *concat(Node *n1, Node *n2); 40 | static Node *exprStmt(Node *n); 41 | static Node *ifStmt(Node *n1, Node *n2); 42 | static Node *endIfStmt(Node *n1, Node *n3); 43 | static void loop(); 44 | static Node *doStmt(Node *n1, Node *n2); 45 | static Node *whileStmt(Node *n1, Node *n2); 46 | static Node *forStmt(Node *n1, Node *n2, Node *n3, Node *n4); 47 | static void startRlimits(); 48 | static Node *endRlimits(Node *n1, Node *n2, Node *n3); 49 | static Node *exception(Node *n); 50 | static void startCatch(); 51 | static void endCatch(); 52 | static Node *doneCatch(Node *n1, Node *n2, bool pop); 53 | static void startSwitch(Node *n, int typechecked); 54 | static Node *endSwitch(Node *expr, Node *stmt); 55 | static Node *caseLabel(Node *n1, Node *n2); 56 | static Node *defaultLabel(); 57 | static Node *label(Node *n); 58 | static Node *gotoStmt(Node *n); 59 | static Node *breakStmt(); 60 | static Node *continueStmt(); 61 | static Node *returnStmt(Node *n, int typechecked); 62 | static void startCompound(); 63 | static Node *endCompound(Node *n); 64 | static Node *flookup(Node *n, int typechecked); 65 | static Node *iflookup(Node *n, Node *label); 66 | static Node *aggregate(Node *n, unsigned int type); 67 | static Node *localVar(Node *n); 68 | static Node *globalVar(Node *n); 69 | static short vtype(int i); 70 | static Node *funcall(Node *func, Node *args); 71 | static Node *arrow(Node *other, Node *func, Node *args); 72 | static Node *address(Node *func, Node *args, int typechecked); 73 | static Node *extend(Node *func, Node *args, int typechecked); 74 | static Node *call(Node *func, Node *args, int typechecked); 75 | static Node *newObject(Node *o, Node *args); 76 | static Node *instanceOf(Node *n, Node *prog); 77 | static Node *checkcall(Node *n, int typechecked); 78 | static Node *tst(Node *n); 79 | static Node *_not(Node *n); 80 | static Node *lvalue(Node *n, const char *oper); 81 | static Node *assign(Node *n); 82 | static unsigned short matchType(unsigned int type1, unsigned int type2); 83 | static void error(const char *format, ...); 84 | 85 | private: 86 | static void clear(); 87 | static void declFunc(unsigned short sclass, Node *type, String *str, 88 | Node *formals, bool function); 89 | static void declVar(unsigned short sclass, Node *type, String *str, 90 | bool global); 91 | static void declList(unsigned short sclass, Node *type, Node *list, 92 | bool global); 93 | static Node *block(Node *n, int type, int flags); 94 | static Node *reloop(Node *n); 95 | static Node *endloop(Node *n); 96 | static unsigned int aggrType(unsigned int, unsigned int); 97 | static bool lvalue(Node *n); 98 | static Node *funcall(Node *call, Node *args, int funcptr); 99 | static void lvalAggr(Node **n); 100 | }; 101 | -------------------------------------------------------------------------------- /src/comp/node.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "comp.h" 21 | # include "str.h" 22 | # include "array.h" 23 | # include "object.h" 24 | # include "xfloat.h" 25 | # include "data.h" 26 | # include "interpret.h" 27 | # include "ppcontrol.h" 28 | # include "node.h" 29 | 30 | # define NODE_CHUNK 128 31 | 32 | static class nodechunk : public Chunk { 33 | public: 34 | /* 35 | * dereference strings when iterating through items 36 | */ 37 | virtual bool item(Node *n) { 38 | if (n->type == N_STR || n->type == N_GOTO || n->type == N_LABEL) { 39 | n->l.string->del(); 40 | } 41 | if (n->sclass != (String *) NULL) { 42 | n->sclass->del(); 43 | } 44 | return TRUE; 45 | } 46 | } nchunk; 47 | 48 | int nil_node; /* N_NIL or N_INT */ 49 | 50 | /* 51 | * initialize node handling 52 | */ 53 | void Node::init(int flag) 54 | { 55 | nil_node = (flag) ? N_NIL : N_INT; 56 | } 57 | 58 | /* 59 | * constructor 60 | */ 61 | Node::Node(unsigned short line) 62 | { 63 | type = N_INT; 64 | flags = 0; 65 | mod = 0; 66 | this->line = line; 67 | sclass = (String *) NULL; 68 | l.left = (Node *) NULL; 69 | r.right = (Node *) NULL; 70 | } 71 | 72 | /* 73 | * create a new node 74 | */ 75 | Node *Node::create(unsigned short line) 76 | { 77 | return chunknew (nchunk) Node(line); 78 | } 79 | 80 | /* 81 | * create an integer node 82 | */ 83 | Node *Node::createInt(LPCint num) 84 | { 85 | Node *n; 86 | 87 | n = create(PP->line()); 88 | n->type = N_INT; 89 | n->flags = F_CONST; 90 | n->mod = T_INT; 91 | n->l.number = num; 92 | 93 | return n; 94 | } 95 | 96 | /* 97 | * create a float node 98 | */ 99 | Node *Node::createFloat(Float *flt) 100 | { 101 | Node *n; 102 | 103 | n = create(PP->line()); 104 | n->type = N_FLOAT; 105 | n->flags = F_CONST; 106 | n->mod = T_FLOAT; 107 | NFLT_PUT(n, *flt); 108 | 109 | return n; 110 | } 111 | 112 | /* 113 | * create a nil node 114 | */ 115 | Node *Node::createNil() 116 | { 117 | Node *n; 118 | 119 | n = create(PP->line()); 120 | n->type = nil_node; 121 | n->flags = F_CONST; 122 | n->mod = nil.type; 123 | n->l.number = 0; 124 | 125 | return n; 126 | } 127 | 128 | /* 129 | * create a string node 130 | */ 131 | Node *Node::createStr(String *str) 132 | { 133 | Node *n; 134 | 135 | n = create(PP->line()); 136 | n->type = N_STR; 137 | n->flags = F_CONST; 138 | n->mod = T_STRING; 139 | n->l.string = str; 140 | n->l.string->ref(); 141 | n->r.right = (Node *) NULL; 142 | 143 | return n; 144 | } 145 | 146 | /* 147 | * create a variable type node 148 | */ 149 | Node *Node::createVar(unsigned int type, int idx) 150 | { 151 | Node *n; 152 | 153 | n = create(PP->line()); 154 | n->type = N_VAR; 155 | n->mod = type; 156 | n->l.number = idx; 157 | 158 | return n; 159 | } 160 | 161 | /* 162 | * create a type node 163 | */ 164 | Node *Node::createType(int type, String *tclass) 165 | { 166 | Node *n; 167 | 168 | n = create(PP->line()); 169 | n->type = N_TYPE; 170 | n->mod = type; 171 | n->sclass = tclass; 172 | if (tclass != (String *) NULL) { 173 | tclass->ref(); 174 | } 175 | 176 | return n; 177 | } 178 | 179 | /* 180 | * create a function call node 181 | */ 182 | Node *Node::createFcall(int mod, String *tclass, char *func, LPCint call) 183 | { 184 | Node *n; 185 | 186 | n = create(PP->line()); 187 | n->type = N_FUNC; 188 | n->mod = mod; 189 | n->sclass = tclass; 190 | if (tclass != (String *) NULL) { 191 | tclass->ref(); 192 | } 193 | n->l.ptr = func; 194 | n->r.number = call; 195 | 196 | return n; 197 | } 198 | 199 | /* 200 | * create an operator node 201 | */ 202 | Node *Node::createOp(const char *op) 203 | { 204 | return createStr(String::create(op, strlen(op))); 205 | } 206 | 207 | /* 208 | * create a node for a monadic operator 209 | */ 210 | Node *Node::createMon(int type, int mod, Node *left) 211 | { 212 | Node *n; 213 | 214 | n = create(PP->line()); 215 | n->type = type; 216 | n->mod = mod; 217 | n->l.left = left; 218 | n->r.right = (Node *) NULL; 219 | 220 | return n; 221 | } 222 | 223 | /* 224 | * create a node for a binary operator 225 | */ 226 | Node *Node::createBin(int type, int mod, Node *left, Node *right) 227 | { 228 | Node *n; 229 | 230 | n = create(PP->line()); 231 | n->type = type; 232 | n->mod = mod; 233 | n->l.left = left; 234 | n->r.right = right; 235 | 236 | return n; 237 | } 238 | 239 | /* 240 | * convert node type to integer constant 241 | */ 242 | void Node::toint(LPCint i) 243 | { 244 | if (type == N_STR) { 245 | l.string->del(); 246 | } else if (type == N_TYPE && sclass != (String *) NULL) { 247 | sclass->del(); 248 | } 249 | type = N_INT; 250 | flags = F_CONST; 251 | l.number = i; 252 | } 253 | 254 | /* 255 | * convert node type to string constant 256 | */ 257 | void Node::tostr(String *str) 258 | { 259 | str->ref(); 260 | if (type == N_STR) { 261 | l.string->del(); 262 | } else if (type == N_TYPE && sclass != (String *) NULL) { 263 | sclass->del(); 264 | } 265 | type = N_STR; 266 | flags = F_CONST; 267 | l.string = str; 268 | } 269 | 270 | /* 271 | * revert a "linked list" of nodes 272 | */ 273 | Node *Node::revert(Node *n) 274 | { 275 | Node *m; 276 | 277 | if (n != (Node *) NULL && n->type == N_PAIR) { 278 | while ((m=n->l.left)->type == N_PAIR) { 279 | /* 280 | * ((a, b), c) -> (a, (b, c)) 281 | */ 282 | n->l.left = m->r.right; 283 | m->r.right = n; 284 | n = m; 285 | } 286 | } 287 | return n; 288 | } 289 | 290 | /* 291 | * cleanup after node handling 292 | */ 293 | void Node::clear() 294 | { 295 | nchunk.items(); 296 | nchunk.clean(); 297 | } 298 | -------------------------------------------------------------------------------- /src/comp/optimize.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2020 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class Optimize { 21 | public: 22 | static void init(); 23 | static Node *stmt(Node *first, Uint *depth); 24 | 25 | private: 26 | static Uint max2(Uint a, Uint b); 27 | static Uint max3(Uint a, Uint b, Uint c); 28 | static Node **sideStart(Node **n, Uint *depth); 29 | static void sideAdd(Node **n, Uint depth); 30 | static Uint sideEnd(Node **n, Node *side, Node **oldside, Uint olddepth); 31 | static Uint lvalue(Node *n); 32 | static Uint binconst(Node **m); 33 | static Node *tst(Node *n); 34 | static Node *_not(Node *n); 35 | static Uint binop(Node **m); 36 | static Uint assignExpr(Node **m, bool pop); 37 | static bool ctest(Node *n); 38 | static Uint cond(Node **m, bool pop); 39 | static Uint expr(Node **m, bool pop); 40 | static int constant(Node *n); 41 | static Node *skip(Node *n); 42 | }; 43 | -------------------------------------------------------------------------------- /src/dgd.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # define INCLUDE_FILE_IO 21 | # include "dgd.h" 22 | # include "str.h" 23 | # include "array.h" 24 | # include "object.h" 25 | # include "xfloat.h" 26 | # include "data.h" 27 | # include "interpret.h" 28 | # include "editor.h" 29 | # include "call_out.h" 30 | # include "comm.h" 31 | # include "ext.h" 32 | # include "node.h" 33 | # include "compile.h" 34 | 35 | static uindex dindex; /* driver object index */ 36 | static Uint dcount; /* driver object count */ 37 | static Sector fragment; /* swap fragment parameter */ 38 | static bool rebuild; /* rebuild swapfile? */ 39 | bool intr; /* received an interrupt? */ 40 | 41 | /* 42 | * call a function in the driver object 43 | */ 44 | bool DGD::callDriver(Frame *f, const char *func, int narg) 45 | { 46 | Object *driver; 47 | char *driver_name; 48 | 49 | if (dindex == UINDEX_MAX || dcount != (driver=OBJR(dindex))->count || 50 | !(driver->flags & O_DRIVER)) { 51 | driver_name = Config::driver(); 52 | driver = Object::find(driver_name, OACC_READ); 53 | if (driver == (Object *) NULL) { 54 | driver = Compile::compile(f, driver_name, (Object *) NULL, 0, 55 | FALSE); 56 | } 57 | dindex = driver->index; 58 | dcount = driver->count; 59 | } 60 | if (!f->call(driver, (LWO *) NULL, func, strlen(func), TRUE, narg)) { 61 | EC->fatal("missing function in driver object: %s", func); 62 | } 63 | return TRUE; 64 | } 65 | 66 | /* 67 | * register an interrupt 68 | */ 69 | void DGD::interrupt() 70 | { 71 | intr = TRUE; 72 | } 73 | 74 | /* 75 | * clean up after a task has terminated 76 | */ 77 | void DGD::endTask() 78 | { 79 | Comm::flush(); 80 | Dataspace::xport(); 81 | Object::clean(); 82 | Frame::clear(); 83 | Editor::clear(); 84 | EC->clearException(); 85 | 86 | CallOut::swapcount(Dataspace::swapout(fragment)); 87 | 88 | if (stop) { 89 | Comm::clear(); 90 | Editor::finish(); 91 | # ifdef DEBUG 92 | swap = TRUE; 93 | # endif 94 | } 95 | 96 | if (swap || !MM->check()) { 97 | /* 98 | * swap out everything and possibly extend the static memory area 99 | */ 100 | Dataspace::swapout(1); 101 | Array::freeall(); 102 | String::clean(); 103 | MM->purge(); 104 | swap = FALSE; 105 | } 106 | 107 | if (dump) { 108 | /* 109 | * create a snapshot 110 | */ 111 | Config::dump(incr, boot); 112 | dump = FALSE; 113 | if (!incr) { 114 | rebuild = TRUE; 115 | dindex = UINDEX_MAX; 116 | } 117 | } 118 | 119 | if (stop) { 120 | Swap::finish(); 121 | Config::modFinish(TRUE); 122 | Ext::finish(); 123 | 124 | if (boot) { 125 | char **hotboot; 126 | 127 | /* 128 | * attempt to hotboot 129 | */ 130 | hotboot = Config::hotbootExec(); 131 | P_execv(hotboot[0], hotboot); 132 | EC->message("Hotboot failed\012"); /* LF */ 133 | } 134 | 135 | Comm::finish(); 136 | Array::freeall(); 137 | String::clean(); 138 | MM->finish(); 139 | std::exit(boot); 140 | } 141 | } 142 | 143 | /* 144 | * default error handler 145 | */ 146 | void DGD::errHandler(Frame *f, LPCint depth) 147 | { 148 | UNREFERENCED_PARAMETER(depth); 149 | Frame::runtimeError(f, 0); 150 | } 151 | 152 | /* 153 | * the main loop of DGD 154 | */ 155 | int DGD::main(int argc, char **argv) 156 | { 157 | char *program; 158 | Uint rtime, timeout; 159 | unsigned short rmtime, mtime; 160 | 161 | rmtime = 0; 162 | 163 | --argc; 164 | program = *argv++; 165 | if (argc < 1 || argc > 3) { 166 | EC->message("Usage: %s config_file [[partial_snapshot] snapshot]\012", /* LF */ 167 | program); 168 | return 2; 169 | } 170 | 171 | /* initialize */ 172 | dindex = UINDEX_MAX; 173 | swap = dump = incr = stop = FALSE; 174 | rebuild = TRUE; 175 | rtime = 0; 176 | if (!Config::init(argv[0], (argc > 1) ? argv[1] : (char *) NULL, 177 | (argc > 2) ? argv[2] : (char *) NULL, &fragment)) { 178 | return 2; /* initialization failed */ 179 | } 180 | 181 | for (;;) { 182 | /* rebuild swapfile */ 183 | if (rebuild) { 184 | timeout = CallOut::cotime(&mtime); 185 | if (timeout > rtime || (timeout == rtime && mtime >= rmtime)) { 186 | rebuild = Object::copy(timeout); 187 | CallOut::swapcount(Dataspace::swapout(fragment)); 188 | if (rebuild) { 189 | rtime = timeout + 1; 190 | rmtime = mtime; 191 | } else { 192 | rtime = 0; 193 | } 194 | } 195 | } 196 | 197 | /* interrupts */ 198 | if (intr) { 199 | intr = FALSE; 200 | try { 201 | EC->push((ErrorContext::Handler) errHandler); 202 | callDriver(cframe, "interrupt", 0); 203 | (cframe->sp++)->del(); 204 | EC->pop(); 205 | } catch (const char*) { } 206 | endTask(); 207 | } 208 | 209 | /* handle user input */ 210 | timeout = CallOut::delay(rtime, rmtime, &mtime); 211 | Comm::receive(cframe, timeout, mtime); 212 | 213 | /* callouts */ 214 | CallOut::call(cframe); 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /src/dgd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2022 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "host.h" 21 | 22 | class String; 23 | class Array; 24 | class Object; 25 | class Value; 26 | class Control; 27 | class Dataplane; 28 | class Dataspace; 29 | class Frame; 30 | 31 | # include "config.h" 32 | # include "alloc.h" 33 | # include "error.h" 34 | 35 | # define BOFF(bit) ((bit) >> 5) 36 | # define BBIT(bit) (1 << ((bit) & 31)) 37 | # define BMAP(size) BOFF((size) + 31) 38 | 39 | # define BSET(map, bit) (map[BOFF(bit)] |= BBIT(bit)) 40 | # define BCLR(map, bit) (map[BOFF(bit)] &= ~BBIT(bit)) 41 | # define BTST(map, bit) (map[BOFF(bit)] & BBIT(bit)) 42 | 43 | typedef uint64_t Time; 44 | 45 | # define TIME_INT 2000 46 | 47 | class DGD { 48 | public: 49 | static bool callDriver(Frame *frame, const char *func, int narg); 50 | static void interrupt(); 51 | static void endTask(); 52 | static void errHandler(Frame *f, LPCint depth); 53 | static int main(int argc, char **argv); 54 | }; 55 | 56 | extern bool intr; 57 | -------------------------------------------------------------------------------- /src/ed/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of DGD, https://github.com/dworkin/dgd 3 | # Copyright (C) 1993-2010 Dworkin B.V. 4 | # Copyright (C) 2010-2021 DGD Authors (see the commit log for details) 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as 8 | # published by the Free Software Foundation, either version 3 of the 9 | # License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | # 19 | CXXFLAGS=-I. -I.. $(CCFLAGS) 20 | 21 | SRC= line.cpp buffer.cpp fileio.cpp regexp.cpp vars.cpp edcmd.cpp cmdsub.cpp 22 | OBJ= line.o buffer.o fileio.o regexp.o vars.o edcmd.o cmdsub.o 23 | 24 | all: 25 | @echo Please run make from the src directory. 26 | 27 | dgd: $(OBJ) 28 | @for i in $(OBJ); do echo ed/$$i; done > dgd 29 | 30 | ed: $(OBJ) ed.o 31 | $(LD) $(DEBUG) $(LDFLAGS) -o $@ $(OBJ) ed.o 32 | 33 | clean: 34 | rm -f dgd ed $(OBJ) ed.o 35 | 36 | 37 | $(OBJ) ed.o: ../dgd.h ../config.h ../host.h ../alloc.h ../error.h ../editor.h 38 | fileio.o ed.o: ../path.h 39 | 40 | $(OBJ) ed.o: ed.h 41 | buffer.o fileio.o edcmd.o cmdsub.o: buffer.h 42 | edcmd.o cmdsub.o ed.o: edcmd.h 43 | cmdsub.o fileio.o: fileio.h 44 | line.o buffer.o fileio.o edcmd.o cmdsub.o: line.h 45 | regexp.o edcmd.o cmdsub.o: regexp.h 46 | vars.o edcmd.o cmdsub.o: vars.h 47 | -------------------------------------------------------------------------------- /src/ed/buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2021 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "line.h" 21 | 22 | class EditBuf : public LineBuf { 23 | public: 24 | EditBuf(char *tmpfile); 25 | virtual ~EditBuf(); 26 | 27 | virtual char *getline(); 28 | virtual void putline(const char *line); 29 | 30 | void clear(); 31 | void add(Int ln, char *(*get)()); 32 | Block del(Int first, Int last); 33 | void change(Int first, Int last, Block b); 34 | Block yank(Int first, Int last); 35 | void put(Int ln, Block b); 36 | void range(Int first, Int last, void (*put)(const char*), bool reverse); 37 | void startblock(); 38 | void addblock(const char *text); 39 | void endblock(); 40 | 41 | Block buffer; /* the actual edit buffer */ 42 | Int lines; /* # lines in edit buffer */ 43 | Block flines; /* block of first lines to add */ 44 | 45 | private: 46 | void flushLine(); 47 | 48 | int szlines; /* size of "last" insert add */ 49 | char *llines; /* llbuf pointer */ 50 | char *(*getLine)(); /* getline function */ 51 | void (*putLine)(const char*); /* putline function */ 52 | char llbuf[4 * MAX_LINE_SIZE]; /* last lines buffer */ 53 | }; 54 | -------------------------------------------------------------------------------- /src/ed/ed.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 2021-2023 DGD Authors (see the commit log for details) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as 7 | * published by the Free Software Foundation, either version 3 of the 8 | * License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | # include "ed.h" 20 | # include "path.h" 21 | # include "edcmd.h" 22 | 23 | 24 | static Alloc EDMM; 25 | Alloc *MM = &EDMM; 26 | 27 | static ErrorContext EDEC; 28 | ErrorContext *EDC = &EDEC; 29 | 30 | static Path EDPM; 31 | Path *PM = &EDPM; 32 | 33 | /* 34 | * stand-alone editor 35 | */ 36 | int main(int argc, char *argv[]) 37 | { 38 | char tmp[100], line[2048], *p; 39 | CmdBuf *ed; 40 | 41 | snprintf(tmp, sizeof(tmp), "/tmp/ed%05d", (int) getpid()); 42 | ed = new CmdBuf(tmp); 43 | if (argc > 1) { 44 | snprintf(line, sizeof(line), "e %s", argv[1]); 45 | try { 46 | ed->command(line); 47 | } catch (const char*) { } 48 | } 49 | 50 | for (;;) { 51 | if (ed->flags & CB_INSERT) { 52 | fputs("*\b", stdout); 53 | } else { 54 | putchar(':'); 55 | } 56 | if (fgets(line, sizeof(line), stdin) == NULL) { 57 | break; 58 | } 59 | p = strchr(line, '\n'); 60 | if (p != NULL) { 61 | *p = '\0'; 62 | } 63 | try { 64 | if (!ed->command(line)) { 65 | break; 66 | } 67 | } catch (const char*) { } 68 | } 69 | 70 | delete ed; 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /src/ed/ed.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2021 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "dgd.h" 21 | # include "editor.h" 22 | -------------------------------------------------------------------------------- /src/ed/edcmd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2021 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "regexp.h" 21 | # include "buffer.h" 22 | # include "vars.h" 23 | 24 | /* status flags */ 25 | # define CB_NOIMAGE 0x0001 26 | # define CB_INSERT 0x0002 27 | # define CB_CHANGE 0x0004 28 | # define CB_GLOBAL 0x0008 29 | # define CB_EXCL 0x0010 30 | # define CB_NUMBER 0x0020 31 | # define CB_LIST 0x0040 32 | 33 | /* indentor */ 34 | # define CB_PPCONTROL 0x0080 35 | # define CB_COMMENT 0x0100 36 | # define CB_JSKEYWORD 0x0200 37 | 38 | /* substitutor */ 39 | # define CB_CURRENTBLK 0x0080 40 | # define CB_SKIPPED 0x0100 41 | # define CB_GLOBSUBST 0x0200 42 | # define CB_UPPER 0x0400 43 | # define CB_LOWER 0x0800 44 | # define CB_TUPPER 0x1000 45 | # define CB_TLOWER 0x2000 46 | 47 | class CmdBuf : public Allocated { 48 | public: 49 | CmdBuf(char *tmpfile); 50 | virtual ~CmdBuf(); 51 | 52 | bool command(const char *command); 53 | int doundo(); 54 | int global(); 55 | int vglobal(); 56 | int print(); 57 | int list(); 58 | int number(); 59 | int page(); 60 | int assign(); 61 | int domark(); 62 | int append(); 63 | int insert(); 64 | int change(); 65 | int del(); 66 | int copy(); 67 | int move(); 68 | int put(); 69 | int yank(); 70 | int lshift(); 71 | int rshift(); 72 | int indent(); 73 | int join(); 74 | int subst(); 75 | int file(); 76 | int read(); 77 | int edit(); 78 | int quit(); 79 | int write(); 80 | int wq(); 81 | int xit(); 82 | int set(); 83 | 84 | EditBuf edbuf; /* edit buffer */ 85 | short flags; /* status flags */ 86 | 87 | private: 88 | void count(); 89 | void not_in_global(); 90 | void dodo(Int cthis); 91 | void dobuf(Block b); 92 | void add(Int ln, Block b, Int size); 93 | Block dellines(Int first, Int last); 94 | void change(Int first, Int last, Block b); 95 | void startblock(); 96 | void addblock(const char *text); 97 | void endblock(); 98 | Int dosearch(Int first, Int last, bool reverse); 99 | void pattern(char delim); 100 | Int address(Int first); 101 | void range(); 102 | int doshift(); 103 | void noshift(const char *text); 104 | void sub(const char *text, unsigned int size); 105 | bool getfname(char *buffer); 106 | 107 | static const char *skipst(const char *p); 108 | static const char *pattern(const char *pat, int delim, char *buffer); 109 | static void globfind(const char *text); 110 | static void find(const char *text); 111 | static void println(const char *text); 112 | static void doshift(const char *text); 113 | static void indent(const char *text); 114 | static void join(const char *text); 115 | static void subst(const char *text); 116 | static void io_show(struct io *iob); 117 | 118 | const char *cmd; /* command to do */ 119 | RxBuf regexp; /* current regular expression */ 120 | Vars vars; /* variables */ 121 | bool reverse; /* reverse search */ 122 | bool ignorecase; /* ignore case */ 123 | 124 | Int edits; /* number of edits on file */ 125 | 126 | Int cthis; /* current line number */ 127 | Int othis; /* current line number after last operation */ 128 | Int first; /* first line number of current range */ 129 | Int last; /* last line number of current range */ 130 | 131 | Int a_addr; /* argument address */ 132 | char a_buffer; /* argument buffer */ 133 | 134 | Int lineno; /* current line number in internal operations */ 135 | char *buffer; /* buffer for internal operations */ 136 | int buflen; /* size of buffer */ 137 | 138 | /* globals */ 139 | RxBuf *glob_rx; /* global regexp */ 140 | Int glob_next; /* next line affected in global */ 141 | Int glob_size; /* # lines affected in global */ 142 | 143 | /* indenting and shifting */ 144 | char *stack, *stackbot; /* token stack */ 145 | int *ind; /* indent stack */ 146 | char quote; /* ' or " */ 147 | short shift; /* shift amount */ 148 | 149 | /* substituting */ 150 | Int offset; /* offset in lines */ 151 | Int *moffset; /* mark offsets */ 152 | 153 | Int mark[26]; /* line numbers of marks */ 154 | Block buf; /* default yank buffer */ 155 | Block zbuf[26]; /* named buffers */ 156 | 157 | char fname[STRINGSZ]; /* current filename */ 158 | 159 | Block undo; /* undo block */ 160 | Int uthis; /* current line number after undo */ 161 | Int umark[26]; /* marks after undo */ 162 | 163 | char search[STRINGSZ]; /* pattern to search for */ 164 | char replace[STRINGSZ]; /* string to replace with */ 165 | }; 166 | 167 | # define RET_QUIT 1 168 | # define RET_FLAGS 2 169 | 170 | extern CmdBuf *ccb; 171 | -------------------------------------------------------------------------------- /src/ed/fileio.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2021 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # define INCLUDE_FILE_IO 21 | # include "ed.h" 22 | # include "buffer.h" 23 | # include "path.h" 24 | # include "fileio.h" 25 | 26 | /* 27 | * The file I/O operations of the editor. 28 | */ 29 | 30 | static IO *iostat; /* I/O status */ 31 | 32 | /* 33 | * read a line from the input, return as '\0'-terminated string 34 | * without '\n' 35 | */ 36 | char *IO::get_line() 37 | { 38 | char c, *p, *bp; 39 | int i; 40 | 41 | if (iostat->ill) { 42 | /* previous line was incomplete, therefore the last */ 43 | return (char *) NULL; 44 | } 45 | 46 | p = iostat->lbuf; 47 | bp = iostat->bufp; 48 | i = iostat->inbuf; 49 | do { 50 | if (i == 0) { /* buffer empty */ 51 | i = P_read(iostat->ffd, iostat->buffer, BUF_SIZE); 52 | if (i <= 0) { 53 | /* eof or error */ 54 | if (i < 0) { 55 | EDC->error("error while reading file \"/%s\"", 56 | iostat->filename); 57 | } 58 | if (p == iostat->lbuf) { 59 | return (char *) NULL; 60 | } else { 61 | p++; /* make room for terminating '\0' */ 62 | iostat->ill = TRUE; 63 | break; 64 | } 65 | } 66 | bp = iostat->buffer; 67 | } 68 | --i; 69 | c = *bp++; 70 | if (c == '\0') { 71 | iostat->zero++; /* skip zeroes */ 72 | } else { 73 | if (p == iostat->lbuflast && c != LF) { 74 | iostat->split++; 75 | i++; 76 | --bp; 77 | c = LF; 78 | } 79 | *p++ = c; 80 | } 81 | } while (c != LF); /* eoln */ 82 | 83 | iostat->lines++; 84 | iostat->chars += p - iostat->lbuf; /* including terminating '\0' */ 85 | iostat->bufp = bp; 86 | iostat->inbuf = i; 87 | *--p = '\0'; 88 | return iostat->lbuf; 89 | } 90 | 91 | /* 92 | * append block read from file after a line 93 | */ 94 | bool IO::load(EditBuf *eb, char *fname, Int l) 95 | { 96 | char b[MAX_LINE_SIZE], buf[BUF_SIZE]; 97 | struct stat sbuf; 98 | 99 | /* open file */ 100 | if (PM->edRead(filename, fname) == (char *) NULL || 101 | P_stat(filename, &sbuf) < 0 || (sbuf.st_mode & S_IFMT) != S_IFREG) { 102 | return FALSE; 103 | } 104 | 105 | ffd = P_open(filename, O_RDONLY | O_BINARY, 0); 106 | if (ffd < 0) { 107 | return FALSE; 108 | } 109 | 110 | /* initialize buffers */ 111 | buffer = buf; 112 | inbuf = 0; 113 | lbuf = b; 114 | lbuflast = &b[MAX_LINE_SIZE - 1]; 115 | 116 | /* initialize statistics */ 117 | lines = 0; 118 | chars = 0; 119 | zero = 0; 120 | split = 0; 121 | ill = FALSE; 122 | iostat = this; 123 | 124 | /* add the block to the edit buffer */ 125 | try { 126 | EDC->push(); 127 | eb->add(l, get_line); 128 | EDC->pop(); 129 | } catch (const char*) { 130 | P_close(ffd); 131 | EDC->error((char *) NULL); /* pass on error */ 132 | } 133 | P_close(ffd); 134 | 135 | return TRUE; 136 | } 137 | 138 | /* 139 | * write a line to a file 140 | */ 141 | void IO::put_line(const char *text) 142 | { 143 | unsigned int len; 144 | 145 | len = strlen(text); 146 | iostat->lines += 1; 147 | iostat->chars += len + 1; 148 | while (iostat->inbuf + len >= BUF_SIZE) { /* flush buffer */ 149 | if (iostat->inbuf != BUF_SIZE) { /* room left for a piece of line */ 150 | unsigned int chunk; 151 | 152 | chunk = BUF_SIZE - iostat->inbuf; 153 | memcpy(iostat->buffer + iostat->inbuf, text, chunk); 154 | text += chunk; 155 | len -= chunk; 156 | } 157 | if (P_write(iostat->ffd, iostat->buffer, BUF_SIZE) != BUF_SIZE) { 158 | EDC->error("error while writing file \"/%s\"", iostat->filename); 159 | } 160 | iostat->inbuf = 0; 161 | } 162 | if (len > 0) { /* piece of line left */ 163 | memcpy(iostat->buffer + iostat->inbuf, text, len); 164 | iostat->inbuf += len; 165 | } 166 | iostat->buffer[iostat->inbuf++] = LF; 167 | } 168 | 169 | /* 170 | * write a range of lines to a file 171 | */ 172 | bool IO::save(EditBuf *eb, char *fname, Int first, Int last, int append) 173 | { 174 | char buf[BUF_SIZE]; 175 | struct stat sbuf; 176 | 177 | if (PM->edWrite(filename, fname) == (char *) NULL || 178 | (P_stat(filename, &sbuf) >= 0 && (sbuf.st_mode & S_IFMT) != S_IFREG)) 179 | { 180 | return FALSE; 181 | } 182 | /* create file */ 183 | ffd = P_open(filename, 184 | (append) ? O_CREAT | O_APPEND | O_WRONLY | O_BINARY : 185 | O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 186 | 0664); 187 | if (ffd < 0) { 188 | return FALSE; 189 | } 190 | 191 | /* initialize buffer */ 192 | buffer = buf; 193 | inbuf = 0; 194 | 195 | /* initialize statistics */ 196 | lines = 0; 197 | chars = 0; 198 | zero = 0; 199 | split = 0; 200 | ill = FALSE; 201 | iostat = this; 202 | 203 | /* write range */ 204 | try { 205 | EDC->push(); 206 | eb->range(first, last, put_line, FALSE); 207 | if (P_write(ffd, buffer, inbuf) != inbuf) { 208 | EDC->error("error while writing file \"/%s\"", filename); 209 | } 210 | EDC->pop(); 211 | } catch (const char*) { 212 | P_close(ffd); 213 | EDC->error((char *) NULL); /* pass on error */ 214 | } 215 | P_close(ffd); 216 | 217 | return TRUE; 218 | } 219 | 220 | /* 221 | * show statistics on the file just read/written 222 | */ 223 | void IO::show() 224 | { 225 | EDC->message("%ld lines, %ld characters", (long) lines, 226 | (long) (chars + zero - split - ill)); 227 | if (zero > 0) { 228 | EDC->message(" [%ld zero]", (long) zero); 229 | } 230 | if (split > 0) { 231 | EDC->message(" [%ld split]", (long) split); 232 | } 233 | if (ill) { 234 | EDC->message(" [incomplete last line]"); 235 | } 236 | EDC->message("\012"); /* LF */ 237 | } 238 | -------------------------------------------------------------------------------- /src/ed/fileio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2022 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class IO { 21 | public: 22 | bool load(EditBuf *ed, char *fname, Int l); 23 | bool save(EditBuf *ed, char *fname, Int first, Int last, int append); 24 | void show(); 25 | 26 | static char *get_line(); 27 | static void put_line(const char *text); 28 | 29 | Int lines; /* number of lines */ 30 | Int chars; /* number of characters */ 31 | Int zero; /* number of zeroes discarded */ 32 | Int split; /* number of splits of too long lines */ 33 | bool ill; /* incomplete last line */ 34 | 35 | private: 36 | int ffd; /* read/write file descriptor */ 37 | char *buffer; /* file buffer */ 38 | char *bufp; /* buffer pointer */ 39 | unsigned int inbuf; /* # bytes in buffer */ 40 | char *lbuf; /* line buffer */ 41 | char *lbuflast; /* end of line buffer */ 42 | char filename[STRINGSZ]; /* file name */ 43 | }; 44 | -------------------------------------------------------------------------------- /src/ed/line.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2021 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | /* 21 | * The basic data type is a line buffer, in which blocks of lines are 22 | * allocated. The line buffer can be made inactive, to make it use as little 23 | * system resources as possible. 24 | * Blocks can be created, deleted, queried for their size, split in two, or 25 | * concatenated. 26 | */ 27 | typedef Int Block; 28 | 29 | class LineBuf : public Allocated { 30 | public: 31 | LineBuf(char *filename); 32 | virtual ~LineBuf(); 33 | 34 | virtual char *getline() = 0; 35 | virtual void putline(const char *line) = 0; 36 | 37 | void reset(); 38 | void inact(); 39 | Block create(); 40 | Int size(Block b); 41 | void split(Block b, Int size, Block *b1, Block *b2); 42 | Block cat(Block b1, Block b2); 43 | void put(Block b, Int idx, Int size, bool reverse); 44 | 45 | private: 46 | struct BTBuf { 47 | long offset; /* offset in tmpfile */ 48 | BTBuf *prev; /* prev in linked list */ 49 | BTBuf *next; /* next in linked list */ 50 | char *buf; /* buffer with blocks and text */ 51 | }; 52 | struct Blk { 53 | Block prev, next; /* first and last */ 54 | Int lines; /* size of this block */ 55 | union { 56 | Int lindex; /* index from start of chain block */ 57 | struct { 58 | short u_index1; /* index in first chain block */ 59 | short u_index2; /* index in last chain block */ 60 | } s; 61 | }; 62 | }; 63 | 64 | void init(); 65 | void act(); 66 | void write(); 67 | Blk *load(Block b); 68 | Blk *putblk(Blk *bp, char *text); 69 | Blk *putln(Blk *bp, char *text); 70 | void split1(Blk *bp, Int size, Block *b1, Block *b2); 71 | void put1(Blk *bp, Int idx, Int size); 72 | 73 | char *file; /* tmpfile name */ 74 | int fd; /* tmpfile fd */ 75 | char *buf; /* current low-level buffer */ 76 | int blksz; /* block size in write buffer */ 77 | int txtsz; /* text size in write buffer */ 78 | bool reverse; /* for bk_put() */ 79 | BTBuf *wb; /* write buffer */ 80 | BTBuf bt[NR_EDBUFS]; /* read & write buffers */ 81 | }; 82 | -------------------------------------------------------------------------------- /src/ed/regexp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2019 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | /* 21 | * Regular expressions, ex-style. Allocating and freeing memory for each 22 | * regular expression would cause memory problems, so a buffer is allocated 23 | * instead in which a regular expression can be compiled. 24 | */ 25 | # define RXBUFSZ 2048 26 | # define NSUBEXP 9 27 | 28 | class RxBuf : public Allocated { 29 | public: 30 | RxBuf(); 31 | virtual ~RxBuf(); 32 | 33 | const char *comp(const char *pattern); 34 | int exec(const char *text, int idx, bool ic); 35 | 36 | bool valid; /* is the present matcher valid? */ 37 | bool anchor; /* is the match anchored (^pattern) */ 38 | char firstc; /* first character in match, if any */ 39 | const char *start; /* start of matching sequence */ 40 | int size; /* size of matching sequence */ 41 | struct { 42 | const char *start; /* start of subexpression */ 43 | int size; /* size of subexpression */ 44 | } se[NSUBEXP]; 45 | char buffer[RXBUFSZ]; /* buffer to hold matcher */ 46 | 47 | private: 48 | bool match(const char *start, const char *text, bool ic, char *m, 49 | const char *t); 50 | }; 51 | -------------------------------------------------------------------------------- /src/ed/vars.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2021 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "ed.h" 21 | # include "vars.h" 22 | 23 | /* 24 | * The editor variables are handled here. 25 | */ 26 | 27 | /* 28 | * allocate and initialize a variable buffer 29 | */ 30 | Vars::Vars() 31 | { 32 | static Var dflt[] = { 33 | { "ignorecase", "ic", FALSE }, 34 | { "shiftwidth", "sw", 4 }, 35 | { "window", "wi", 20 }, 36 | }; 37 | 38 | memcpy(v, dflt, sizeof(dflt)); 39 | } 40 | 41 | /* 42 | * set the value of a variable. 43 | */ 44 | void Vars::set(char *option) 45 | { 46 | char buffer[2]; 47 | char *val; 48 | Int i; 49 | Var *v; 50 | 51 | if (strncmp(option, "no", 2) == 0) { 52 | option += 2; 53 | strcpy(buffer, "0"); 54 | val = buffer; 55 | } else { 56 | val = strchr(option, '='); 57 | if (val != (char *) NULL) { 58 | *val++ = '\0'; 59 | } 60 | } 61 | 62 | for (i = NUMBER_OF_VARS, v = this->v; i > 0; --i, v++) { 63 | if (strcmp(v->name, option) == 0 || 64 | strcmp(v->sname, option) == 0) { 65 | if (!val) { 66 | v->val = 1; 67 | } else { 68 | char *p; 69 | 70 | p = val; 71 | i = strtol(p, &p, 10); 72 | if (val == p || i < 0) { 73 | EDC->error("Bad numeric value for option \"%s\"", v->name); 74 | } 75 | v->val = i; 76 | } 77 | return; 78 | } 79 | } 80 | EDC->error("No such option"); 81 | } 82 | 83 | /* 84 | * show all variables 85 | */ 86 | void Vars::show() 87 | { 88 | EDC->message("%signorecase\011", (v[0].val) ? "" : "no"); /* HT */ 89 | EDC->message("shiftwidth=%ld\011", (long) v[1].val); /* HT */ 90 | EDC->message("window=%ld\012", (long) v[2].val); /* LF */ 91 | } 92 | -------------------------------------------------------------------------------- /src/ed/vars.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2021 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # define NUMBER_OF_VARS 3 21 | 22 | class Vars { 23 | public: 24 | struct Var { 25 | const char *name; /* long variable name */ 26 | const char *sname; /* short variable name */ 27 | Int val; /* value */ 28 | }; 29 | 30 | Vars(); 31 | 32 | void set(char *option); 33 | void show(); 34 | 35 | Var v[NUMBER_OF_VARS]; 36 | }; 37 | 38 | # define IGNORECASE(vars) (vars.v[0].val) 39 | # define SHIFTWIDTH(vars) (vars.v[1].val) 40 | # define WINDOW(vars) (vars.v[2].val) 41 | -------------------------------------------------------------------------------- /src/editor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2023 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "dgd.h" 21 | # include "str.h" 22 | # include "array.h" 23 | # include "object.h" 24 | # include "interpret.h" 25 | # include "edcmd.h" 26 | # include "editor.h" 27 | 28 | static Editor *editors; /* editor table */ 29 | static Editor *flist; /* free list */ 30 | static int neditors; /* # of editors */ 31 | static char *tmpedfile; /* proto temporary file */ 32 | static char *outbuf; /* output buffer */ 33 | static Uint outbufsz; /* chars in output buffer */ 34 | static eindex newed; /* new editor in current task */ 35 | static bool recursion; /* recursion in editor command */ 36 | static bool internal; /* flag editor internal error */ 37 | 38 | /* 39 | * fake error handler 40 | */ 41 | static void ed_handler(Frame *f, LPCint depth) 42 | { 43 | /* 44 | * This function just exists to prevent the higher level error handler 45 | * from being called. 46 | */ 47 | UNREFERENCED_PARAMETER(f); 48 | UNREFERENCED_PARAMETER(depth); 49 | } 50 | 51 | class EditorErrorContext : public ErrorContextImpl { 52 | public: 53 | /* 54 | * handle an editor internal error 55 | */ 56 | virtual void error(const char *format, ...) { 57 | char ebuf[2 * STRINGSZ]; 58 | va_list args; 59 | 60 | if (format != (char *) NULL) { 61 | internal = TRUE; 62 | EC->push((ErrorContext::Handler) ed_handler); 63 | va_start(args, format); 64 | vsnprintf(ebuf, sizeof(ebuf), format, args); 65 | va_end(args); 66 | EC->error(ebuf); 67 | } else { 68 | EC->error((char *) NULL); 69 | } 70 | } 71 | 72 | /* 73 | * handle output from the editor 74 | */ 75 | virtual void message(const char *format, ...) { 76 | char buf[2 * MAX_LINE_SIZE + 15]; 77 | va_list args; 78 | Uint len; 79 | 80 | va_start(args, format); 81 | vsnprintf(buf, sizeof(buf), format, args); 82 | va_end(args); 83 | len = strlen(buf); 84 | if (outbufsz + len > USHRT_MAX) { 85 | EC->error("Editor output string too long"); 86 | } 87 | memcpy(outbuf + outbufsz, buf, len); 88 | outbufsz += len; 89 | } 90 | }; 91 | 92 | static EditorErrorContext EDEC; /* editor error context */ 93 | ErrorContext *EDC = &EDEC; 94 | 95 | /* 96 | * initialize editor handling 97 | */ 98 | void Editor::init(char *tmp, int num) 99 | { 100 | Editor *e, *f; 101 | 102 | tmpedfile = tmp; 103 | f = (Editor *) NULL; 104 | neditors = num; 105 | if (num != 0) { 106 | outbuf = ALLOC(char, USHRT_MAX + 1); 107 | editors = ALLOC(Editor, num); 108 | for (e = editors + num; num != 0; --num) { 109 | (--e)->ed = (CmdBuf *) NULL; 110 | e->next = f; 111 | f = e; 112 | } 113 | } 114 | flist = f; 115 | newed = EINDEX_MAX; 116 | } 117 | 118 | /* 119 | * terminate all editor sessions 120 | */ 121 | void Editor::finish() 122 | { 123 | int i; 124 | Editor *e; 125 | 126 | for (i = neditors, e = editors; i > 0; --i, e++) { 127 | delete e->ed; 128 | } 129 | } 130 | 131 | /* 132 | * allow new editor to be created 133 | */ 134 | void Editor::clear() 135 | { 136 | newed = EINDEX_MAX; 137 | } 138 | 139 | /* 140 | * check for recursion in editor commands 141 | */ 142 | void Editor::checkRecursion() 143 | { 144 | if (recursion) { 145 | EC->error("Recursion in editor command"); 146 | } 147 | } 148 | 149 | /* 150 | * start a new editor 151 | */ 152 | void Editor::create(Object *obj) 153 | { 154 | char tmp[STRINGSZ + 3]; 155 | Editor *e; 156 | 157 | checkRecursion(); 158 | if (EINDEX(newed) != EINDEX_MAX) { 159 | EC->error("Too many simultaneous editors started"); 160 | } 161 | e = flist; 162 | if (e == (Editor *) NULL) { 163 | EC->error("Too many editor instances"); 164 | } 165 | flist = e->next; 166 | obj->etabi = newed = e - editors; 167 | obj->flags |= O_EDITOR; 168 | 169 | snprintf(tmp, sizeof(tmp), "%s%05u", tmpedfile, EINDEX(obj->etabi)); 170 | MM->staticMode(); 171 | e->ed = new CmdBuf(tmp); 172 | MM->dynamicMode(); 173 | } 174 | 175 | /* 176 | * delete an editor instance 177 | */ 178 | void Editor::del(Object *obj) 179 | { 180 | Editor *e; 181 | 182 | checkRecursion(); 183 | e = &editors[EINDEX(obj->etabi)]; 184 | delete e->ed; 185 | if (obj->etabi == newed) { 186 | newed = EINDEX_MAX; 187 | } 188 | e->ed = (CmdBuf *) NULL; 189 | e->next = flist; 190 | flist = e; 191 | obj->flags &= ~O_EDITOR; 192 | } 193 | 194 | /* 195 | * handle an editor command 196 | */ 197 | String *Editor::command(Object *obj, char *cmd) 198 | { 199 | Editor *e; 200 | 201 | checkRecursion(); 202 | if (strchr(cmd, LF) != (char *) NULL) { 203 | EC->error("Newline in editor command"); 204 | } 205 | 206 | e = &editors[EINDEX(obj->etabi)]; 207 | outbufsz = 0; 208 | internal = FALSE; 209 | try { 210 | EC->push(); 211 | recursion = TRUE; 212 | if (e->ed->command(cmd)) { 213 | e->ed->edbuf.inact(); 214 | recursion = FALSE; 215 | } else { 216 | recursion = FALSE; 217 | del(obj); 218 | } 219 | EC->pop(); 220 | } catch (const char*) { 221 | e->ed->flags &= ~(CB_INSERT | CB_CHANGE); 222 | e->ed->edbuf.inact(); 223 | recursion = FALSE; 224 | if (!internal) { 225 | EC->error((char *) NULL); /* pass on error */ 226 | } 227 | EDC->message("%s\012", EC->exception()->text); /* LF */ 228 | EC->pop(); 229 | } 230 | 231 | if (outbufsz == 0) { 232 | return (String *) NULL; 233 | } 234 | return String::create(outbuf, outbufsz); 235 | } 236 | 237 | /* 238 | * return the editor status of an object 239 | */ 240 | const char *Editor::status(Object *obj) 241 | { 242 | if (editors[EINDEX(obj->etabi)].ed->flags & CB_INSERT) { 243 | return "insert"; 244 | } else { 245 | return "command"; 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/editor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2021 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class Editor { 21 | public: 22 | class CmdBuf *ed; /* editor instance */ 23 | Editor *next; /* next in free list */ 24 | 25 | static void init(char *tmp, int num); 26 | static void finish(); 27 | static void clear(); 28 | static void create(Object *obj); 29 | static void del(Object *obj); 30 | static String *command(Object *obj, char *cmd); 31 | static const char *status(Object *obj); 32 | 33 | private: 34 | static void checkRecursion(); 35 | }; 36 | 37 | extern ErrorContext *EDC; 38 | -------------------------------------------------------------------------------- /src/error.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2025 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # define INCLUDE_FILE_IO 21 | # include "dgd.h" 22 | # include "str.h" 23 | # include "array.h" 24 | # include "object.h" 25 | # include "xfloat.h" 26 | # include "interpret.h" 27 | # include "data.h" 28 | # include "comm.h" 29 | 30 | 31 | static ErrorContextImpl ECI; /* global error context */ 32 | ErrorContext *EC = &ECI; 33 | 34 | ErrorContextImpl::ErrorFrame::ErrorFrame(Frame *frame, Handler handler) 35 | { 36 | f = frame; 37 | offset = frame->fp - frame->sp; 38 | atomic = frame->atomic; 39 | rlim = frame->rlim; 40 | 41 | this->handler = handler; 42 | next = (ErrorFrame *) NULL; 43 | } 44 | 45 | /* 46 | * push a new errorcontext 47 | */ 48 | jmp_buf *ErrorContextImpl::push(Handler handler) 49 | { 50 | ErrorFrame *e; 51 | jmp_buf *jump; 52 | 53 | if (eFrame == (ErrorFrame *) NULL) { 54 | MM->staticMode(); 55 | e = new ErrorFrame(cframe, handler); 56 | MM->dynamicMode(); 57 | jump = (jmp_buf *) NULL; 58 | } else { 59 | e = new ErrorFrame(cframe, handler); 60 | jump = &eFrame->env; 61 | } 62 | e->next = eFrame; 63 | eFrame = e; 64 | EC->env = &e->env; 65 | return jump; 66 | } 67 | 68 | /* 69 | * pop the current errorcontext 70 | */ 71 | void ErrorContextImpl::pop() 72 | { 73 | ErrorFrame *e; 74 | 75 | e = eFrame; 76 | # ifdef DEBUG 77 | if (e == (ErrorFrame *) NULL) { 78 | fatal("pop empty error stack"); 79 | } 80 | # endif 81 | cframe->atomic = e->atomic; 82 | eFrame = e->next; 83 | if (eFrame == (ErrorFrame *) NULL) { 84 | MM->staticMode(); 85 | delete e; 86 | MM->dynamicMode(); 87 | clearException(); 88 | EC->env = (jmp_buf *) NULL; 89 | } else { 90 | delete e; 91 | EC->env = &eFrame->env; 92 | } 93 | } 94 | 95 | /* 96 | * dummy handler for previously handled error 97 | */ 98 | static void dummyHandler(Frame *f, LPCint depth) 99 | { 100 | UNREFERENCED_PARAMETER(f); 101 | UNREFERENCED_PARAMETER(depth); 102 | } 103 | 104 | /* 105 | * set the current error string 106 | */ 107 | void ErrorContextImpl::setException(String *err) 108 | { 109 | if (this->err != (String *) NULL) { 110 | this->err->del(); 111 | } 112 | this->err = err; 113 | err->ref(); 114 | } 115 | 116 | /* 117 | * return the current error string 118 | */ 119 | String *ErrorContextImpl::exception() 120 | { 121 | return err; 122 | } 123 | 124 | /* 125 | * clear the error context string 126 | */ 127 | void ErrorContextImpl::clearException() 128 | { 129 | if (err != (String *) NULL) { 130 | err->del(); 131 | err = (String *) NULL; 132 | } 133 | } 134 | 135 | /* 136 | * handle error 137 | */ 138 | void ErrorContextImpl::error(String *str) 139 | { 140 | ErrorFrame *e; 141 | Handler handler; 142 | 143 | if (str != (String *) NULL) { 144 | setException(str); 145 | # ifdef DEBUG 146 | } else if (exception() == (String *) NULL) { 147 | fatal("no error string"); 148 | # endif 149 | } 150 | 151 | e = eFrame; 152 | 153 | if (atomicFrame == (ErrorFrame *) NULL || atomicFrame == e) { 154 | do { 155 | if (cframe->level != e->f->level) { 156 | if (atomicFrame == (ErrorFrame *) NULL) { 157 | cframe->atomicError(e->f->level); 158 | if (e != eFrame) { 159 | atomicFrame = e; 160 | break; /* handle rollback later */ 161 | } 162 | } 163 | 164 | cframe = cframe->restore(e->f->level); 165 | atomicFrame = (ErrorFrame *) NULL; 166 | } 167 | 168 | if (e->handler != (Handler) NULL) { 169 | handler = e->handler; 170 | e->handler = (Handler) dummyHandler; 171 | (*handler)(cframe, e->f->depth); 172 | break; 173 | } 174 | e = e->next; 175 | } while (e != (ErrorFrame *) NULL); 176 | } 177 | 178 | if (cframe->rlim != eFrame->rlim) { 179 | cframe->setRlimits(eFrame->rlim); 180 | } 181 | cframe = cframe->setSp(eFrame->f->fp - eFrame->offset); 182 | cframe->atomic = eFrame->atomic; 183 | cframe->rlim = eFrame->rlim; 184 | pop(); 185 | throw "LPC error"; 186 | } 187 | 188 | /* 189 | * cause an error 190 | */ 191 | void ErrorContextImpl::error(const char *format, ...) 192 | { 193 | va_list args; 194 | char ebuf[4 * STRINGSZ]; 195 | 196 | if (format != (char *) NULL) { 197 | va_start(args, format); 198 | vsnprintf(ebuf, sizeof(ebuf), format, args); 199 | error(String::create(ebuf, strlen(ebuf))); 200 | va_end(args); 201 | } else { 202 | error((String *) NULL); 203 | } 204 | } 205 | 206 | /* 207 | * a fatal error has been encountered; terminate the program and 208 | * dump a core if possible 209 | */ 210 | void ErrorContextImpl::fatal(const char *format, ...) 211 | { 212 | static short count; 213 | va_list args; 214 | char ebuf1[STRINGSZ], ebuf2[STRINGSZ + 14]; 215 | 216 | if (count++ == 0) { 217 | va_start(args, format); 218 | vsnprintf(ebuf1, sizeof(ebuf1), format, args); 219 | va_end(args); 220 | 221 | snprintf(ebuf2, sizeof(ebuf2), "Fatal error: %s\012", ebuf1); /* LF */ 222 | 223 | P_message(ebuf2); /* show message */ 224 | } 225 | std::abort(); 226 | } 227 | 228 | /* 229 | * issue a message on stderr 230 | */ 231 | void ErrorContextImpl::message(const char *format, ...) 232 | { 233 | va_list args; 234 | char ebuf[4 * STRINGSZ]; 235 | 236 | if (format == (char *) NULL) { 237 | # ifdef DEBUG 238 | if (exception() == (String *) NULL) { 239 | fatal("no error string"); 240 | } 241 | # endif 242 | if (exception()->len <= sizeof(ebuf) - 2) { 243 | snprintf(ebuf, sizeof(ebuf), "%s\012", exception()->text); 244 | } else { 245 | strcpy(ebuf, "[too long error string]\012"); 246 | } 247 | } else { 248 | va_start(args, format); 249 | vsnprintf(ebuf, sizeof(ebuf), format, args); 250 | va_end(args); 251 | } 252 | P_message(ebuf); /* show message */ 253 | } 254 | -------------------------------------------------------------------------------- /src/error.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2021 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class ErrorContext { 21 | public: 22 | typedef void (*Handler) (Frame*, LPCint); 23 | 24 | virtual jmp_buf *push(Handler handler = NULL) { 25 | UNREFERENCED_PARAMETER(handler); 26 | return (jmp_buf *) NULL; 27 | } 28 | virtual void pop() { } 29 | 30 | virtual void setException(String *err) { 31 | UNREFERENCED_PARAMETER(err); 32 | } 33 | virtual String *exception() { 34 | return (String *) NULL; 35 | } 36 | virtual void clearException() { } 37 | 38 | virtual void error(String *str) { 39 | UNREFERENCED_PARAMETER(str); 40 | } 41 | virtual void error(const char *format, ...) { 42 | va_list args; 43 | 44 | if (format != (char *) NULL) { 45 | va_start(args, format); 46 | vprintf(format, args); 47 | va_end(args); 48 | putchar('\n'); 49 | } 50 | throw "error"; 51 | } 52 | virtual void message(const char *format, ...) { 53 | va_list args; 54 | 55 | va_start(args, format); 56 | vprintf(format, args); 57 | va_end(args); 58 | } 59 | virtual void fatal(const char *format, ...) { 60 | va_list args; 61 | 62 | printf("Fatal error: "); 63 | va_start(args, format); 64 | vprintf(format, args); 65 | va_end(args); 66 | putchar('\n'); 67 | 68 | std::abort(); 69 | } 70 | 71 | jmp_buf *env; /* current error env */ 72 | }; 73 | 74 | class ErrorContextImpl : public ErrorContext { 75 | public: 76 | virtual jmp_buf *push(Handler handler); 77 | virtual void pop(); 78 | 79 | virtual void setException(String *err); 80 | virtual String *exception(); 81 | virtual void clearException(); 82 | 83 | virtual void error(String *str); 84 | virtual void error(const char *format, ...); 85 | virtual void message(const char *format, ...); 86 | virtual void fatal(const char *format, ...); 87 | 88 | private: 89 | class ErrorFrame : public Allocated { 90 | public: 91 | ErrorFrame(Frame *frame, Handler handler); 92 | 93 | Frame *f; /* frame context */ 94 | unsigned short offset; /* sp offset */ 95 | bool atomic; /* atomic status */ 96 | struct RLInfo *rlim; /* rlimits info */ 97 | Handler handler; /* error handler */ 98 | ErrorFrame *next; /* next in linked list */ 99 | jmp_buf env; /* extension error env */ 100 | }; 101 | 102 | ErrorFrame *eFrame; /* current error frame */ 103 | ErrorFrame *atomicFrame; /* first frame beyond atomic */ 104 | String *err; /* current error string */ 105 | }; 106 | 107 | extern ErrorContext *EC; 108 | -------------------------------------------------------------------------------- /src/ext.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 2020-2022 DGD Authors (see the commit log for details) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as 7 | * published by the Free Software Foundation, either version 3 of the 8 | * License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | class Ext { 20 | public: 21 | # ifndef NOFLOAT 22 | static double getFloat(const Float *flt); 23 | static bool checkFloat(double *d); 24 | static void constrainFloat(double *d); 25 | static void putFloat(Float *flt, double d); 26 | # ifdef LARGENUM 27 | static bool smallFloat(unsigned short *fhigh, Uint *flow, Float *flt); 28 | static void largeFloat(Float *flt, unsigned short fhigh, Uint flow); 29 | # endif 30 | # endif 31 | static void kfuns(char *protos, int size, int nkfun); 32 | static bool execute(const Frame *f, int func); 33 | static void release(uint64_t index, uint64_t instance); 34 | static bool load(char *module, char *config, void (**fdlist)(int*, int), 35 | void (**finish)(int)); 36 | static void finish(); 37 | 38 | private: 39 | static void spawn(void (*fdlist)(int*, int), void (*finish)(int)); 40 | static void cleanup(); 41 | static void jit(int (*init)(int, int, size_t, size_t, int, int, int, 42 | uint8_t*, size_t, void**), 43 | void (*finish)(), 44 | void (*compile)(uint64_t, uint64_t, int, uint8_t*, size_t, 45 | int, uint8_t*, size_t, uint8_t*, size_t), 46 | int (*execute)(uint64_t, uint64_t, int, int, void*), 47 | void (*release)(uint64_t, uint64_t), 48 | int (*functions)(uint64_t, uint64_t, int, void*)); 49 | static void compile(const Frame *f, Control *ctrl); 50 | }; 51 | 52 | Value *ext_value_temp(Dataspace *data); 53 | -------------------------------------------------------------------------------- /src/hash.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "dgd.h" 21 | # include "hash.h" 22 | 23 | /* 24 | * Generic string hash table. 25 | */ 26 | 27 | static unsigned char tab[256] = { 28 | 0001, 0127, 0061, 0014, 0260, 0262, 0146, 0246, 29 | 0171, 0301, 0006, 0124, 0371, 0346, 0054, 0243, 30 | 0016, 0305, 0325, 0265, 0241, 0125, 0332, 0120, 31 | 0100, 0357, 0030, 0342, 0354, 0216, 0046, 0310, 32 | 0156, 0261, 0150, 0147, 0215, 0375, 0377, 0062, 33 | 0115, 0145, 0121, 0022, 0055, 0140, 0037, 0336, 34 | 0031, 0153, 0276, 0106, 0126, 0355, 0360, 0042, 35 | 0110, 0362, 0024, 0326, 0364, 0343, 0225, 0353, 36 | 0141, 0352, 0071, 0026, 0074, 0372, 0122, 0257, 37 | 0320, 0005, 0177, 0307, 0157, 0076, 0207, 0370, 38 | 0256, 0251, 0323, 0072, 0102, 0232, 0152, 0303, 39 | 0365, 0253, 0021, 0273, 0266, 0263, 0000, 0363, 40 | 0204, 0070, 0224, 0113, 0200, 0205, 0236, 0144, 41 | 0202, 0176, 0133, 0015, 0231, 0366, 0330, 0333, 42 | 0167, 0104, 0337, 0116, 0123, 0130, 0311, 0143, 43 | 0172, 0013, 0134, 0040, 0210, 0162, 0064, 0012, 44 | 0212, 0036, 0060, 0267, 0234, 0043, 0075, 0032, 45 | 0217, 0112, 0373, 0136, 0201, 0242, 0077, 0230, 46 | 0252, 0007, 0163, 0247, 0361, 0316, 0003, 0226, 47 | 0067, 0073, 0227, 0334, 0132, 0065, 0027, 0203, 48 | 0175, 0255, 0017, 0356, 0117, 0137, 0131, 0020, 49 | 0151, 0211, 0341, 0340, 0331, 0240, 0045, 0173, 50 | 0166, 0111, 0002, 0235, 0056, 0164, 0011, 0221, 51 | 0206, 0344, 0317, 0324, 0312, 0327, 0105, 0345, 52 | 0033, 0274, 0103, 0174, 0250, 0374, 0052, 0004, 53 | 0035, 0154, 0025, 0367, 0023, 0315, 0047, 0313, 54 | 0351, 0050, 0272, 0223, 0306, 0300, 0233, 0041, 55 | 0244, 0277, 0142, 0314, 0245, 0264, 0165, 0114, 56 | 0214, 0044, 0322, 0254, 0051, 0066, 0237, 0010, 57 | 0271, 0350, 0161, 0304, 0347, 0057, 0222, 0170, 58 | 0063, 0101, 0034, 0220, 0376, 0335, 0135, 0275, 59 | 0302, 0213, 0160, 0053, 0107, 0155, 0270, 0321, 60 | }; 61 | 62 | /* 63 | * hash a single character using lookup table 64 | * Based on Peter K. Pearson's article in CACM 33-6, pp 677. 65 | */ 66 | unsigned char HashImpl::hashchar(unsigned char c) 67 | { 68 | return tab[c]; 69 | } 70 | 71 | static HashImpl HMI; 72 | Hash *HM = &HMI; 73 | -------------------------------------------------------------------------------- /src/hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # ifndef H_HASH 21 | # define H_HASH 22 | 23 | extern class Hash *HM; 24 | 25 | class Hash { 26 | public: 27 | struct Entry { 28 | Entry *next; /* next entry in hash table */ 29 | const char *name; /* string to use in hashing */ 30 | }; 31 | 32 | class Hashtab : public Allocated { 33 | public: 34 | /* 35 | * create a new hashtable of size "size", where "maxlen" characters 36 | * of each string are significant 37 | */ 38 | Hashtab(unsigned int size, unsigned int maxlen, bool mem) : 39 | size(size), maxlen(maxlen), mem(mem) { 40 | table = ALLOC(Entry*, size); 41 | memset(table, '\0', size * sizeof(Entry*)); 42 | } 43 | 44 | /* 45 | * delete a hash table 46 | */ 47 | virtual ~Hashtab() { 48 | FREE(table); 49 | } 50 | 51 | /* 52 | * lookup a name in a hashtable, return the address of the entry 53 | * or &NULL if none found 54 | */ 55 | Entry **lookup(const char *name, bool move) { 56 | Entry **first, **e, *next; 57 | 58 | if (mem) { 59 | first = e = &(table[HM->hashmem(name, maxlen) % size]); 60 | while (*e != (Entry *) NULL) { 61 | if (memcmp((*e)->name, name, maxlen) == 0) { 62 | if (move && e != first) { 63 | /* move to first position */ 64 | next = (*e)->next; 65 | (*e)->next = *first; 66 | *first = *e; 67 | *e = next; 68 | return first; 69 | } 70 | break; 71 | } 72 | e = &((*e)->next); 73 | } 74 | } else { 75 | first = e = &(table[HM->hashstr(name, maxlen) % size]); 76 | while (*e != (Entry *) NULL) { 77 | if (strcmp((*e)->name, name) == 0) { 78 | if (move && e != first) { 79 | /* move to first position */ 80 | next = (*e)->next; 81 | (*e)->next = *first; 82 | *first = *e; 83 | *e = next; 84 | return first; 85 | } 86 | break; 87 | } 88 | e = &((*e)->next); 89 | } 90 | } 91 | return e; 92 | } 93 | 94 | Uint size; /* size of hash table */ 95 | Entry **table; /* hash table entries */ 96 | 97 | private: 98 | unsigned short maxlen; /* max length of string to be used in hashing */ 99 | bool mem; /* \0-terminated string or raw memory? */ 100 | }; 101 | 102 | /* 103 | * hashtable factory 104 | */ 105 | virtual Hashtab *create(unsigned int size, unsigned int maxlen, bool mem) { 106 | return new Hashtab(size, maxlen, mem); 107 | } 108 | 109 | virtual unsigned char hashchar(unsigned char c) { 110 | return c; 111 | } 112 | 113 | /* 114 | * hash string 115 | */ 116 | virtual unsigned short hashstr(const char *str, unsigned int len) { 117 | unsigned char h, l; 118 | 119 | h = l = 0; 120 | while (*str != '\0' && len > 0) { 121 | h = l; 122 | l = hashchar(l ^ (unsigned char) *str++); 123 | --len; 124 | } 125 | return (unsigned short) ((h << 8) | l); 126 | } 127 | 128 | /* 129 | * hash memory 130 | */ 131 | virtual unsigned short hashmem(const char *mem, unsigned int len) { 132 | unsigned char h, l; 133 | 134 | h = l = 0; 135 | while (len > 0) { 136 | h = l; 137 | l = hashchar(l ^ (unsigned char) *mem++); 138 | --len; 139 | } 140 | return (unsigned short) ((h << 8) | l); 141 | } 142 | }; 143 | 144 | class HashImpl : public Hash { 145 | public: 146 | virtual unsigned char hashchar(unsigned char c); 147 | }; 148 | 149 | # endif /* H_HASH */ 150 | -------------------------------------------------------------------------------- /src/host/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of DGD, https://github.com/dworkin/dgd 3 | # Copyright (C) 1993-2010 Dworkin B.V. 4 | # Copyright (C) 2010-2025 DGD Authors (see the commit log for details) 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as 8 | # published by the Free Software Foundation, either version 3 of the 9 | # License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | # 19 | CXXFLAGS=-I. -I.. $(CCFLAGS) 20 | 21 | ifeq ($(HOST),LINUX) 22 | SYSV_STYLE=1 23 | endif 24 | ifeq ($(HOST),SOLARIS) 25 | SYSV_STYLE=1 26 | endif 27 | ifeq ($(HOST),DECALPHA) 28 | SYSV_STYLE=1 29 | endif 30 | ifeq ($(HOST),GENERIC_SYSV) 31 | SYSV_STYLE=1 32 | endif 33 | 34 | SRC= local.cpp dirent.cpp dload.cpp time.cpp connect.cpp 35 | OBJ= local.o dirent.o dload.o time.o connect.o crypt.o asn.o 36 | ifdef SIMFLOAT 37 | OBJ+=simfloat.o 38 | else 39 | OBJ+=hostfloat.o 40 | endif 41 | ifdef SYSV_STYLE 42 | SRC+=lrand48.cpp 43 | OBJ+=lrand48.o 44 | else 45 | SRC+=random.cpp 46 | OBJ+=random.o 47 | endif 48 | 49 | all: 50 | @echo Please run make from the src directory. 51 | 52 | dgd: $(OBJ) 53 | @for i in $(OBJ); do echo host/$$i; done > dgd 54 | 55 | clean: 56 | rm -f dgd $(SRC) $(OBJ) 57 | 58 | 59 | local.cpp: unix/local.cpp 60 | cp unix/$@ $@ 61 | 62 | random.cpp: unix/random.cpp 63 | cp unix/$@ $@ 64 | 65 | lrand48.cpp: unix/lrand48.cpp 66 | cp unix/$@ $@ 67 | 68 | dirent.cpp: unix/dirent.cpp 69 | cp unix/$@ $@ 70 | 71 | dload.cpp: unix/dload.cpp 72 | cp unix/$@ $@ 73 | 74 | time.cpp: unix/time.cpp 75 | cp unix/$@ $@ 76 | 77 | connect.cpp: unix/connect.cpp 78 | cp unix/$@ $@ 79 | 80 | $(OBJ): ../dgd.h ../host.h ../config.h ../alloc.h ../error.h 81 | connect.o: ../hash.h ../comm.h 82 | simfloat.o hostfloat.o crypt.o asn.o: ../xfloat.h 83 | hostfloat.o: ../ext.h 84 | crypt.o asn.o: ../str.h ../array.h ../object.h ../hash.h ../swap.h 85 | crypt.o asn.o: ../interpret.h ../data.h 86 | asn.o: ../asn.h 87 | -------------------------------------------------------------------------------- /src/host/telnet.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | /* 21 | * Definitions for the TELNET protocol. 22 | */ 23 | 24 | # define IAC 255 /* interpret as command */ 25 | # define DONT 254 /* don't */ 26 | # define DO 253 /* do */ 27 | # define WONT 252 /* won't */ 28 | # define WILL 251 /* will */ 29 | # define SB 250 /* begin subnegotiation */ 30 | # define GA 249 /* go ahead */ 31 | # define AYT 246 /* are you there */ 32 | # define IP 244 /* interrupt process */ 33 | # define BREAK 243 /* break */ 34 | # define SE 240 /* end subnegotiation */ 35 | 36 | /* options */ 37 | # define TELOPT_ECHO 1 /* echo */ 38 | # define TELOPT_SGA 3 /* suppress go ahead */ 39 | # define TELOPT_TM 6 /* timing mark */ 40 | -------------------------------------------------------------------------------- /src/host/unix/direct.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2020 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "dgd.h" 21 | # include 22 | 23 | static DIR *d; 24 | 25 | /* 26 | * open a directory 27 | */ 28 | bool P_opendir(const char *dir) 29 | { 30 | d = opendir(dir); 31 | return (d != (DIR *) NULL); 32 | } 33 | 34 | /* 35 | * read a directory, skipping . and .. 36 | */ 37 | char *P_readdir() 38 | { 39 | struct direct *de; 40 | 41 | do { 42 | de = readdir(d); 43 | if (de == (struct direct *) NULL) { 44 | return (char *) NULL; 45 | } 46 | } while (de->d_name[0] == '.' && (de->d_name[1] == '\0' || 47 | (de->d_name[1] == '.' && de->d_name[2] == '\0'))); 48 | return de->d_name; 49 | } 50 | 51 | /* 52 | * close a directory 53 | */ 54 | void P_closedir() 55 | { 56 | closedir(d); 57 | } 58 | -------------------------------------------------------------------------------- /src/host/unix/dirent.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2020 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "dgd.h" 21 | # include 22 | 23 | static DIR *d; 24 | 25 | /* 26 | * open a directory 27 | */ 28 | bool P_opendir(const char *dir) 29 | { 30 | d = opendir(dir); 31 | return (d != (DIR *) NULL); 32 | } 33 | 34 | /* 35 | * read a directory, skipping . and .. 36 | */ 37 | char *P_readdir() 38 | { 39 | struct dirent *de; 40 | 41 | do { 42 | de = readdir(d); 43 | if (de == (struct dirent *) NULL) { 44 | return (char *) NULL; 45 | } 46 | } while (de->d_name[0] == '.' && (de->d_name[1] == '\0' || 47 | (de->d_name[1] == '.' && de->d_name[2] == '\0'))); 48 | return de->d_name; 49 | } 50 | 51 | /* 52 | * close a directory 53 | */ 54 | void P_closedir() 55 | { 56 | closedir(d); 57 | } 58 | -------------------------------------------------------------------------------- /src/host/unix/dload.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "dgd.h" 21 | # include 22 | # ifdef SOLARIS 23 | # include 24 | # endif 25 | 26 | voidf *P_dload(char *module, const char *symbol) 27 | { 28 | void *h; 29 | 30 | h = dlopen(module, RTLD_NOW | RTLD_LOCAL); 31 | if (h == (void *) NULL) { 32 | return (voidf *) NULL; 33 | } 34 | return (voidf *) dlsym(h, symbol); 35 | } 36 | -------------------------------------------------------------------------------- /src/host/unix/local.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2020 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "dgd.h" 21 | # include 22 | 23 | extern "C" { 24 | 25 | /* 26 | * catch SIGTERM 27 | */ 28 | static void term(int arg) 29 | { 30 | signal(SIGTERM, term); 31 | DGD::interrupt(); 32 | } 33 | 34 | } 35 | 36 | /* 37 | * main program 38 | */ 39 | int main(int argc, char *argv[]) 40 | { 41 | long seed; 42 | unsigned short mtime; 43 | 44 | seed = P_mtime(&mtime); 45 | P_srandom(seed ^ ((long) mtime << 22)); 46 | signal(SIGPIPE, SIG_IGN); 47 | signal(SIGTERM, term); 48 | return DGD::main(argc, argv); 49 | } 50 | 51 | /* 52 | * show message 53 | */ 54 | void P_message(const char *mess) 55 | { 56 | fputs(mess, stderr); 57 | fflush(stderr); 58 | } 59 | -------------------------------------------------------------------------------- /src/host/unix/lrand48.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2020 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "dgd.h" 21 | 22 | extern void srand48 (long); 23 | extern long lrand48 (); 24 | 25 | /* 26 | * set the random seed 27 | */ 28 | void P_srandom(long s) 29 | { 30 | srand48(s); 31 | } 32 | 33 | /* 34 | * return a long random number 35 | */ 36 | long P_random() 37 | { 38 | return lrand48(); 39 | } 40 | -------------------------------------------------------------------------------- /src/host/unix/random.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2020 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "dgd.h" 21 | 22 | extern long random (); 23 | 24 | /* 25 | * set the random seed 26 | */ 27 | void P_srandom(long s) 28 | { 29 | srandom((int) s); 30 | } 31 | 32 | /* 33 | * return a long random number 34 | */ 35 | long P_random() 36 | { 37 | return random(); 38 | } 39 | -------------------------------------------------------------------------------- /src/host/unix/time.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "dgd.h" 21 | # include 22 | # include 23 | 24 | /* 25 | * return the current time 26 | */ 27 | Uint P_time() 28 | { 29 | return (Uint) time((time_t *) NULL); 30 | } 31 | 32 | /* 33 | * return the current time in milliseconds 34 | */ 35 | Uint P_mtime(unsigned short *milli) 36 | { 37 | struct timeval time; 38 | 39 | gettimeofday(&time, (struct timezone *) NULL); 40 | *milli = time.tv_usec / 1000; 41 | return (Uint) time.tv_sec; 42 | } 43 | 44 | /* 45 | * convert the given time to a string 46 | */ 47 | char *P_ctime(char *buf, Uint time) 48 | { 49 | int offset; 50 | time_t t; 51 | 52 | for (offset = 0; time >= 2147397248L; time -= 883612800L, offset += 28) ; 53 | t = time; 54 | memcpy(buf, ctime(&t), 26); 55 | if (offset != 0) { 56 | long year; 57 | 58 | year = std::strtol(buf + 20, (char **) NULL, 10) + offset; 59 | if (year > 2100 || 60 | (year == 2100 && (buf[4] != 'J' || buf[5] != 'a') && 61 | (buf[4] != 'F' || (buf[8] == '2' && buf[9] == '9')))) { 62 | /* 2100 is not a leap year */ 63 | t -= 378604800L; 64 | offset += 12; 65 | memcpy(buf, ctime(&t), 26); 66 | year = std::strtol(buf + 20, (char **) NULL, 10) + offset; 67 | } 68 | snprintf(buf + 20, 10, "%d\012", (int) year); 69 | } 70 | return buf; 71 | } 72 | -------------------------------------------------------------------------------- /src/host/win32/README.md: -------------------------------------------------------------------------------- 1 | To compile DGD on Windows you need to have Visual Studio 2010 or later. 2 | 3 | Look for it [here](https://visualstudio.microsoft.com). 4 | 5 | You also will need to install GnuWin's Bison. 6 | 7 | Look for it [here](https://gnuwin32.sourceforge.net/packages/bison.htm). 8 | 9 | The location of Bison.exe will need to be added to your path. It is recommended that you install it to a location with no spaces in the path since bison will not function correctly otherwise. If you do install to a location such as `c:\program files\gnuwin32`, then you must use the 8.3 form of the path `c:\progra~1\gnuwin32` instead. 10 | 11 | DGD for Windows is a console application and should be run just as it is on Unix-type operating systems. 12 | -------------------------------------------------------------------------------- /src/host/win32/dgd.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dgd", "dgd.vcxproj", "{D35360AA-B87E-4F90-AD31-183DAB9EFAF0}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Debug|x64 = Debug|x64 10 | Release|Win32 = Release|Win32 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {D35360AA-B87E-4F90-AD31-183DAB9EFAF0}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {D35360AA-B87E-4F90-AD31-183DAB9EFAF0}.Debug|Win32.Build.0 = Debug|Win32 16 | {D35360AA-B87E-4F90-AD31-183DAB9EFAF0}.Debug|x64.ActiveCfg = Debug|x64 17 | {D35360AA-B87E-4F90-AD31-183DAB9EFAF0}.Debug|x64.Build.0 = Debug|x64 18 | {D35360AA-B87E-4F90-AD31-183DAB9EFAF0}.Release|Win32.ActiveCfg = Release|Win32 19 | {D35360AA-B87E-4F90-AD31-183DAB9EFAF0}.Release|Win32.Build.0 = Release|Win32 20 | {D35360AA-B87E-4F90-AD31-183DAB9EFAF0}.Release|x64.ActiveCfg = Release|x64 21 | {D35360AA-B87E-4F90-AD31-183DAB9EFAF0}.Release|x64.Build.0 = Release|x64 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /src/host/win32/dload.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2020 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include 21 | # include "dgd.h" 22 | 23 | /* 24 | * load module 25 | */ 26 | voidf *P_dload(char *module, const char *symbol) 27 | { 28 | HMODULE h; 29 | 30 | h = LoadLibrary(module); 31 | if (h == (void *) NULL) { 32 | return (voidf *) NULL; 33 | } 34 | return (voidf *) GetProcAddress(h, symbol); 35 | } 36 | -------------------------------------------------------------------------------- /src/host/win32/dosfile.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2020 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include 21 | # include 22 | # include 23 | # include 24 | # include 25 | # define INCLUDE_FILE_IO 26 | # include "dgd.h" 27 | 28 | /* 29 | * deal with a path that's already native 30 | */ 31 | char *path_native(char *to, const char *from) 32 | { 33 | to[0] = '/'; /* mark as native */ 34 | strncpy(to + 1, from, STRINGSZ - 1); 35 | to[STRINGSZ - 1] = '\0'; 36 | return to; 37 | } 38 | 39 | /* 40 | * translate a path into a native file name 41 | */ 42 | static char *path_file(char *buf, const char *path) 43 | { 44 | bool valid; 45 | 46 | if (path[0] == '/') { 47 | /* already native */ 48 | strcpy(buf, path + 1); 49 | } else if (strpbrk(path, ":\\") != (char *) NULL || 50 | strlen(path) >= _MAX_PATH) { 51 | return (char *) NULL; 52 | } else { 53 | strcpy(buf, path); 54 | valid = FALSE; 55 | for (char *p = buf; *p != '\0'; p++) { 56 | if (*p == '/') { 57 | if (!valid) { 58 | return (char *) NULL; 59 | } 60 | *p = '\\'; 61 | valid = FALSE; 62 | } else if (*p != '.') { 63 | valid = TRUE; 64 | } 65 | } 66 | if (!valid && strcmp(buf, ".") != 0) { 67 | return (char *) NULL; 68 | } 69 | } 70 | return buf; 71 | } 72 | 73 | /* 74 | * open a file 75 | */ 76 | int P_open(const char *file, int flags, int mode) 77 | { 78 | char buf[STRINGSZ]; 79 | 80 | if (path_file(buf, file) == (char *) NULL) { 81 | return -1; 82 | } 83 | return _open(buf, flags, mode); 84 | } 85 | 86 | /* 87 | * close a file 88 | */ 89 | int P_close(int fd) 90 | { 91 | return _close(fd); 92 | } 93 | 94 | /* 95 | * read from a file 96 | */ 97 | int P_read(int fd, char *buf, int nbytes) 98 | { 99 | return _read(fd, buf, nbytes); 100 | } 101 | 102 | /* 103 | * write to a file 104 | */ 105 | int P_write(int fd, const char *buf, int nbytes) 106 | { 107 | return _write(fd, buf, nbytes); 108 | } 109 | 110 | /* 111 | * seek on a file 112 | */ 113 | long P_lseek(int fd, long offset, int whence) 114 | { 115 | return _lseek(fd, offset, whence); 116 | } 117 | 118 | /* 119 | * get information about a file 120 | */ 121 | int P_stat(const char *path, struct stat *sb) 122 | { 123 | char buf[STRINGSZ]; 124 | 125 | if (path_file(buf, path) == (char *) NULL) { 126 | return -1; 127 | } 128 | return _stat(buf, (struct _stat *) sb); 129 | } 130 | 131 | /* 132 | * get information about an open file 133 | */ 134 | int P_fstat(int fd, struct stat *sb) 135 | { 136 | return _fstat(fd, (struct _stat *) sb); 137 | } 138 | 139 | /* 140 | * remove a file (but not a directory) 141 | */ 142 | int P_unlink(const char *path) 143 | { 144 | char buf[STRINGSZ]; 145 | 146 | if (path_file(buf, path) == (char *) NULL) { 147 | return -1; 148 | } 149 | 150 | return _unlink(buf); 151 | } 152 | 153 | /* 154 | * rename a file 155 | */ 156 | int P_rename(const char *from, const char *to) 157 | { 158 | char buf1[STRINGSZ], buf2[STRINGSZ]; 159 | 160 | if (path_file(buf1, from) == (char *) NULL || 161 | path_file(buf2, to) == (char *) NULL) { 162 | return -1; 163 | } 164 | return rename(buf1, buf2); /* has no underscore for some reason */ 165 | } 166 | 167 | /* 168 | * check access on a file 169 | */ 170 | int P_access(const char *path, int mode) 171 | { 172 | char buf[STRINGSZ]; 173 | 174 | if (path_file(buf, path) == (char *) NULL) { 175 | return -1; 176 | } 177 | return _access(buf, mode); 178 | } 179 | 180 | /* 181 | * create a directory 182 | */ 183 | int P_mkdir(const char *path, int mode) 184 | { 185 | char buf[STRINGSZ]; 186 | 187 | UNREFERENCED_PARAMETER(mode); 188 | 189 | if (path_file(buf, path) == (char *) NULL) { 190 | return -1; 191 | } 192 | 193 | return _mkdir(buf); 194 | } 195 | 196 | /* 197 | * remove an empty directory 198 | */ 199 | int P_rmdir(const char *path) 200 | { 201 | char buf[STRINGSZ]; 202 | 203 | if (path_file(buf, path) == (char *) NULL) { 204 | return -1; 205 | } 206 | 207 | return _rmdir(buf); 208 | } 209 | 210 | /* 211 | * change the current directory (and drive) 212 | */ 213 | int P_chdir(const char *dir) 214 | { 215 | char buf[STRINGSZ]; 216 | 217 | if (path_file(buf, dir) == (char *) NULL || _chdir(buf) < 0) { 218 | return -1; 219 | } 220 | if (buf[1] == ':' && _chdrive(toupper(buf[0]) - 'A' + 1) < 0) { 221 | return -1; 222 | } 223 | return 0; 224 | } 225 | 226 | static intptr_t d; 227 | static struct _finddata_t fdata; 228 | 229 | /* 230 | * open a directory 231 | */ 232 | bool P_opendir(const char *dir) 233 | { 234 | char path[_MAX_PATH + 2]; 235 | 236 | if (path_file(path, dir) == (char *) NULL) { 237 | return FALSE; 238 | } 239 | strcat(path, "\\*"); 240 | d = _findfirst(path, &fdata); 241 | return (d != -1); 242 | } 243 | 244 | /* 245 | * read a directory 246 | */ 247 | char *P_readdir() 248 | { 249 | static struct _finddata_t fd; 250 | 251 | do { 252 | if (d == -1) { 253 | return (char *) NULL; 254 | } 255 | fd = fdata; 256 | if (_findnext(d, &fdata) != 0) { 257 | _findclose(d); 258 | d = -1; 259 | } 260 | } while (fd.name[0] == '.' && 261 | (fd.name[1] == '\0' || 262 | (fd.name[1] == '.' && fd.name[2] == '\0'))); 263 | return fd.name; 264 | } 265 | 266 | /* 267 | * close a directory 268 | */ 269 | void P_closedir() 270 | { 271 | if (d != -1) { 272 | _findclose(d); 273 | } 274 | } 275 | 276 | /* 277 | * execute a program 278 | */ 279 | int P_execv(const char *path, char **argv) 280 | { 281 | UNREFERENCED_PARAMETER(path); 282 | UNREFERENCED_PARAMETER(argv); 283 | P_message("Hotbooting not supported on Windows\012"); /* LF */ 284 | return -1; 285 | } 286 | -------------------------------------------------------------------------------- /src/host/win32/local.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2020 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "dgd.h" 21 | 22 | /* 23 | * set random seed 24 | */ 25 | void P_srandom(long seed) 26 | { 27 | srand((unsigned int) seed); 28 | } 29 | 30 | /* 31 | * get random number 32 | */ 33 | long P_random() 34 | { 35 | return (long) (rand() ^ (rand() << 9) ^ (rand() << 16)); 36 | } 37 | -------------------------------------------------------------------------------- /src/host/win32/time.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include 21 | # include 22 | # include "dgd.h" 23 | 24 | # define UNIXBIRTH 0x019db1ded53e8000 25 | 26 | /* 27 | * return the time in seconds since Jan 1, 1970 28 | */ 29 | Uint P_time() 30 | { 31 | FILETIME ft; 32 | SYSTEMTIME st; 33 | __int64 time; 34 | 35 | GetSystemTime(&st); 36 | SystemTimeToFileTime(&st, &ft); 37 | time = ((__int64) ft.dwHighDateTime << 32) + ft.dwLowDateTime - UNIXBIRTH; 38 | return (Uint) (time / 10000000); 39 | } 40 | 41 | /* 42 | * return the time in seconds since Jan 1, 1970 in milliseconds 43 | */ 44 | Uint P_mtime(unsigned short *milli) 45 | { 46 | FILETIME ft; 47 | SYSTEMTIME st; 48 | __int64 time; 49 | 50 | GetSystemTime(&st); 51 | SystemTimeToFileTime(&st, &ft); 52 | time = ((__int64) ft.dwHighDateTime << 32) + ft.dwLowDateTime - UNIXBIRTH; 53 | *milli = (unsigned short) ((time % 10000000) / 10000); 54 | return (Uint) (time / 10000000); 55 | } 56 | 57 | /* 58 | * return time as string 59 | */ 60 | char *P_ctime(char *buf, Uint time) 61 | { 62 | int offset; 63 | time_t t; 64 | 65 | for (offset = 0; time > 2147397248; time -= 883612800, offset += 28) ; 66 | t = time; 67 | memcpy(buf, ctime(&t), 26); 68 | if (offset != 0) { 69 | long year; 70 | 71 | year = strtol(buf + 20, (char **) NULL, 10) + offset; 72 | if (year > 2100 || 73 | (year == 2100 && (buf[4] != 'J' || buf[5] != 'a') && 74 | (buf[4] != 'F' || (buf[8] == '2' && buf[9] == '9')))) { 75 | /* 2100 is not a leap year */ 76 | t -= 378604800; 77 | offset += 12; 78 | memcpy(buf, ctime(&t), 26); 79 | year = strtol(buf + 20, (char **) NULL, 10) + offset; 80 | } 81 | snprintf(buf + 20, 10, "%d\012", (int) year); 82 | } 83 | if (buf[8] == '0') { 84 | buf[8] = ' '; /* MSDEV ctime weirdness */ 85 | } 86 | return buf; 87 | } 88 | -------------------------------------------------------------------------------- /src/host/win32/windgd.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2020 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | #include "dgd.h" 22 | 23 | extern void conn_intr(); 24 | 25 | BOOL WINAPI handler(DWORD type) 26 | { 27 | UNREFERENCED_PARAMETER(type); 28 | DGD::interrupt(); 29 | conn_intr(); 30 | return TRUE; 31 | } 32 | 33 | int main(int argc, char **argv) 34 | { 35 | long seed; 36 | unsigned short mtime; 37 | 38 | seed = P_mtime(&mtime); 39 | P_srandom(seed ^ ((long) mtime << 22)); 40 | SetConsoleCtrlHandler(handler, TRUE); 41 | return DGD::main(argc, argv); 42 | } 43 | 44 | /* 45 | * show message 46 | */ 47 | void P_message(const char *mess) 48 | { 49 | fputs(mess, stdout); 50 | fflush(stdout); 51 | } 52 | -------------------------------------------------------------------------------- /src/kfun/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of DGD, https://github.com/dworkin/dgd 3 | # Copyright (C) 1993-2010 Dworkin B.V. 4 | # Copyright (C) 2010-2021 DGD Authors (see the commit log for details) 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as 8 | # published by the Free Software Foundation, either version 3 of the 9 | # License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | # 19 | CXXFLAGS=-I. -I.. -I../comp -I../parser $(CCFLAGS) 20 | 21 | SRC= builtin.cpp std.cpp file.cpp math.cpp extra.cpp 22 | OBJ= builtin.o std.o file.o math.o extra.o 23 | 24 | all: 25 | @echo Please run make from the src directory. 26 | 27 | dgd: table.o $(OBJ) 28 | @for i in table.o $(OBJ); do echo kfun/$$i; done > dgd 29 | 30 | clean: 31 | rm -f dgd table.o $(OBJ) 32 | 33 | 34 | $(OBJ): ../dgd.h ../config.h ../host.h ../alloc.h ../error.h ../str.h ../array.h 35 | $(OBJ): ../object.h ../hash.h ../swap.h ../xfloat.h ../interpret.h ../data.h 36 | std.o file.o: ../path.h ../editor.h 37 | std.o: ../comm.h ../call_out.h 38 | extra.o: ../asn.h 39 | table.o: ../ext.h 40 | 41 | std.o: ../comp/node.h ../comp/control.h ../comp/compile.h 42 | table.o: ../comp/control.h 43 | 44 | extra.o: ../parser/parse.h 45 | 46 | $(OBJ): kfun.h table.h 47 | table.o: $(OBJ) 48 | -------------------------------------------------------------------------------- /src/kfun/kfun.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2021 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "dgd.h" 21 | # include "str.h" 22 | # include "array.h" 23 | # include "object.h" 24 | # include "xfloat.h" 25 | # include "control.h" 26 | # include "data.h" 27 | # include "interpret.h" 28 | # include "table.h" 29 | -------------------------------------------------------------------------------- /src/kfun/table.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2023 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | typedef void (*ExtFunc)(Frame *, int, Value *); 21 | struct ExtKFun { 22 | const char *name; /* added kfun name */ 23 | char *proto; /* simplified prototype */ 24 | ExtFunc func; /* function address */ 25 | }; 26 | 27 | class KFun { 28 | public: 29 | void argError(int n); 30 | void unary(Frame *f); 31 | void binary(Frame *f); 32 | void ternary(Frame *f); 33 | void compare(Frame *f); 34 | 35 | static void init(); 36 | static void clear(); 37 | static void add(const ExtKFun *kfadd, int n); 38 | static void jit(); 39 | static int find(KFun *kf, unsigned int l, unsigned int h, const char *name); 40 | static int kfunc(const char *name); 41 | static void reclaim(); 42 | static bool dump(int fd); 43 | static void restore(int fd); 44 | 45 | const char *name; /* function name */ 46 | char *proto; /* prototype */ 47 | int (*func)(Frame*, int, KFun*); /* function address */ 48 | ExtFunc ext; /* extension */ 49 | short version; /* version number */ 50 | bool lval; /* has lvalue params */ 51 | 52 | private: 53 | static int callgate(Frame *f, int nargs, KFun *kf); 54 | static char *prototype(char *proto, bool *lval); 55 | static KFun *replace(KFun *table, int from, int to, int *size, 56 | const char *name); 57 | static int cmp(cvoid *cv1, cvoid *cv2); 58 | }; 59 | 60 | extern KFun kftab[], kfenc[], kfdec[], kfhsh[]; /* kfun tables */ 61 | extern kfindex kfind[]; /* indirection table */ 62 | extern int nkfun, ne, nd, nh; /* # kfuns */ 63 | 64 | # define KFUN(kf) (kftab[kfind[kf]]) 65 | 66 | extern int kf_ckrangeft(Frame*, int, KFun*); 67 | extern int kf_ckrangef (Frame*, int, KFun*); 68 | extern int kf_ckranget (Frame*, int, KFun*); 69 | extern int kf_nil (Frame*, int, KFun*); 70 | extern int kf_unused (Frame*, int, KFun*); 71 | 72 | # define KF_ADD 0 73 | # define KF_ADD_INT 1 74 | # define KF_ADD1 2 75 | # define KF_ADD1_INT 3 76 | # define KF_AND 4 77 | # define KF_AND_INT 5 78 | # define KF_DIV 6 79 | # define KF_DIV_INT 7 80 | # define KF_EQ 8 81 | # define KF_EQ_INT 9 82 | # define KF_GE 10 83 | # define KF_GE_INT 11 84 | # define KF_GT 12 85 | # define KF_GT_INT 13 86 | # define KF_LE 14 87 | # define KF_LE_INT 15 88 | # define KF_LSHIFT 16 89 | # define KF_LSHIFT_INT 17 90 | # define KF_LT 18 91 | # define KF_LT_INT 19 92 | # define KF_MOD 20 93 | # define KF_MOD_INT 21 94 | # define KF_MULT 22 95 | # define KF_MULT_INT 23 96 | # define KF_NE 24 97 | # define KF_NE_INT 25 98 | # define KF_NEG 26 99 | # define KF_NEG_INT 27 100 | # define KF_NOT 28 101 | # define KF_NOT_INT 29 102 | # define KF_OR 30 103 | # define KF_OR_INT 31 104 | # define KF_RANGEFT 32 105 | # define KF_RANGEF 33 106 | # define KF_RANGET 34 107 | # define KF_RANGE 35 108 | # define KF_RSHIFT 36 109 | # define KF_RSHIFT_INT 37 110 | # define KF_SUB 38 111 | # define KF_SUB_INT 39 112 | # define KF_SUB1 40 113 | # define KF_SUB1_INT 41 114 | # define KF_TOFLOAT 42 115 | # define KF_TOINT 43 116 | # define KF_TST 44 117 | # define KF_TST_INT 45 118 | # define KF_UMIN 46 119 | # define KF_UMIN_INT 47 120 | # define KF_XOR 48 121 | # define KF_XOR_INT 49 122 | # define KF_TOSTRING 50 123 | # define KF_CKRANGEFT 51 124 | # define KF_CKRANGEF 52 125 | # define KF_CKRANGET 53 126 | # define KF_CALL_OTHER 54 127 | # define KF_STATUS_IDX 55 128 | # define KF_STATUSO_IDX 56 129 | # define KF_CALLTR_IDX 57 130 | # define KF_NIL 58 131 | # define KF_STATUS 59 132 | # define KF_CALL_TRACE 60 133 | # define KF_ADD_FLT 61 134 | # define KF_ADD_FLT_STR 62 135 | # define KF_ADD_INT_STR 63 136 | # define KF_ADD_STR 64 137 | # define KF_ADD_STR_FLT 65 138 | # define KF_ADD_STR_INT 66 139 | # define KF_ADD1_FLT 67 140 | # define KF_DIV_FLT 68 141 | # define KF_EQ_FLT 69 142 | # define KF_EQ_STR 70 143 | # define KF_GE_FLT 71 144 | # define KF_GE_STR 72 145 | # define KF_GT_FLT 73 146 | # define KF_GT_STR 74 147 | # define KF_LE_FLT 75 148 | # define KF_LE_STR 76 149 | # define KF_LT_FLT 77 150 | # define KF_LT_STR 78 151 | # define KF_MULT_FLT 79 152 | # define KF_NE_FLT 80 153 | # define KF_NE_STR 81 154 | # define KF_NOT_FLT 82 155 | # define KF_NOT_STR 83 156 | # define KF_SUB_FLT 84 157 | # define KF_SUB1_FLT 85 158 | # define KF_TST_FLT 86 159 | # define KF_TST_STR 87 160 | # define KF_UMIN_FLT 88 161 | # define KF_SUM 89 162 | # define KF_FABS 90 163 | # define KF_FLOOR 91 164 | # define KF_CEIL 92 165 | # define KF_FMOD 93 166 | # define KF_FREXP 94 167 | # define KF_LDEXP 95 168 | # define KF_MODF 96 169 | # define KF_EXP 97 170 | # define KF_LOG 98 171 | # define KF_LOG10 99 172 | # define KF_POW 100 173 | # define KF_SQRT 101 174 | # define KF_COS 102 175 | # define KF_SIN 103 176 | # define KF_TAN 104 177 | # define KF_ACOS 105 178 | # define KF_ASIN 106 179 | # define KF_ATAN 107 180 | # define KF_ATAN2 108 181 | # define KF_COSH 109 182 | # define KF_SINH 110 183 | # define KF_TANH 111 184 | # define KF_CALLTR_IDX_IDX 112 185 | # define KF_STRLEN 113 186 | # define KF_RANGEFT_STRING 114 187 | # define KF_RANGEF_STRING 115 188 | # define KF_RANGET_STRING 116 189 | 190 | # define KF_BUILTINS 117 191 | 192 | # define SUM_SIMPLE -2 193 | # define SUM_ALLOCATE_NIL -3 194 | # define SUM_ALLOCATE_INT -4 195 | # define SUM_ALLOCATE_FLT -5 196 | # define SUM_AGGREGATE -6 197 | 198 | extern void hash_md5_start (Uint*); 199 | extern void hash_md5_block (Uint*, char*); 200 | extern void hash_md5_end (char*, Uint*, char*, unsigned int, Uint); 201 | -------------------------------------------------------------------------------- /src/lex/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of DGD, https://github.com/dworkin/dgd 3 | # Copyright (C) 1993-2010 Dworkin B.V. 4 | # Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as 8 | # published by the Free Software Foundation, either version 3 of the 9 | # License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | # 19 | CXXFLAGS=-I. -I.. -I../comp $(CCFLAGS) 20 | 21 | SRC= macro.cpp ppstr.cpp token.cpp special.cpp ppcontrol.cpp 22 | OBJ= macro.o ppstr.o token.o special.o ppcontrol.o 23 | 24 | all: 25 | @echo Please run make from the src directory. 26 | 27 | dgd: $(OBJ) 28 | @for i in $(OBJ); do echo lex/$$i; done > dgd 29 | 30 | clean: 31 | rm -f dgd $(OBJ) 32 | 33 | lex: $(OBJ) lex.o 34 | $(LD) $(DEBUG) $(LDFLAGS) -o $@ $(OBJ) lex.o 35 | 36 | 37 | $(OBJ) lex.o : lex.h ../config.h ../host.h ../alloc.h ../xfloat.h 38 | macro.o special.o token.o ppcontrol.o lex.o: ../hash.h 39 | token.o ppcontrol.o lex.o: ../path.h 40 | 41 | $(OBJ) lex.o: ../comp/node.h ../comp/compile.h ../comp/parser.h 42 | 43 | $(OBJ) lex.o: lex.h 44 | macro.o special.o token.o ppcontrol.o: macro.h 45 | ppstr.o token.o ppcontrol.o: ppstr.h 46 | special.o token.o ppcontrol.o: special.h token.h 47 | token.o ppcontrol.o lex.o: ppcontrol.h 48 | -------------------------------------------------------------------------------- /src/lex/lex.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 2024 DGD Authors (see the commit log for details) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as 7 | * published by the Free Software Foundation, either version 3 of the 8 | * License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | # include "lex.h" 20 | # include "ppcontrol.h" 21 | # include "path.h" 22 | # include "hash.h" 23 | # include 24 | # include 25 | # include 26 | 27 | 28 | static Alloc LMM; 29 | Alloc *MM = &LMM; 30 | 31 | static ErrorContext LEC; 32 | ErrorContext *EC = &LEC; 33 | 34 | static Hash LHM; 35 | Hash *HM = &LHM; 36 | 37 | static Preproc LPP; 38 | Preproc *PP = &LPP; 39 | 40 | class LexPath : public Path { 41 | public: 42 | virtual char *include(char *buf, char *from, char *file) { 43 | if (!PP->include(Path::from(buf, from, file), (char *) NULL, 0)) { 44 | return (char *) NULL; 45 | } 46 | return buf; 47 | } 48 | }; 49 | 50 | static LexPath LPM; 51 | Path *PM = &LPM; 52 | 53 | const char *paths[] = { "/usr/include", (char *) NULL }; 54 | YYSTYPE yylval; 55 | static double flt; 56 | 57 | bool Float::atof(char **buf, Float *f) 58 | { 59 | errno = 0; 60 | flt = strtod(*buf, buf); 61 | return (errno == 0); 62 | } 63 | 64 | Uint P_time() 65 | { 66 | return (Uint) time((time_t *) NULL); 67 | } 68 | 69 | char *P_ctime(char *buf, Uint time) 70 | { 71 | time_t t; 72 | 73 | t = time; 74 | return ctime_r(&t, buf); 75 | } 76 | 77 | int main(int argc, char *argv[]) 78 | { 79 | char filename[1024], *nfilename; 80 | int line, nline, c; 81 | 82 | if (argc != 2) { 83 | fprintf(stderr, "Usage: %s file\n", argv[0]); 84 | return 2; 85 | } 86 | 87 | filename[0] = '\0'; 88 | line = 0; 89 | Preproc::init(argv[1], (char **) paths, (char *) NULL, 0, 0); 90 | while ((c=Preproc::gettok()) != EOF) { 91 | nfilename = Preproc::filename() + 1; 92 | nline = Preproc::line(); 93 | if (strcmp(filename, nfilename) != 0) { 94 | if (filename[0] != '\0') { 95 | printf("\n"); 96 | } 97 | strcpy(filename, nfilename); 98 | line = nline; 99 | printf("#line %d \"%s\"\n", line, filename); 100 | } else if (nline != line) { 101 | if (nline > line && nline - line <= 5) { 102 | while (line < nline) { 103 | printf("\n"); 104 | line++; 105 | } 106 | } else { 107 | line = nline; 108 | printf("\n#line %d\n", line); 109 | } 110 | } 111 | switch (c) { 112 | case STRING_CONST: 113 | printf(" \"%s\"", yytext); 114 | break; 115 | 116 | case INT_CONST: 117 | printf(" %lld", (long long) yylval.number); 118 | break; 119 | 120 | case FLOAT_CONST: 121 | printf(" %lg", flt); 122 | break; 123 | 124 | default: 125 | printf(" %s", yytext); 126 | break; 127 | } 128 | } 129 | printf("\n"); 130 | 131 | return 0; 132 | } 133 | -------------------------------------------------------------------------------- /src/lex/lex.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "dgd.h" 21 | # include "xfloat.h" 22 | # include "node.h" 23 | # include "compile.h" 24 | # include "parser.h" 25 | -------------------------------------------------------------------------------- /src/lex/macro.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2023 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "lex.h" 21 | # include "macro.h" 22 | 23 | /* 24 | * The macro handling routines. These use the hash table. 25 | */ 26 | 27 | # define MCHUNKSZ 32 28 | 29 | static class MacroChunk : public Chunk { 30 | public: 31 | /* 32 | * free strings when iterating through items 33 | */ 34 | virtual bool item(Macro *m) { 35 | if (m->name != (char *) NULL) { 36 | FREE(m->name); 37 | if (m->replace != (char *) NULL) { 38 | FREE(m->replace); 39 | } 40 | } 41 | return TRUE; 42 | } 43 | } mchunk; 44 | 45 | static Hash::Hashtab *mt; /* macro hash table */ 46 | 47 | /* 48 | * intiialize the macro table 49 | */ 50 | void Macro::init() 51 | { 52 | mt = HM->create(MACTABSZ, MACHASHSZ, FALSE); 53 | } 54 | 55 | /* 56 | * clear the macro table 57 | */ 58 | void Macro::clear() 59 | { 60 | if (mt != (Hash::Hashtab *) NULL) { 61 | delete mt; 62 | mt = (Hash::Hashtab *) NULL; 63 | 64 | mchunk.items(); 65 | mchunk.clean(); 66 | } 67 | } 68 | 69 | /* 70 | * constructor 71 | */ 72 | Macro::Macro(const char *name) 73 | { 74 | next = (Hash::Entry *) NULL; 75 | this->name = strcpy(ALLOC(char, strlen(name) + 1), name); 76 | replace = (char *) NULL; 77 | } 78 | 79 | /* 80 | * destructor 81 | */ 82 | Macro::~Macro() 83 | { 84 | FREE(name); 85 | name = (char *) NULL; 86 | if (replace != (char *) NULL) { 87 | FREE(replace); 88 | replace = (char *) NULL; 89 | } 90 | } 91 | 92 | /* 93 | * define a macro 94 | */ 95 | bool Macro::define(const char *name, const char *replace, int narg) 96 | { 97 | bool status; 98 | Hash::Entry **m; 99 | Macro *mac; 100 | 101 | status = TRUE; 102 | m = mt->lookup(name, FALSE); 103 | if ((Macro *) *m != (Macro *) NULL) { 104 | /* the macro already exists. */ 105 | mac = (Macro *) *m; 106 | if (mac->replace != (char *) NULL && 107 | (mac->narg != narg || strcmp(mac->replace, replace) != 0)) { 108 | status = FALSE; 109 | } 110 | } else { 111 | *m = mac = chunknew (mchunk) Macro(name); 112 | } 113 | /* fill in macro */ 114 | if (replace != (char *) NULL) { 115 | mac->replace = strcpy(REALLOC(mac->replace, char, 0, 116 | strlen(replace) + 1), 117 | replace); 118 | } else { 119 | mac->replace = (char *) NULL; 120 | } 121 | mac->narg = narg; 122 | 123 | return status; 124 | } 125 | 126 | /* 127 | * undefine a macro 128 | */ 129 | void Macro::undef(char *name) 130 | { 131 | Hash::Entry **m; 132 | Macro *mac; 133 | 134 | m = mt->lookup(name, FALSE); 135 | if ((Macro *) *m != (Macro *) NULL) { 136 | /* it really exists. */ 137 | mac = (Macro *) *m; 138 | *m = mac->next; 139 | delete mac; 140 | } 141 | } 142 | 143 | /* 144 | * lookup a macro definition in the macro table. Return NULL if 145 | * the macro is not found. 146 | */ 147 | Macro *Macro::lookup(char *name) 148 | { 149 | return (Macro *) *mt->lookup(name, TRUE); 150 | } 151 | -------------------------------------------------------------------------------- /src/lex/macro.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2023 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "hash.h" 21 | 22 | class Macro : public Hash::Entry, public ChunkAllocated { 23 | public: 24 | Macro(const char *name); 25 | virtual ~Macro(); 26 | 27 | static void init(); 28 | static void clear(); 29 | static bool define(const char *name, const char *replace, int narg); 30 | static void undef(char *name); 31 | static Macro *lookup(char *name); 32 | 33 | char *replace; /* replace text */ 34 | int narg; /* number of arguments */ 35 | }; 36 | 37 | # define MA_NARG 0x1f 38 | # define MA_NOEXPAND 0x20 39 | # define MA_STRING 0x40 40 | # define MA_TAG 0x80 41 | 42 | # define MAX_NARG 31 43 | 44 | # define MAX_REPL_SIZE (4 * MAX_LINE_SIZE) 45 | -------------------------------------------------------------------------------- /src/lex/ppcontrol.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class Preproc { 21 | public: 22 | bool init(char *file, char **id, char *buffer, unsigned int buflen, 23 | int level); 24 | void clear(); 25 | bool include(char *file, char *buffer, unsigned int buflen); 26 | void push(char *buffer, unsigned int buflen); 27 | char *filename(); 28 | unsigned short line(); 29 | int gettok(); 30 | 31 | virtual void error(const char *format, ...) { 32 | va_list args; 33 | char buf[4 * STRINGSZ]; /* file name + 2 * string + overhead */ 34 | 35 | snprintf(buf, sizeof(buf), "\"%s\", %u: ", filename() + 1, line()); 36 | va_start(args, format); 37 | vsnprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), format, args); 38 | va_end(args); 39 | fprintf(stderr, "%s\n", buf); 40 | } 41 | 42 | private: 43 | int wsgettok(); 44 | int mcgtok(); 45 | int wsmcgtok(); 46 | int expr_get(); 47 | long eval_expr(int priority); 48 | int pptokenz(char *key, unsigned int len); 49 | int tokenz(char *key, unsigned int len); 50 | void unexpected(int token, const char *wanted, const char *directive); 51 | void do_include(); 52 | int argnum(char **args, int narg, int token); 53 | void do_define(); 54 | }; 55 | 56 | extern Preproc *PP; 57 | 58 | extern char *yytext; 59 | extern int yyleng; 60 | extern LPCint yynumber; 61 | extern Float yyfloat; 62 | -------------------------------------------------------------------------------- /src/lex/ppstr.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2019 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "lex.h" 21 | # include "ppstr.h" 22 | 23 | /* 24 | * A string utility for the preprocessor. 25 | */ 26 | 27 | # define SCHUNKSZ 8 28 | 29 | static Chunk schunk; 30 | 31 | /* 32 | * finish string handling 33 | */ 34 | void Str::clear() 35 | { 36 | schunk.clean(); 37 | } 38 | 39 | /* 40 | * constructor 41 | */ 42 | Str::Str(char *buf, int sz) 43 | { 44 | buffer = buf; 45 | buffer[0] = '\0'; 46 | size = sz; 47 | len = 0; 48 | } 49 | 50 | /* 51 | * make a new string with length 0. 52 | */ 53 | Str *Str::create(char *buf, int sz) 54 | { 55 | return chunknew (schunk) Str(buf, sz); 56 | } 57 | 58 | /* 59 | * append a string. The length becomes -1 if the result is too long 60 | */ 61 | int Str::append(const char *s) 62 | { 63 | int l; 64 | 65 | if (len < 0 || len + (l = strlen(s)) >= size) { 66 | return len = -1; 67 | } 68 | strcpy(buffer + len, s); 69 | return len += l; 70 | } 71 | 72 | /* 73 | * append a char. The length becomes -1 if the result is too long 74 | */ 75 | int Str::append(int c) 76 | { 77 | if (len < 0 || c == '\0' || len + 1 >= size) { 78 | return len = -1; 79 | } 80 | buffer[len++] = c; 81 | buffer[len] = '\0'; 82 | return len; 83 | } 84 | -------------------------------------------------------------------------------- /src/lex/ppstr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2019 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class Str : public ChunkAllocated { 21 | public: 22 | int append(const char *s); 23 | int append(int c); 24 | 25 | static void clear(); 26 | static Str *create(char *buf, int sz); 27 | 28 | char *buffer; /* string buffer */ 29 | int len; /* lenth of string (-1 if illegal) */ 30 | 31 | private: 32 | Str(char *buf, int sz); 33 | 34 | int size; /* size of buffer */ 35 | }; 36 | -------------------------------------------------------------------------------- /src/lex/special.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2023 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "lex.h" 21 | # include "macro.h" 22 | # include "token.h" 23 | # include "special.h" 24 | 25 | /* 26 | * Predefined macro handling. 27 | */ 28 | 29 | static char datestr[14]; 30 | static char timestr[11]; 31 | 32 | /* 33 | * predefine macros 34 | */ 35 | void Special::define() 36 | { 37 | char buf[26]; 38 | 39 | Macro::define("__LINE__", (char *) NULL, -1); 40 | Macro::define("__FILE__", (char *) NULL, -1); 41 | Macro::define("__DATE__", (char *) NULL, -1); 42 | Macro::define("__TIME__", (char *) NULL, -1); 43 | 44 | P_ctime(buf, P_time()); 45 | snprintf(datestr, sizeof(datestr), "\"%.6s %.4s\"", buf + 4, buf + 20); 46 | snprintf(timestr, sizeof(timestr), "\"%.8s\"", buf + 11); 47 | } 48 | 49 | /* 50 | * return the expansion of a predefined macro 51 | */ 52 | char *Special::replace(const char *name) 53 | { 54 | static char buf[STRINGSZ + 3]; 55 | 56 | if (strcmp(name, "__LINE__") == 0) { 57 | snprintf(buf, sizeof(buf), " %u ", TokenBuf::line()); 58 | return buf; 59 | } else if (strcmp(name, "__FILE__") == 0) { 60 | snprintf(buf, sizeof(buf), "\"%s\"", TokenBuf::filename()); 61 | return buf; 62 | } else if (strcmp(name, "__DATE__") == 0) { 63 | return datestr; 64 | } else if (strcmp(name, "__TIME__") == 0) { 65 | return timestr; 66 | } 67 | return (char *) NULL; 68 | } 69 | -------------------------------------------------------------------------------- /src/lex/special.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2019 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class Special { 21 | public: 22 | static void define(); 23 | static char *replace(const char *name); 24 | }; 25 | -------------------------------------------------------------------------------- /src/lex/token.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class TokenBuf : public ChunkAllocated { 21 | public: 22 | static void init(); 23 | static void clear(); 24 | static void push(char *buffer, unsigned int buflen); 25 | static bool include(char *file, char *buffer, unsigned int buflen); 26 | static void endinclude(); 27 | static unsigned short line(); 28 | static char *filename(); 29 | static void setline(unsigned short line); 30 | static void setfilename(char *file); 31 | static void header(bool incl); 32 | static void setpp(int pp); 33 | static int gettok(); 34 | static void skiptonl(int ws); 35 | static int expand(Macro *mc); 36 | 37 | private: 38 | void pop(); 39 | 40 | static void push(Macro *mc, char *buffer, unsigned int buflen, bool eof); 41 | static int gc(); 42 | static void skip_comment(); 43 | static void skip_alt_comment(); 44 | static void comment(bool flag); 45 | static char *esc(char *p); 46 | static int string(char quote); 47 | 48 | char *buffer; /* token buffer */ 49 | char *p; /* token buffer pointer */ 50 | int inbuf; /* # chars in token buffer */ 51 | char ubuf[4]; /* unget buffer */ 52 | char *up; /* unget buffer pointer */ 53 | bool file; /* file buffer? */ 54 | bool eof; /* TRUE if empty(buffer) -> EOF */ 55 | unsigned short _line; /* line number */ 56 | int fd; /* file descriptor */ 57 | union { 58 | char *_filename; /* file name */ 59 | Macro *mc; /* macro this buffer is an expansion of */ 60 | }; 61 | TokenBuf *prev; /* previous token buffer */ 62 | TokenBuf *iprev; /* previous token ibuffer */ 63 | }; 64 | -------------------------------------------------------------------------------- /src/object.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "hash.h" 21 | # include "swap.h" 22 | 23 | # define OACC_READ 0x00 /* read access */ 24 | # define OACC_MODIFY 0x01 /* write access */ 25 | 26 | class Object : public Hash::Entry { 27 | public: 28 | Object *clone(); 29 | void lightWeight(); 30 | void upgrade(Control *ctrl, Frame *f); 31 | void upgraded(Object *tmpl); 32 | void del(Frame *f); 33 | 34 | const char *objName(char *name); 35 | Control *control(); 36 | Dataspace *dataspace(); 37 | 38 | static void init(unsigned int n, Uint interval); 39 | static void newPlane(); 40 | static void commitPlane(); 41 | static void discardPlane(); 42 | 43 | static Object *access(unsigned int index, int access); 44 | 45 | static Object *create(char *name, Control *ctrl); 46 | static const char *builtinName(LPCint type); 47 | static Object *find(char *name, int access); 48 | 49 | static bool space(); 50 | static void clean(); 51 | static uindex ocount(); 52 | static uindex dobjects(); 53 | static bool save(int fd, bool incr); 54 | static void restore(int fd, bool part); 55 | static bool copy(Uint time); 56 | 57 | static void swapout(); 58 | static void dumpState(bool incr); 59 | static void finish(bool boot); 60 | 61 | char flags; /* object status */ 62 | eindex etabi; /* index in external table */ 63 | uindex cref; /* # clone references (sometimes) */ 64 | uindex prev; /* previous in issue list */ 65 | uindex index; /* index in object table */ 66 | Uint count; /* object creation count */ 67 | Uint update; /* object update count */ 68 | union { 69 | Uint ref; /* ref count (if master object) */ 70 | Uint master; /* master (if clone) */ 71 | }; 72 | Control *ctrl; /* control block (master object only) */ 73 | Dataspace *data; /* dataspace block */ 74 | Sector cfirst; /* first sector of control block */ 75 | Sector dfirst; /* first sector of dataspace block */ 76 | 77 | private: 78 | void remove(Frame *f); 79 | void restoreObject(bool cactive, bool dactive); 80 | bool purgeUpgrades(); 81 | 82 | static Object *alloc(); 83 | static void sweep(uindex n); 84 | static Uint recount(uindex n); 85 | static void cleanUpgrades(); 86 | }; 87 | 88 | # define O_MASTER 0x01 89 | # define O_AUTO 0x02 90 | # define O_DRIVER 0x04 91 | # define O_TOUCHED 0x08 92 | # define O_USER 0x10 93 | # define O_EDITOR 0x20 94 | # define O_COMPILED 0x40 95 | # define O_LWOBJ 0x80 96 | 97 | # define O_SPECIAL 0x30 98 | 99 | # define OBJ_LAYOUT "xceuuuiiippdd" 100 | 101 | # define OBJ(i) (&objTable[i]) 102 | # define OBJR(i) ((BTST(ocmap, (i))) ? \ 103 | Object::access((i), OACC_READ) : OBJ((i))) 104 | # define OBJW(i) ((!obase) ? \ 105 | Object::access((i), OACC_MODIFY) : OBJ((i))) 106 | 107 | # define O_UPGRADING(o) ((o)->cref > (o)->ref) 108 | # define O_INHERITED(o) ((o)->ref - 1 != (o)->cref) 109 | # define O_HASDATA(o) ((o)->data != (Dataspace *) NULL || \ 110 | (o)->dfirst != SW_UNUSED) 111 | 112 | # define OBJ_NONE UINDEX_MAX 113 | 114 | extern Object *objTable; 115 | extern Uint *ocmap; 116 | extern bool obase, swap, dump, incr, stop, boot; 117 | extern Uint objDestrCount; 118 | 119 | 120 | # ifdef CLOSURES 121 | # define BUILTIN_FUNCTION 0 122 | # endif 123 | -------------------------------------------------------------------------------- /src/parser/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of DGD, https://github.com/dworkin/dgd 3 | # Copyright (C) 1993-2010 Dworkin B.V. 4 | # Copyright (C) 2010-2025 DGD Authors (see the commit log for details) 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as 8 | # published by the Free Software Foundation, either version 3 of the 9 | # License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | # 19 | CXXFLAGS=-I. -I.. $(CCFLAGS) 20 | 21 | SRC= grammar.cpp dfa.cpp srp.cpp parse.cpp 22 | OBJ= grammar.o dfa.o srp.o parse.o 23 | 24 | all: 25 | @echo Please run make from the src directory. 26 | 27 | dgd: $(OBJ) 28 | @for i in $(OBJ); do echo parser/$$i; done > dgd 29 | 30 | clean: 31 | rm -f dgd $(OBJ) 32 | 33 | 34 | $(OBJ): ../dgd.h ../config.h ../host.h ../alloc.h ../error.h 35 | grammar.o dfa.o: ../hash.h ../str.h 36 | parse.o: ../str.h ../array.h ../object.h ../xfloat.h ../hash.h ../swap.h 37 | parse.o: ../interpret.h ../data.h 38 | 39 | grammar.o parse.o: grammar.h 40 | dfa.o parse.o: dfa.h 41 | srp.o parse.o: srp.h 42 | parse.o: parse.h 43 | -------------------------------------------------------------------------------- /src/parser/dfa.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2023 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class Dfa : public Allocated { 21 | public: 22 | virtual ~Dfa(); 23 | 24 | bool save(char **str, Uint *len); 25 | short scan(String *str, ssizet *strlen, char **token, ssizet *len); 26 | 27 | static Dfa *create(char *source, char *grammar); 28 | static Dfa *load(char *source, char *grammar, char *str, Uint len); 29 | 30 | private: 31 | Dfa(char *source, char *grammar); 32 | 33 | void extend(class DfaState *state, unsigned short limit); 34 | void loadtmp(); 35 | void split(class Charset *iset, Charset *cset, Uint ncset); 36 | unsigned short newstate(DfaState *state, DfaState *newstate, Charset *ecset, 37 | Charset *cset); 38 | DfaState *expand(DfaState *state); 39 | 40 | char *source; /* source grammar */ 41 | char *grammar; /* reference grammar */ 42 | char *strings; /* offset of strings in grammar */ 43 | unsigned short nsstrings; /* # strings in source grammar */ 44 | short whitespace; /* whitespace rule or -1 */ 45 | short nomatch; /* nomatch rule or -1 */ 46 | 47 | bool modified; /* dfa modified */ 48 | bool allocated; /* dfa strings allocated locally */ 49 | Uint dfasize; /* size of state machine */ 50 | Uint tmpssize; /* size of temporary state data */ 51 | Uint tmppsize; /* size of temporary posn data */ 52 | char *dfastr; /* saved dfa */ 53 | char *tmpstr; /* saved temporary data */ 54 | 55 | unsigned short nregexp; /* # regexps */ 56 | Uint nposn; /* number of unique positions */ 57 | class RpChunk *rpc; /* current rgxposn chunk */ 58 | Hash::Hashtab *posnhtab; /* position hash table */ 59 | 60 | unsigned short nstates; /* # states */ 61 | unsigned short nexpanded; /* # expanded states */ 62 | unsigned short endstates; /* # states with no valid transitions */ 63 | Uint sttsize; /* state table size */ 64 | Uint sthsize; /* size of state hash table */ 65 | DfaState *states; /* dfa states */ 66 | unsigned short *sthtab; /* state hash table */ 67 | 68 | unsigned short ecnum; /* number of equivalence classes */ 69 | char *ecsplit; /* equivalence class split history */ 70 | char *ecmembers; /* members per equivalence class */ 71 | Charset *ecset; /* equivalence class sets */ 72 | char eclass[256]; /* equivalence classes */ 73 | 74 | char zerotrans[2 * 256]; /* shared zero transitions */ 75 | }; 76 | 77 | # define DFA_EOS -1 78 | # define DFA_REJECT -2 79 | # define DFA_TOOBIG -3 80 | -------------------------------------------------------------------------------- /src/parser/grammar.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2020 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # define GRAM_VERSION 2 21 | 22 | class Grammar { 23 | public: 24 | static String *parse(String *gram); 25 | 26 | private: 27 | static String *create(class Rule *rgxlist, Rule *strlist, Rule *estrlist, 28 | Rule *prodlist, int nrgx, int nstr, int nestr, 29 | int nprod, long size); 30 | }; 31 | -------------------------------------------------------------------------------- /src/parser/parse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2023 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | struct SnList { 21 | class SnChunk *snc; /* snode chunk */ 22 | class SNode *first; /* first node in list */ 23 | SNode *last; /* last node in list */ 24 | }; 25 | 26 | class Parser : public Allocated { 27 | public: 28 | virtual ~Parser(); 29 | 30 | void save(); 31 | 32 | static Array *parse_string(Frame *f, String *source, String *str, 33 | LPCint maxalt); 34 | 35 | private: 36 | void reset(); 37 | void reduce(class PNode *pn, char *p); 38 | void shift(SNode *sn, short token, char *text, ssizet len); 39 | PNode *parse(String *str, bool *toobig); 40 | Int traverse(PNode *pn, PNode *next); 41 | 42 | static Parser *create(Frame *f, String *source, String *grammar); 43 | static void flatten(PNode *pn, PNode *next, Value *v); 44 | static Parser *load(Frame *f, Value *elts); 45 | 46 | Frame *frame; /* interpreter stack frame */ 47 | Dataspace *data; /* dataspace for current object */ 48 | 49 | String *source; /* grammar source */ 50 | String *grammar; /* preprocessed grammar */ 51 | char *fastr; /* DFA string */ 52 | char *lrstr; /* SRP string */ 53 | 54 | class Dfa *fa; /* (partial) DFA */ 55 | class Srp *lr; /* (partial) shift/reduce parser */ 56 | short ntoken; /* # of tokens (regexp + string) */ 57 | short nprod; /* # of nonterminals */ 58 | 59 | class PnChunk *pnc; /* pnode chunk */ 60 | 61 | unsigned short nstates; /* state table size */ 62 | struct PState *states; /* state table */ 63 | SnList list; /* snode list */ 64 | 65 | class StrPChunk *strc; /* string chunk */ 66 | class ArrPChunk *arrc; /* array chunk */ 67 | 68 | LPCint maxalt; /* max number of branches */ 69 | }; 70 | -------------------------------------------------------------------------------- /src/parser/srp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2021 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | 21 | class Srp : public Allocated { 22 | public: 23 | virtual ~Srp(); 24 | 25 | void loadtmp(); 26 | bool save(char **str, Uint *len); 27 | short reduce(unsigned int num, unsigned short *nredp, char **redp); 28 | short shift(unsigned int num, unsigned int token); 29 | short _goto(unsigned int num, unsigned int symb); 30 | 31 | static Srp *create(char *grammar); 32 | static Srp *load(char *grammar, char *str, Uint len); 33 | 34 | private: 35 | Srp(char *grammar); 36 | 37 | Int pack(unsigned short *check, unsigned short *from, unsigned short *to, 38 | unsigned short n); 39 | class SrpState *expand(SrpState *state); 40 | 41 | char *grammar; /* grammar */ 42 | unsigned short nsstring; /* # of source grammar strings */ 43 | unsigned short ntoken; /* # of tokens (regexp & string) */ 44 | unsigned short nprod; /* # of nonterminals */ 45 | 46 | Uint nred; /* # of reductions */ 47 | Uint nitem; /* # of items */ 48 | Uint srpsize; /* size of shift/reduce parser */ 49 | Uint tmpsize; /* size of temporary data */ 50 | bool modified; /* srp needs saving */ 51 | bool allocated; /* srp allocated */ 52 | char *srpstr; /* srp string */ 53 | char *tmpstr; /* tmp string */ 54 | 55 | unsigned short nstates; /* number of states */ 56 | unsigned short nexpanded; /* number of expanded states */ 57 | Uint sttsize; /* state table size */ 58 | Uint sthsize; /* state hash table size */ 59 | class SrpState *states; /* state array */ 60 | unsigned short *sthtab; /* state hash table */ 61 | 62 | class ItChunk *itc; /* item chunk */ 63 | 64 | Uint gap; /* first gap in packed mapping */ 65 | Uint spread; /* max spread in packed mapping */ 66 | Uint mapsize; /* packed mapping size */ 67 | char *data; /* packed shifts */ 68 | char *check; /* packed check for shift validity */ 69 | bool alloc; /* data and check allocated separately? */ 70 | 71 | class SlChunk *slc; /* shlink chunk */ 72 | Uint nshift; /* number of shifts (from/to pairs) */ 73 | Uint shtsize; /* shift table size */ 74 | Uint shhsize; /* shift hash table size */ 75 | char *shtab; /* shift (from/to) table */ 76 | class ShLink **shhtab; /* shift hash table */ 77 | }; 78 | -------------------------------------------------------------------------------- /src/path.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "dgd.h" 21 | # include "str.h" 22 | # include "array.h" 23 | # include "object.h" 24 | # include "xfloat.h" 25 | # include "data.h" 26 | # include "interpret.h" 27 | # include "path.h" 28 | # include "ppcontrol.h" 29 | # include "node.h" 30 | # include "compile.h" 31 | 32 | static PathImpl PMI; 33 | Path *PM = &PMI; 34 | 35 | /* 36 | * resolve an editor read file path 37 | */ 38 | char *PathImpl::edRead(char *buf, char *file) 39 | { 40 | Frame *f; 41 | 42 | f = cframe; 43 | if (OBJR(f->oindex)->flags & O_DRIVER) { 44 | return resolve(buf, file); 45 | } else { 46 | PUSH_STRVAL(f, String::create(file, strlen(file))); 47 | DGD::callDriver(f, "path_read", 1); 48 | if (f->sp->type != T_STRING) { 49 | (f->sp++)->del(); 50 | return (char *) NULL; 51 | } 52 | resolve(buf, f->sp->string->text); 53 | (f->sp++)->string->del(); 54 | return buf; 55 | } 56 | } 57 | 58 | /* 59 | * resolve an editor write file path 60 | */ 61 | char *PathImpl::edWrite(char *buf, char *file) 62 | { 63 | Frame *f; 64 | 65 | f = cframe; 66 | if (OBJR(f->oindex)->flags & O_DRIVER) { 67 | return resolve(buf, file); 68 | } else { 69 | PUSH_STRVAL(f, String::create(file, strlen(file))); 70 | DGD::callDriver(f, "path_write", 1); 71 | if (f->sp->type != T_STRING) { 72 | (f->sp++)->del(); 73 | return (char *) NULL; 74 | } 75 | resolve(buf, f->sp->string->text); 76 | (f->sp++)->string->del(); 77 | return buf; 78 | } 79 | } 80 | 81 | /* 82 | * attempt to include a path 83 | */ 84 | char *PathImpl::include(char *buf, char *from, char *file) 85 | { 86 | Frame *f; 87 | int i; 88 | Value *v; 89 | String *str; 90 | 91 | if (Compile::autodriver()) { 92 | if (PP->include(PathImpl::from(buf, from, file), (char *) NULL, 0)) { 93 | return buf; 94 | } 95 | } else { 96 | f = cframe; 97 | PUSH_STRVAL(f, String::create(from, strlen(from))); 98 | PUSH_STRVAL(f, String::create(file, strlen(file))); 99 | if (!DGD::callDriver(f, "include_file", 2)) { 100 | if (PP->include(PathImpl::from(buf, from, file), (char *) NULL, 0)) 101 | { 102 | return buf; 103 | } 104 | } else if (f->sp->type == T_STRING) { 105 | /* simple path */ 106 | resolve(buf, f->sp->string->text); 107 | if (PP->include(buf, (char *) NULL, 0)) { 108 | (f->sp++)->string->del(); 109 | return buf; 110 | } 111 | } else if (f->sp->type == T_ARRAY) { 112 | /* 113 | * Array of strings. Check that the array does indeed contain only 114 | * strings, then return it. 115 | */ 116 | i = f->sp->array->size; 117 | if (i != 0) { 118 | v = Dataspace::elts(f->sp->array); 119 | while ((v++)->type == T_STRING) { 120 | if (--i == 0) { 121 | PathImpl::from(buf, from, file); 122 | 123 | i = f->sp->array->size; 124 | str = (--v)->string; 125 | PP->include(buf, str->text, str->len); 126 | 127 | while (--i != 0) { 128 | str = (--v)->string; 129 | PP->push(str->text, str->len); 130 | } 131 | (f->sp++)->del(); 132 | 133 | /* return the untranslated path, as well */ 134 | return buf; 135 | } 136 | } 137 | } 138 | } 139 | 140 | (f->sp++)->del(); 141 | } 142 | 143 | return (char *) NULL; 144 | } 145 | -------------------------------------------------------------------------------- /src/path.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class Path { 21 | public: 22 | virtual char *resolve(char *buf, char *file) { 23 | char *p, *q, *d; 24 | 25 | strncpy(buf, file, STRINGSZ - 1); 26 | buf[STRINGSZ - 1] = '\0'; 27 | d = p = q = buf; 28 | for (;;) { 29 | if (*p == '/' || *p == '\0') { 30 | /* reached a directory separator */ 31 | if (q - 1 == d && d[0] == '.') { 32 | q = d; /* . */ 33 | } else if (q - 2 == d && d[0] == '.' && d[1] == '.') { 34 | /* .. */ 35 | q = d; 36 | if (q != buf) { 37 | for (--q; q != buf && *--q != '/'; ) ; 38 | } 39 | } 40 | if (q != buf) { 41 | if (q[-1] == '/') { 42 | --q; /* // or path/ */ 43 | } 44 | *q++ = *p; 45 | } 46 | d = q; 47 | if (*p == '\0') { 48 | break; 49 | } 50 | p++; 51 | } else { 52 | *q++ = *p++; 53 | } 54 | } 55 | 56 | if (q == buf) { 57 | /* "" -> "." */ 58 | *q++ = '.'; 59 | *q = '\0'; 60 | } 61 | return buf; 62 | } 63 | virtual char *string(char *buf, char *file, unsigned int len) { 64 | if (len >= STRINGSZ || strlen(file) != len) { 65 | return NULL; 66 | } 67 | return resolve(buf, file); 68 | } 69 | virtual char *from(char *buf, char *from, char *file) { 70 | char buf2[STRINGSZ]; 71 | 72 | if (file[0] != '/' && strlen(from) + strlen(file) < STRINGSZ - 4) { 73 | snprintf(buf2, sizeof(buf2), "%s/../%s", from, file); 74 | file = buf2; 75 | } 76 | return resolve(buf, file); 77 | } 78 | virtual char *edRead(char *buf, char *file) { 79 | return resolve(buf, file); 80 | } 81 | virtual char *edWrite(char *buf, char *file) { 82 | return resolve(buf, file); 83 | } 84 | virtual char *include(char *buf, char *from, char *file) { 85 | return Path::from(buf, from, file); 86 | } 87 | }; 88 | 89 | class PathImpl : public Path { 90 | public: 91 | virtual char *edRead(char *buf, char *file); 92 | virtual char *edWrite(char *buf, char *file); 93 | virtual char *include(char *buf, char *from, char *file); 94 | }; 95 | 96 | extern Path *PM; 97 | -------------------------------------------------------------------------------- /src/str.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2025 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # include "dgd.h" 21 | # include "str.h" 22 | # include "array.h" 23 | # include "object.h" 24 | # include "xfloat.h" 25 | # include "data.h" 26 | 27 | # define STR_CHUNK 128 28 | 29 | struct StrHash : public Hash::Entry, public ChunkAllocated { 30 | String *str; /* string entry */ 31 | Uint index; /* building index */ 32 | }; 33 | 34 | static Chunk schunk; 35 | static Chunk hchunk; 36 | 37 | static Hash::Hashtab *sht; /* string merge table */ 38 | 39 | 40 | String::String(const char *text, long len) 41 | { 42 | this->text = ALLOC(char, len + 1); 43 | if (text != (char *) NULL && len > 0) { 44 | memcpy(this->text, text, (unsigned int) len); 45 | } 46 | this->text[this->len = len] = '\0'; 47 | refCount = 0; 48 | primary = (StrRef *) NULL; 49 | } 50 | 51 | String::~String() 52 | { 53 | FREE(text); 54 | } 55 | 56 | /* 57 | * Create a new string. The text can be a NULL pointer, in which case it must 58 | * be filled in later. 59 | */ 60 | String *String::alloc(const char *text, long len) 61 | { 62 | return chunknew (schunk) String(text, len); 63 | } 64 | 65 | /* 66 | * create a new string with size check 67 | */ 68 | String *String::create(const char *text, LPCint len) 69 | { 70 | if (len > (LPCint) MAX_STRLEN) { 71 | EC->error("String too long"); 72 | } 73 | return alloc(text, len); 74 | } 75 | 76 | /* 77 | * Remove a reference from a string. If there are none left, the string is 78 | * removed. 79 | */ 80 | void String::del() 81 | { 82 | if (--refCount == 0) { 83 | delete this; 84 | } 85 | } 86 | 87 | /* 88 | * remove string chunks from memory 89 | */ 90 | void String::clean() 91 | { 92 | schunk.clean(); 93 | } 94 | 95 | /* 96 | * prepare string merge 97 | */ 98 | void String::merge() 99 | { 100 | sht = HM->create(STRMERGETABSZ, STRMERGEHASHSZ, FALSE); 101 | } 102 | 103 | /* 104 | * put a string in the string merge table 105 | */ 106 | Uint String::put(Uint n) 107 | { 108 | StrHash **h; 109 | 110 | h = (StrHash **) sht->lookup(text, FALSE); 111 | for (;;) { 112 | /* 113 | * The hasher doesn't handle \0 in strings, and so may not have 114 | * found the proper string. Follow the hash table chain until 115 | * the end is reached, or until a match is found using cmp(). 116 | */ 117 | if (*h == (StrHash *) NULL) { 118 | StrHash *s; 119 | 120 | /* 121 | * Not in the hash table. Make a new entry. 122 | */ 123 | s = *h = chunknew (hchunk) StrHash; 124 | s->next = (Hash::Entry *) NULL; 125 | s->name = text; 126 | s->str = this; 127 | s->index = n; 128 | 129 | return n; 130 | } else if (cmp((*h)->str) == 0) { 131 | /* already in the hash table */ 132 | return (*h)->index; 133 | } 134 | h = (StrHash **) &(*h)->next; 135 | } 136 | } 137 | 138 | /* 139 | * clear the string merge table 140 | */ 141 | void String::clear() 142 | { 143 | if (sht != (Hash::Hashtab *) NULL) { 144 | delete sht; 145 | 146 | hchunk.clean(); 147 | sht = (Hash::Hashtab *) NULL; 148 | } 149 | } 150 | 151 | 152 | /* 153 | * compare two strings 154 | */ 155 | int String::cmp(String *str) 156 | { 157 | if (this == str) { 158 | return 0; 159 | } else { 160 | ssizet length; 161 | char *p, *q; 162 | long cmplen; 163 | int cmp; 164 | 165 | cmplen = (long) len - str->len; 166 | if (cmplen > 0) { 167 | /* s1 longer */ 168 | cmplen = 1; 169 | length = str->len; 170 | } else { 171 | /* str longer or equally long */ 172 | if (cmplen < 0) { 173 | cmplen = -1; 174 | } 175 | length = len; 176 | } 177 | for (p = text, q = str->text; length > 0 && *p == *q; 178 | p++, q++, --length) 179 | ; 180 | cmp = UCHAR(*p) - UCHAR(*q); 181 | return (cmp != 0) ? cmp : cmplen; 182 | } 183 | } 184 | 185 | /* 186 | * add two strings 187 | */ 188 | String *String::add(String *str) 189 | { 190 | String *s; 191 | 192 | s = create((char *) NULL, (LPCint) len + str->len); 193 | memcpy(s->text, text, len); 194 | memcpy(s->text + len, str->text, str->len); 195 | 196 | return s; 197 | } 198 | 199 | /* 200 | * index a string 201 | */ 202 | ssizet String::index(LPCint l) 203 | { 204 | if (l < 0 || l >= (LPCint) len) { 205 | EC->error("String index out of range"); 206 | } 207 | 208 | return l; 209 | } 210 | 211 | /* 212 | * check a string subrange 213 | */ 214 | void String::checkRange(LPCint l1, LPCint l2) 215 | { 216 | if (l1 < 0 || l1 > l2 + 1 || l2 >= (LPCint) len) { 217 | EC->error("Invalid string range"); 218 | } 219 | } 220 | 221 | /* 222 | * return a subrange of a string 223 | */ 224 | String *String::range(LPCint l1, LPCint l2) 225 | { 226 | if (l1 < 0 || l1 > l2 + 1 || l2 >= (LPCint) len) { 227 | EC->error("Invalid string range"); 228 | } 229 | 230 | return create(text + l1, l2 - l1 + 1); 231 | } 232 | -------------------------------------------------------------------------------- /src/str.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2021 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class String : public ChunkAllocated { 21 | public: 22 | ~String(); 23 | void ref() { refCount++; } 24 | void del(); 25 | int cmp(String *str); 26 | String *add(String *str); 27 | ssizet index(LPCint idx); 28 | void checkRange(LPCint from, LPCint to); 29 | String *range(LPCint from, LPCint to); 30 | Uint put(Uint n); 31 | 32 | static String *alloc(const char *text, long length); 33 | static String *create(const char *text, LPCint length); 34 | static void clean(); 35 | static void merge(); 36 | static void clear(); 37 | 38 | struct StrRef *primary; /* primary reference */ 39 | Uint refCount; /* number of references */ 40 | ssizet len; /* string length */ 41 | char *text; /* string text */ 42 | 43 | private: 44 | String(const char *text, long length); 45 | }; 46 | -------------------------------------------------------------------------------- /src/swap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | class Swap { 21 | public: 22 | struct SwapSlot { /* swap slot header */ 23 | SwapSlot *prev; /* previous in swap slot list */ 24 | SwapSlot *next; /* next in swap slot list */ 25 | Sector sec; /* the sector that uses this slot */ 26 | Sector swap; /* the swap sector (if any) */ 27 | bool dirty; /* has the swap slot been written to? */ 28 | }; 29 | 30 | static void init(char *file, unsigned int total, unsigned int secsize); 31 | static void finish(); 32 | static bool write(int fd, void *buffer, size_t size); 33 | static void wipev(Sector *vec, unsigned int size); 34 | static void delv(Sector *vec, unsigned int size); 35 | static Sector alloc(Uint size, Sector nsectors, Sector **sectors); 36 | static void readv(char*, Sector*, Uint, Uint); 37 | static void writev(char*, Sector*, Uint, Uint); 38 | static void dreadv(char*, Sector*, Uint, Uint); 39 | static void conv(char*, Sector*, Uint, Uint); 40 | static void conv2(char*, Sector*, Uint, Uint); 41 | static Uint convert(char *m, Sector *vec, const char *layout, Uint n, 42 | Uint idx, void (*readv) (char*, Sector*, Uint, Uint)); 43 | static Uint compress(char *data, char *text, Uint size); 44 | static char *decompress(Sector *sectors, 45 | void (*readv) (char*, Sector*, Uint, Uint), 46 | Uint size, Uint offset, Uint *dsize); 47 | static Sector count(); 48 | static int save(char *snapshot, bool keep); 49 | static void save2(SnapshotInfo *header, int size, bool incr); 50 | static void restore(int fd, unsigned int secsize); 51 | static void restore2(int fd); 52 | 53 | private: 54 | static void create(); 55 | static Sector mapsize(unsigned int size); 56 | static void newv(Sector *vec, unsigned int size); 57 | static SwapSlot *load(Sector sec, bool restore, bool fill); 58 | }; 59 | -------------------------------------------------------------------------------- /src/version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2024 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # define VERSION "DGD 1.7.6" 21 | -------------------------------------------------------------------------------- /src/xfloat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of DGD, https://github.com/dworkin/dgd 3 | * Copyright (C) 1993-2010 Dworkin B.V. 4 | * Copyright (C) 2010-2022 DGD Authors (see the commit log for details) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | # ifdef LARGENUM 21 | 22 | # define FLOAT_BIAS 0x3fff 23 | # define FLOAT_SIGN 0x80000000L 24 | # define FLOAT_ONE 0x3fff0000L 25 | # define FLOAT_MONE 0xbfff0000L 26 | # define FLOAT_DIGITS 14 27 | # define FLOAT_LIMIT 100000000000000LL 28 | # define FLOAT_BUFFER LPCINT_BUFFER 29 | 30 | typedef Uint FloatHigh; 31 | typedef uint64_t FloatLow; 32 | 33 | # else 34 | 35 | # define FLOAT_BIAS 0x3ff 36 | # define FLOAT_SIGN 0x8000 37 | # define FLOAT_ONE 0x3ff0 38 | # define FLOAT_MONE 0xbff0 39 | # define FLOAT_DIGITS 9 40 | # define FLOAT_LIMIT 1000000000 41 | # define FLOAT_BUFFER 17 42 | 43 | typedef unsigned short FloatHigh; 44 | typedef Uint FloatLow; 45 | 46 | # endif 47 | 48 | class Float { 49 | public: 50 | static bool atof(char **buf, Float *f); 51 | static void itof(LPCint i, Float *f); 52 | 53 | void initZero() { 54 | high = 0; 55 | low = 0; 56 | } 57 | void initOne() { 58 | high = FLOAT_ONE; 59 | low = 0; 60 | } 61 | 62 | void ftoa(char *buffer); 63 | LPCint ftoi(); 64 | 65 | void abs() { 66 | high &= ~FLOAT_SIGN; 67 | } 68 | void negate() { 69 | high ^= FLOAT_SIGN; 70 | } 71 | bool negative() { 72 | return !!(high & FLOAT_SIGN); 73 | } 74 | 75 | void add(Float &f); 76 | void sub(Float &f); 77 | void mult(Float &f); 78 | void div(Float &f); 79 | int cmp(Float &f); 80 | void floor(); 81 | void ceil(); 82 | void fmod(Float &f); 83 | LPCint frexp(); 84 | void ldexp(LPCint exp); 85 | void modf(Float *f); 86 | 87 | void exp(); 88 | void log(); 89 | void log10(); 90 | void pow(Float &f); 91 | void sqrt(); 92 | void cos(); 93 | void sin(); 94 | void tan(); 95 | void acos(); 96 | void asin(); 97 | void atan(); 98 | void atan2(Float &f); 99 | void cosh(); 100 | void sinh(); 101 | void tanh(); 102 | 103 | FloatHigh high; /* high word of float */ 104 | FloatLow low; /* low longword of float */ 105 | }; /* 1 sign, 11 exponent, 36 mantissa */ 106 | 107 | # define FLOAT_ISZERO(h, l) ((h) == 0) 108 | # define FLOAT_ISONE(h, l) ((h) == FLOAT_ONE && (l) == 0) 109 | # define FLOAT_ISMONE(h, l) ((h) == FLOAT_MONE && (l) == 0) 110 | 111 | extern Float max_int, thousand, thousandth; 112 | --------------------------------------------------------------------------------