1;
2; exec: function to chain to another C-generated com file, with
3;	 text argument passing.
4;
5; Calling sequence:
6;	 exec(prog, args);
7;	 char *prog, *args;
8;
9; where
10;	 prog is the name of the program being executed next
11;	 args is a pointer to a string of arguments separated by
12;	   blanks or tabs.  Embedded blanks within the arguments are
13;	   not allowed, unless the called program does not use the
14;	   default FCB parameters (and most don't) and can parse the
15;	   command line parameter list itself (like C80 programs can).
16;
17
18
19	SECTION code_clib
20
21	PUBLIC    execl
22	PUBLIC    _execl
23
24
25	EXTERN    _parsefcb
26	EXTERN    asm_toupper
27	EXTERN    l_gint
28
29
30;
31;	CP/M memory pointers
32;
33DEFC __BASE   =  0000H       ;either 0 or 4200h for CP/M systems
34DEFC __FCB    =  __BASE+5CH  ;default file control block
35DEFC __TBUFF  =  __BASE+80H  ;sector buffer
36DEFC __BDOS   =  __BASE+5    ;bdos entry point
37DEFC __TPA    =  __BASE+100H ;transient program area
38DEFC __ERRV   =  255         ;error value returned by bdos calls
39
40;
41;	CP/M BDOS CALL MNEMONICS
42;
43DEFC __OPENC  =  15 ;open a file
44DEFC __READS  =  20 ;read a sector (sequential)
45DEFC __SDMA  =  26 ;set dma
46
47
48execl:
49_execl:
50
51	LD HL,4
52	ADD	HL,SP
53	LD  E,(HL)
54	INC HL
55	LD  D,(HL) 	;DE points to program name now
56
57	LD HL,-60
58	ADD	HL,SP		; compute &newfcb for use here
59	PUSH HL		; save for much later (will pop into bc)
60	PUSH HL		;make a few copies for local use below
61	PUSH HL
62
63	;  CP/M name->FCB routine.  Call with file name address in DE, FCB IN HL.
64	;CALL x?fcb	;set up com file for exec-ing
65	;push hl
66	push de
67	call _parsefcb
68	pop	de
69	;pop	hl
70
71	POP HL		;get new fcb addr
72	LD BC,9 	;set extension to com
73	ADD	HL,BC
74	LD  (HL),'C'
75	INC HL
76	LD  (HL),'O'
77	INC HL
78	LD  (HL),'M'
79	POP DE		;get new fcb addr again
80	LD  C,__OPENC	;open the file for reading
81	CALL __BDOS
82	CP __ERRV
83	JP	NZ,__NOERR
84	POP HL		;if can't (like it doesn't exist), return -1
85	LD HL,-1
86	RET
87
88
89__NOERR:
90	LD HL,4 	;get args pointer
91	ADD	HL,SP
92	CALL l_gint		; CALL h.	;HL = *HL
93	CALL __SPARG	;separate them into individual strings
94	LD HL,(__ARG1)
95	LD  A,H
96	OR L
97	JP	NZ,__EXCL0
98	LD DE,__ARG1	;no arguments -- create a blank FCB
99	PUSH DE		;call x?fcb with null string
100	LD HL,__FCB
101
102	;  CP/M name->FCB routine.  Call with file name address in DE, FCB IN HL.
103	;CALL x?fcb
104
105	push hl
106	push de
107	call _parsefcb
108	pop	de
109	pop	hl
110
111	POP HL
112	JP __EXCL6
113
114
115__EXCL0:
116	EX	DE,HL
117	LD HL,__FCB
118
119	;  CP/M name->FCB routine.  Call with file name address in DE, FCB IN HL.
120	;CALL x?fcb	;stick first param into default FCB slot
121
122	push hl
123	push de
124	call _parsefcb
125	pop	de
126	pop	hl
127
128	LD HL,(__ARG2)	;and stick second param string
129	LD  A,H
130	OR L
131	JP	NZ,__EXCL6
132	LD HL,__ARG2
133
134__EXCL6:
135	EX	DE,HL		;into second default fcb slot
136	LD HL,__FCB+16
137
138	;  CP/M name->FCB routine.  Call with file name address in DE, FCB IN HL.
139	;CALL x?fcb
140	push hl
141	push de
142	call _parsefcb
143	pop	de
144	pop	hl
145
146	LD DE,__TBUFF+1	 ;now construct command line:
147	LD HL,4
148	ADD	HL,SP		;HL points to arg string pointer
149	CALL l_gint		; CALL h.	;HL points to arg string
150	LD  B,0 	;char count for com. line buf.
151	LD  A,H 	;are there any arguments?
152	OR L
153	JP	Z,__EXCL9
154	OR (HL)		; (Bug fix 7/83 WB)
155	JP	NZ,__EXCL5
156__EXCL9:
157	LD (DE),A		;no--zero TBUFF and TBUFF+1
158	JP __EXCL2
159__EXCL5:
160	LD  A,' '	;yes--start buffer off with a ' '
161	LD (DE),A
162	INC DE
163	INC B
164__EXCL1:
165	LD  A,(HL) 	;now copy argument string to command line
166	CALL asm_toupper	;make sure they're upper case
167	LD (DE),A
168	INC DE
169	INC HL
170	INC B
171	OR A
172	JP	NZ,__EXCL1
173	DEC B
174
175__EXCL2:
176	LD HL,__TBUFF	;set length of command line
177	LD  (HL),B 	;at location tbuff
178
179	LD DE,__CODE0	;copy loader down to end of tbuff
180	LD HL,__TPA-42
181	LD  B,42	;length of loader
182__EXCL4:
183	LD A,(DE)
184	LD  (HL),A
185	INC DE
186	INC HL
187	DEC B
188	JP	NZ,__EXCL4
189
190	POP BC			;get back working fcb pointer
191	LD HL,(__BASE+6)
192	LD	SP,HL
193	LD HL,__BASE
194	PUSH HL			;set base of ram as return addr
195	JP __TPA-42		;(go to `CODE0:')
196;
197; THIS LOADER CODE IS NOW: 42 BYTES LONG.
198;
199__CODE0:
200	LD DE,__TPA		;destination address of new program
201__CODE1:
202	PUSH DE			;push dma addr
203	PUSH BC			;push fcb pointer
204	LD  C,__SDMA		;set dma address for new sector
205	CALL __BDOS
206	POP DE			;get pointer to working fcb in de
207	PUSH DE			;and re-push it
208	LD  C,__READS		;read a sector
209	CALL __BDOS
210	POP BC			;restore fcb pointer into bc
211	POP DE			;and dma address into de
212	OR A			;end of file?
213	JP	Z,__TPA-8		;if not, get next sector (goto `CODE2:')
214	LD  C,__SDMA		;reset dma pointer
215	LD DE,__TBUFF
216	CALL __BDOS
217	JP __TPA		;and go invoke the program
218
219__CODE2:
220	LD HL,80H		; bump dma address
221	ADD	HL,DE
222	EX	DE,HL
223	JP __TPA-39		;and go loop (at CODE1)
224
225
226;
227; this routine takes the string pointed to by HL,
228; seperates it into non-white strings,
229; and places them contiguously in array ARGST.
230; also places pointers to these individual strings in ARGS
231;
232__SPARG:
233	EX	DE,HL		;DE = original string
234	LD BC,__ARGST	;BC = new string (w/ each substr 0-terminated)
235	LD HL,__ARGS	;HL = pointer to ARGS space
236__SEP0:
237	DEC DE
238__SEP1:
239	INC DE		;scan over white space
240	LD A,(DE)
241	CP ' '
242	JP	Z,__SEP1
243	CP 9
244	JP	Z,__SEP1
245	CP 0		; char = 0?
246	JP	Z,__SPRET	; yes -- return
247	LD  (HL),C 	; no -- store local pointer at proper args
248	INC HL
249	LD  (HL),B 	;argsn = BC
250	INC HL
251__TOWSP:
252	LD (BC),A		;store non-white
253	INC BC
254	INC DE		;now scan to next white space
255	LD A,(DE)
256	CP 0
257	JP	Z,__SEP2
258	CP ' '
259	JP	Z,__SEP2
260	CP 9
261	JP	NZ,__TOWSP
262__SEP2:
263	XOR A
264	LD (BC),A		;store 0 to terminate this string
265	INC BC
266	JP __SEP0	; and loop
267
268__SPRET:
269	LD  (HL),A 	;set last argn to 0 and return
270	INC HL
271	LD  (HL),A
272	RET
273
274
275
276SECTION bss_clib
277
278;
279;	Argument pointers
280;
281__ARGS:	DEFS 0
282__ARG1:	DEFS 2
283__ARG2:	DEFS 2
284__ARG3:	DEFS 2
285__ARG4:	DEFS 2
286__ARG5:	DEFS 2
287__ARG6:	DEFS 2
288;
289
290__ARGST:
291	DEFS 100
292
293