2 (*CBC B.Ciesielski *)
\r
3 (* PASCAL routines for EXEC standard function *)
\r
9 cesxqq [external] : word; ! ES register from Pascal
\r
10 addr_ptr : ads of word;
\r
11 ax,bx,cx,dx,si,di : word; ! General Registers
\r
12 ds,es : word; ! Segment Registers
\r
13 errcode : word; ! Error code returned from DOS
\r
15 procedure dos(var ax,bx,cx,dx,si,di,ds,es,errcode : word); external;
\r
17 procedure initdd(var ax,bx,cx,dx,si,di,ds,es : word);
\r
18 {INITDD Initialize registers for call to DOS.}
\r
20 ds := defdsdd; ! Program Data Segment
\r
30 procedure asciizdd(const lstr : lstring; var astr : string);
\r
31 {ASCIIZDD This procedure converts a lstring variable to a ASCIIZ string.
\r
32 An asciiz string is terminated by a byte of zeroes.}
\r
37 alen := wrd(upper(astr));
\r
38 if (len >= alen) then
\r
40 movel(adr lstr[1],adr astr[1],len);
\r
41 astr[len + 1] := chr(0)
\r
45 (* initialize system pointers *)
\r
47 pspdd := cesxqq; ! Program segment prefix
\r
48 addr_ptr := ads cesxqq;
\r
49 defdsdd := addr_ptr.s; ! Default data segment
\r
50 addr_ptr.s := pspdd; ! Program environment address
\r
51 addr_ptr.r := #2c; ! is at offset #2c in PSP.
\r
55 procedure setblkmm(blkseg,blksize : word; var block,ercode : word);
\r
56 {SETBLKMM Modifies Allocated Blocks. The memory block pointed to by
\r
57 blkseg is modified to the size (in paragraphs) of blksize. The
\r
58 block increases or decreases in size to that specified in blksize.
\r
59 If the block cannot grow to blksize, the largest possible expansion
\r
60 is made, and new block size is returned in block. The values for
\r
61 the returned error code are:
\r
63 0 - Successful reallocation. The new block size
\r
64 (in paragraphs) is in block.
\r
65 1 - Memory control blocks destroyed
\r
66 2 - Insufficient memory on a grow request. The
\r
67 new block size is in block.
\r
68 3 - The pointer in blkseg points to a block which
\r
69 has not been allocated.
\r
70 >99 - Unidentified error. }
\r
74 initdd(ax,bx,cx,dx,si,di,ds,es); ! Initialize registers
\r
75 ax := byword(#4a,0); ! DOS Function 4ah
\r
79 dos(ax,bx,cx,dx,si,di,ds,es,errcode);
\r
84 7 : begin ! Destroyed control blocks
\r
88 8 : ercode := 2; ! Not enough memory
\r
90 block := 0; ! Illegal block request
\r
95 ercode := 100 + errcode
\r
100 procedure shrinkmm(var ercode : word);
\r
101 {SHRINKMM Release all memory not needed by the executing program. This
\r
102 procedure makes a call to SETBLKMM to release all memory which has
\r
103 been allocated, but which is not needed. DOS normally allocates all
\r
104 memory to a program, so memory must be released before other calls to
\r
105 ALLOCMM are made. The required memory is calculated as the code size
\r
106 plus the data space. The code size is essentially the default data
\r
107 segment minus the program segment prefix. The data space is the mini-
\r
108 mum of #1000 paragraphs (64K bytes) or the remainder of memory. The
\r
109 value of the error code returned is that returned by SETBLKMM.}
\r
112 topmem_ptr : ads of word; ! Pointer to word containing
\r
113 topmem : word; ! top of memory.
\r
114 data_seg : word; ! data segment start
\r
117 blksize : word; ! Total block size needed
\r
121 topmem_ptr.s := pspdd;
\r
122 topmem_ptr.r := 2; ! At offset 2 in PSP
\r
123 topmem := topmem_ptr^;
\r
124 data_seg := defdsdd; ! Default data segment
\r
125 if (data_seg < pspdd) then ! data_seg can be "negative"
\r
126 data_seg := topmem - (pspdd - data_seg);
\r
127 code_size := data_seg - pspdd;
\r
128 data_space := topmem - data_seg;
\r
129 if (data_space < #1000) then
\r
130 blksize := code_size + data_space
\r
132 blksize := code_size + #1000;
\r
134 setblkmm(pspdd,blksize,blksize,ercode)
\r
138 procedure execmm (const proc_name, cmd_line : lstring;
\r
139 var ercode : word) [public];
\r
140 {EXECMM Load and execute a program. This procedure loads and executes
\r
141 another program. The program path name is given in proc_name; the
\r
142 command line is given in cmd_line. The specified program will be
\r
143 loaded and executed as if invoked from DOS with the given command
\r
144 line. The spawned program returns control to the calling procedure
\r
145 when execution ends, either normally or using a Ctrl/Break sequence.
\r
146 The values of the returned error code are:
\r
148 0 - Successful execution and return.
\r
149 (*) 1 - Memory control blocks destroyed when trying
\r
151 (*) 2 - Insufficient memory when trying to reserve
\r
153 (*) 3 - Illegal block change request when trying to
\r
155 4 - Executable file not found.
\r
156 5 - Access denied. The file does not allow read
\r
158 6 - Insufficient memory to load the new procedure.
\r
159 (*) 7 - Invalid environment created in the called
\r
161 (*) 8 - Invalid format in the environment.
\r
162 9 - Invalid Path Name. Probably illegal characters
\r
163 are present in the proc_name parameter.
\r
164 >99 - Unidentified error
\r
166 Errors marked with (*) are internal errors and should not
\r
167 normally occur. Errors 1 - 3 indicate problems with the
\r
168 SHRINKMM procedure, and errors 7 & 8 are internal errors
\r
169 within EXECMM (the construction of the parameter block).}
\r
172 parm_block = record ! Parameter block
\r
173 env_sadd : word; ! Segment address of environment
\r
174 cmd_addr : adsmem; ! Address of command line
\r
175 fb1_addr : adsmem; ! Address of first FCB
\r
176 fb2_addr : adsmem ! Address of second FCB
\r
179 procz : string(255); ! ASCIIZ procedure name
\r
180 block_val : parm_block; ! Constructed parameter block
\r
184 shrinkmm(ercode); ! Release available memory
\r
186 if (ercode = 0) then ! Now load the program
\r
190 env_sadd := envdd; ! Copy parent's environment
\r
191 cmd_addr := ads cmd_line[0];
\r
192 fb1_addr.s := pspdd;
\r
194 fb2_addr.s := pspdd;
\r
197 initdd(ax,bx,cx,dx,si,di,ds,es);
\r
198 ax := byword(#4b,0); ! DOS function 4bh
\r
199 bx := wrd(adr block_val);
\r
201 asciizdd(proc_name,procz);
\r
202 dx := wrd(adr procz); ! Path name as an asciiz string
\r
204 dos(ax,bx,cx,dx,si,di,ds,es,errcode);
\r
208 1 : ercode := 9; ! Invalid path name
\r
209 2 : ercode := 4; ! File not found
\r
210 5 : ercode := 5; ! Access denied
\r
211 8 : ercode := 6; ! Insufficient memory
\r
212 10 : ercode := 7; ! Invalid environoment
\r
213 11 : ercode := 8; ! Invalid format
\r
215 ercode := 100 + errcode
\r