summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/SUBST
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/CMD/SUBST
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-main.tar.gz
ms-dos-main.tar.xz
ms-dos-main.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/CMD/SUBST')
-rw-r--r--v4.0/src/CMD/SUBST/MAKEFILE81
-rw-r--r--v4.0/src/CMD/SUBST/SUBST.C719
-rw-r--r--v4.0/src/CMD/SUBST/SUBST.LNK12
-rw-r--r--v4.0/src/CMD/SUBST/SUBST.SKL22
-rw-r--r--v4.0/src/CMD/SUBST/SUBSTPAR.H155
-rw-r--r--v4.0/src/CMD/SUBST/_MSGRET.ASM250
-rw-r--r--v4.0/src/CMD/SUBST/_PARSE.ASM121
7 files changed, 1360 insertions, 0 deletions
diff --git a/v4.0/src/CMD/SUBST/MAKEFILE b/v4.0/src/CMD/SUBST/MAKEFILE
new file mode 100644
index 0000000..9ad2e7b
--- /dev/null
+++ b/v4.0/src/CMD/SUBST/MAKEFILE
@@ -0,0 +1,81 @@
1#************************ makefile for cmd\subst *************************
2
3msg =..\..\messages
4dos =..\..\dos
5inc =..\..\inc
6hinc =..\..\h
7map =..\..\mapper
8here =..\cmd\subst # This is the path from INC or MAP dir's to here.
9make =nmake -i
10
11#
12####################### dependencies begin here. #########################
13#
14
15all: subst.exe
16
17$(inc)\errtst.obj:
18 cd $(inc)
19 $(make)
20 cd $(here)
21
22$(inc)\sysvar.obj:
23 cd $(inc)
24 $(make)
25 cd $(here)
26
27$(inc)\cds.obj:
28 cd $(inc)
29 $(make)
30 cd $(here)
31
32$(inc)\dpb.obj:
33 cd $(inc)
34 $(make)
35 cd $(here)
36
37$(inc)\comsubs.lib:
38 cd $(inc)
39 $(make)
40 cd $(here)
41
42$(map)\mapper.lib:
43 cd $(map)
44 $(make)
45 cd $(here)
46
47subst.ctl: subst.skl \
48 $(msg)\$(COUNTRY).msg \
49 makefile
50
51_msgret.obj: _msgret.asm \
52 $(inc)\msgserv.asm \
53 $(inc)\sysmsg.inc \
54 subst.ctl \
55 subst.cla \
56 subst.cl1 \
57 subst.cl2 \
58 subst.skl
59
60_parse.obj: _parse.asm \
61 $(inc)\parse.asm \
62 $(inc)\psdata.inc
63
64subst.obj: subst.c \
65 makefile \
66 substpar.h \
67 $(hinc)\cds.h \
68 $(hinc)\jointype.h \
69 $(hinc)\sysvar.h
70
71subst.exe: subst.obj \
72 $(inc)\cds.obj \
73 $(inc)\dpb.obj \
74 $(inc)\errtst.obj \
75 $(inc)\sysvar.obj \
76 $(map)\mapper.lib \
77 $(inc)\comsubs.lib \
78 _msgret.obj \
79 _parse.obj \
80 subst.lnk
81 link @subst.lnk
diff --git a/v4.0/src/CMD/SUBST/SUBST.C b/v4.0/src/CMD/SUBST/SUBST.C
new file mode 100644
index 0000000..c873e42
--- /dev/null
+++ b/v4.0/src/CMD/SUBST/SUBST.C
@@ -0,0 +1,719 @@
1/*  */
2/**************************************************************************/
3/* */
4/* UTILITY NAME: Subst */
5/* */
6/* SOURCE FILE NAME: Subst.C */
7/* */
8/* STATUS: Subst Utility, DOS Version 4.0 */
9/* */
10/* FUNCTIONAL DESCRIPTION: This utility allows the substitution of a */
11/* physical drive for a pathname on another drive such that operations */
12/* performed using the physical drive as an argument take place on the */
13/* pathname. */
14/* */
15/* SYNTAX: [d:][path]SUBST or */
16/* [d:][path]SUBST d: d:path or */
17/* [d:][path]SUBST d: /D */
18/* where: */
19/* [d:][path] to specify the drive and path that */
20/* contains the SUBST command file */
21/* */
22/* d: specifies the drive letter that you want */
23/* to use to refer to another drive or path. */
24/* */
25/* d:path to specify the drive or path that you */
26/* want to refer to with a nickname. */
27/* */
28/* /D to delete a substitution. You must specify */
29/* the letter of the drive whose substitution */
30/* you want to delete. */
31/* */
32/* LINKS: */
33/* CDS.C - Functions to get/set DOS CDS structures */
34/* DPB.C - Functions to get DOS DPB structures */
35/* ERRTST.C - Drive and path validity testing functions */
36/* SYSVAR.C - Functions to get/set DOS System Variable structures */
37/* COMSUBS.LIB - DOS DBCS function calls */
38/* MAPPER.LIB - DOS function calls */
39/* SLIBC3.LIB - C library functions */
40/* _MSGRET.SAL - Assembler interface for common DOS message services */
41/* _PARSE.SAL - Assembler interface for common DOS parser */
42/* */
43/* ERROR HANDLING: Error message displayed and utility is terminated. */
44/* */
45/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
46/* */
47/* MODIFICATIONS: */
48/* */
49/* Converted to CMERGE 03/26/85 */
50/* */
51/* M000 June 5/85 */
52/* Changed low version check for specific 320. */
53/* */
54/* M001 June 12/85 */
55/* The original IBM version of SUBST allowed the delete switch "/D" */
56/* immediately after the drive specification. The argument parsing code */
57/* has been Revised to allow this combination. */
58/* */
59/* M002 July 3/85 */
60/* When there are only two operand make sure that there are no additional*/
61/* switch characters. */
62/* */
63/* M003 July 9/85 */
64/* Altered pathname verification tests to so that the same error message */
65/* will result. */
66/* */
67/* M004 July 29/85 */
68/* Only allow 2 characters in the drive name specifier for delete (used */
69/* to be three). */
70/* */
71/* May /87 */
72/* Deletion of source code dealing with parsing and displaying messages */
73/* and addition of SYSLOADMSG, SYSDISPMSG, SYSPARSE in order to conform */
74/* to DOS Version 4.0 specifications to utilize common DOS parser and */
75/* message service routines. */
76/* */
77/* AC000: Changed code for DOS Version 4.0 5/87 */
78/* */
79/* AN000: New code for DOS Version 4.0 5/87 */
80/* AN000;M = message services */
81/* AN000;P = parser service */
82/* */
83/* Ax001: Changed code req'd - PTM0003920 3/88 */
84/* Incorrect message response */
85/* */
86/* Ax002: Changed code req'd - PTM0004045 3/88 */
87/* Incomplete message response */
88/* */
89/**************************************************************************/
90
91#include "cds.h"
92#include "dos.h"
93#include "fcntl.h"
94#include "jointype.h"
95#include "string.h"
96#include "substpar.h" /* ;AN000; Parser structures */
97#include "sysvar.h"
98
99/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ PARSE EQUATES ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
100#define ASCII_DRIVE 'A'-1 /* ;AN000;P Convert to Ascii drive */
101#define CAPRESULT 0x0001 /* ;AN000;P Cap result by file table */
102#define DRVONLY_OPT 0x0101 /* ;AN000;P Drive only & optional */
103#define ERRORLEVEL1 1 /* ;AN000;P Parsing error occurred */
104#define FALSE 0
105#define FILESPEC_OPT 0x0201 /* ;AN000;P File spec & optional */
106#define MAX 256 /* ;AN000;P Define a limit */
107#define MAXPOSITION 2 /* ;AN000;P Max positionals in cmdline */
108#define MINPOSITION 0 /* ;AN000;P Min positionals in cmdline */
109#define NOCAPPING 0x0000 /* ;AN000;P Do not cap result */
110#define NULL 0
111#define SWITCH_OPT 0x0000 /* ;AN000;P Optional switch */
112
113/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ MESSAGE EQUATES ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
114#define MSG_PARMNUM 1 /* ;AN000;M Incorrect Num of Parms */
115#define MSG_BADPATH 2 /* ;AN000;M Path not Found */
116#define MSG_NOMEM 3 /* ;AN000;M Insufficient memory */
117#define MSG_BADPARM 4 /* ;AN000;M Invalid parameter */
118#define MSG_NETERR 5 /* ;AN000;M Cannot %1 a network drv */
119#define MSG_INVSWTCH 6 /* ;AN000;M Invalid switch */
120
121#define BLNK ' ' /* ;AN000;M For sublist.pad_char */
122#define CARRY 0x0001 /* ;AN000;M To test carry from msg hndlr */
123#define D_SWITCH "/D" /* ;AN000;M For switch id */
124#define EXT_ERR_CLASS 0x01 /* ;AN000;M DOS Extended error class */
125#define MAXWIDTH 0 /* ;AN000;M 0 ensures no padding */
126#define MINWIDTH 1 /* ;AN000;M At least 1 char in parm */
127#define NO_INPUT 0x00 /* ;AN000;M No input characters */
128#define PARSE_ERR_CLASS 0x02 /* ;AN000;M Parse error class */
129#define RESERVED 0 /* ;AN000;M Reserved byte field */
130#define STDERR 0x0002 /* ;AN000;M Standard error device handle */
131#define STDOUT 0x0001 /* ;AN000;M Std output device handle */
132#define STR_INPUT 16 /* ;AN000;M Byte def for sublist.flags */
133#define SUB_ID0 0 /* ;AN000;M 0 for error substitution */
134#define SUB_ID1 1 /* ;AN000;M Only 1 replaceable parameter */
135#define SUBCNT0 0 /* ;AN000;M 0 substitutions in message */
136#define SUBCNT1 1 /* ;AN000;M 1 substitution in message */
137#define SUBLIST_LENGTH 11 /* ;AN000;M Length of sublist structure */
138#define UTILITY_CLASS 0x0ff /* ;AN000;M Utility message class */
139
140/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ MISCELLANEOUS ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
141extern long GetDPB() ;
142extern char fDelete() ; /* SM '87 compiler required extern */
143extern char *malloc() ; /* SM '87 compiler required extern */
144extern char *strbscan() ; /* SM '87 compiler required extern */
145
146char cmdln_drive[64] = {0} ; /* ;AN002; Save user's input in */
147char cmdln_flspec[64] = {0} ; /* ;AN002; order to pass to error */
148char cmdln_invalid[64] = {0} ; /* ;AN002; */
149char cmdln_switch[64] = {0} ; /* ;AN002; message, if needed */
150char fix_es_reg[1] ; /* ;AN000;P Corrects es reg after type-"far" */
151char p_drive[3] ; /* ;AN000;P Recvs drive ltr from parser */
152char p_filespec[64] ; /* ;AN000;P Recvs filespec from parser */
153char replparm_SUBST[] = "SUBST" ; /* ;AN000;P Cannot SUBST a network drv */
154
155unsigned char source[MAX] = {0} ; /* ;AN000;P buffer for string manipulation */
156
157int index ; /* ;AN000;P Used in creating cmdline string */
158
159struct sysVarsType SysVars ;
160
161/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ PARSE STRUCTURES ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
162struct p_parms p_p ; /* ;AN000;P # of extras & pts to descrptn */
163struct p_parmsx p_px ; /* ;AN000;P min/max parms & pts to controls */
164struct p_control_blk p_con1 ; /* ;AN000;P 1st posit parm in cmd str */
165struct p_control_blk p_con2 ; /* ;AN000;P 2nd posit parm in cmd str */
166struct p_switch_blk p_swi1 ; /* ;AN000;P /D switch in cmd str */
167struct p_result_blk rslt1 ; /* ;AN000;P Result blk rtrnd from parser */
168struct p_fresult_blk rslt2 ; /* ;AN000;P Result blk rtrnd from parser */
169struct p_result_blk rslt3 ; /* ;AN000;P Result blk rtrnd from parser */
170struct noval novals = {0} ; /* ;AN000;P Value list not used */
171
172union REGS inregs, outregs ; /* ;AN000;P Define register variables */
173
174/**************************************************************************/
175/* */
176/* SUBROUTINE NAME: main (program entry point) */
177/* */
178/* SUBROUTINE FUNCTION: Preload message file */
179/* Get the command line parameters */
180/* Parse the command line by calling SYSPARSE */
181/* Verify the correctness of the parameters */
182/* Check for deletion switch */
183/* Check source path and destination not same */
184/* Determine if source or destination is network */
185/* Determine if currently spliced */
186/* Print messages by calling SYSDISPMSG */
187/* */
188/* EXTERNAL ROUTINES: SYSLOADMSG */
189/* SYSDISPMSG */
190/* SYSPARSE */
191/* */
192/* INTERNAL ROUTINES: BackFix Load_Msg */
193/* fDelete Display_Msg */
194/* Insert Parser_Prep */
195/* Display dispmsg_terminate */
196/* */
197/**************************************************************************/
198
199main(c, v)
200int c ;
201char *v[] ;
202{
203 char far * fptr ; /* ;AN000;P Pointer to parser's buffer */
204
205 int delflag = FALSE ; /* Deletion specified M001 */
206 int fchar = 0 ; /* ;AN000;P Parser filespec chars */
207 int more_to_parse = TRUE ; /* ;AN000;P While parsing cmdline */
208 int pdrive_flg = FALSE ; /* ;AN000;P Is there a drive letter? */
209 int pflspec_flg = FALSE ; /* ;AN000;P Is there a filespec? */
210
211/************************ BEGIN ***********************************************/
212
213 load_msg() ; /* ;AN000;M Point to msgs & chk DOS ver */
214
215 for (index = 1; index <= c; index++) /* ;AN000;P Loop through end of cmd line */
216 { /* ;AN000;P */
217 strcat(source,v[index]) ; /* ;AN000;P Add the argument */
218 strcat(source," ") ; /* ;AN000;P Separate with a space */
219 } /* ;AN000;P */
220 Parser_Prep(source) ; /* ;AN000;P Initialization for the parser */
221
222 while (more_to_parse) /* ;AN000;P test the flag */
223 { /* ;AN000;P */
224 index = 0 ; /* ;AN002; Init array index */
225 parse(&inregs,&outregs) ; /* ;AN000;P call the parser */
226 if (outregs.x.ax == P_No_Error) /* ;AN000;P if no error */
227 { /* ;AN000;P */
228 if (outregs.x.dx == (unsigned short)&rslt1) /* ;AN000;P if result is drv ltr */
229 { /* ;AN000;P */
230 p_drive[0] = *(rslt1.p_result_buff) ; /* ;AN000;P save the drive letter */
231 p_drive[0] += (char)ASCII_DRIVE ; /* ;AN000;P */
232 p_drive[1] = COLON ; /* ;AN000;P */
233 pdrive_flg = TRUE ; /* ;AN000;P and set the flag */
234 for (inregs.x.si ; inregs.x.si < outregs.x.si ; inregs.x.si++) /* ;AN002; Copy whatever */
235 { /* ;AN002; parser just parsed */
236 cmdln_drive[index] = *(char *)inregs.x.si ; /* ;AN002; */
237 index++ ; /* ;AN002; */
238 } /* ;AN002; */
239 } /* ;AN000;P */
240 else /* ;AN000;P */
241 if (outregs.x.dx == (unsigned short)&rslt2) /* ;AN000;P if result is filespec */
242 { /* ;AN000;P */
243 for (fptr = rslt2.fp_result_buff; (char)*fptr != NULL; fptr++) /* ;AN000;P From beg of buf til nul */
244 { /* ;AN000;P */
245 p_filespec[fchar] = (char)*fptr ; /* ;AN000;P copy from rslt field buf */
246 fchar++ ; /* ;AN000;P */
247 } /* ;AN000;P */
248 strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */
249 pflspec_flg = TRUE ; /* ;AN000;P and set the flag */
250 for (inregs.x.si ; inregs.x.si < outregs.x.si ; inregs.x.si++) /* ;AN002; Copy whatever */
251 { /* ;AN002; parser just parsed */
252 cmdln_flspec[index] = *(char *)inregs.x.si ; /* ;AN002; */
253 index++ ; /* ;AN002; */
254 } /* ;AN002; */
255 } /* ;AN000;P */
256 else /* ;AN000;P */
257 { /* ;AN000;P */
258 for (inregs.x.si ; inregs.x.si < outregs.x.si ; inregs.x.si++) /* ;AN002; Copy whatever */
259 { /* ;AN002; parser just parsed */
260 cmdln_switch[index] = *(char *)inregs.x.si ; /* ;AN002; */
261 index++ ; /* ;AN002; */
262 } /* ;AN002; */
263 if (!delflag) /* ;AN000;P Check for dup switch */
264 delflag = TRUE ; /* ;AN000;P it's /D switch */
265 else /* ;AN000;P else it's a duplicate switch */
266 dispmsg_terminate(MSG_INVSWTCH,cmdln_switch) ; /* ;AN000;P display err msg & exit util */
267 } /* ;AN000;P */
268 } /* ;AN000;P */
269 else /* ;AN000;P */
270 if (outregs.x.ax != P_RC_EOL) /* ;AN000;P there must be an error */
271 { /* ;AN000;P */
272 for (inregs.x.si ; inregs.x.si < outregs.x.si ; inregs.x.si++) /* ;AN002; Copy whatever */
273 { /* ;AN002; parser just parsed */
274 cmdln_invalid[index] = *(char *)inregs.x.si ; /* ;AN002; */
275 index++ ; /* ;AN002; */
276 } /* ;AN002; */
277 switch (outregs.x.ax) /* ;AN000;P See what error the */
278 { /* ;AN000;P parser may have found */
279 case P_Too_Many : dispmsg_terminate(MSG_PARMNUM,cmdln_invalid) ; /* ;AN000;P incorrect syntax */
280 break ; /* ;AN000;P more_to_parse = FALSE */
281 case P_Not_In_SW : dispmsg_terminate(MSG_INVSWTCH,cmdln_invalid) ; /* ;AN000;P Invalid switch */
282 break ; /* ;AN000;P more_to_parse = FALSE */
283 case P_Op_Missing : /* ;AN000;P Required operand missing */
284 case P_Not_In_Key : /* ;AN000;P Not in kywrd list provided */
285 case P_Out_Of_Range : /* ;AN000;P Out of range specified */
286 case P_Not_In_Val : /* ;AN000;P Not in val list provided */
287 case P_Not_In_Str : /* ;AN000;P Not in strg list provided */
288 case P_Syntax : dispmsg_terminate(MSG_BADPARM,cmdln_invalid) ; /* ;AN000;P incorrect syntax */
289 break ; /* ;AN000;P more_to_parse = FALSE */
290 default : display_msg(MSG_BADPARM,cmdln_invalid) ; /* ;AN000;P */
291 exit(ERRORLEVEL1) ; /* ;AN000;P Something's wrong */
292 } /* ;AN000;P */
293 } /* ;AN000;P */
294 else /* ;AN000;P End of the cmdline */
295 more_to_parse = FALSE ; /* ;AN000;P */
296 inregs.x.cx = outregs.x.cx ; /* ;AN000;P Move the count */
297 inregs.x.si = outregs.x.si ; /* ;AN000;P Move the pointer */
298 } /* ;AN000;P */
299
300 if (pdrive_flg && !(pflspec_flg || delflag)) /* ;AN000;P drive & no flspec or delete ? */
301 dispmsg_terminate(MSG_BADPARM,cmdln_drive) ; /* ;AN000;P display error msg & exit utility */
302
303 if (pflspec_flg && !pdrive_flg) /* ;AN000;P filespec & no drive ? */
304 dispmsg_terminate(MSG_BADPARM,cmdln_flspec) ; /* ;AN000;P display error msg & exit utility */
305
306 if (delflag && !pdrive_flg) /* ;AN000;P delete & no drive ? */
307 dispmsg_terminate(MSG_BADPARM,cmdln_switch) ; /* ;AN000;P display error msg & exit utility */
308
309 if (pdrive_flg && pflspec_flg && delflag) /* ;AN000;P drive, filespec & /D ? */
310 dispmsg_terminate(MSG_PARMNUM,cmdln_switch) ; /* ;AN000;P display error msg & exit utility */
311
312 GetVars(&SysVars) ;
313 strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */
314
315 if (c == 1) /* display all tree aliases */
316 Display() ;
317 else
318 if (delflag) /* ;AC000;P Are we to delete a subst? */
319 {
320 if (!fDelete(p_drive))
321 dispmsg_terminate(MSG_BADPARM,cmdln_drive) ; /* :AC002; */
322 strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */
323 }
324 else
325 Insert(p_drive,p_filespec) ; /* ;AC000;P */
326
327 exit(0) ;
328}
329/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
330
331char *BackFix(p)
332char *p ;
333{
334 char *p1 ;
335 char *p2 ;
336
337 p2 = p-1 ;
338 while (*(p2 = strbscan(p1 = p2+1,"\\")) != NULL) ;
339
340 /* p1 points to char after last path sep. */
341 /* If this is a NULL, p already has a trailing path sep. */
342
343 if (*p1 != NULL)
344 if ((p1 = malloc(strlen(p)+2)) == NULL)
345 dispmsg_terminate(MSG_NOMEM) ; /* ;AN000;M */
346 else
347 {
348 strcpy(p1, p) ;
349 strcat(p1, "\\") ;
350 p = p1 ;
351 }
352 return(p) ;
353}
354/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
355
356char fDelete(v)
357char *v ;
358{
359 struct CDSType CDS ;
360 int drive ;
361
362 /* M004 Only 2 characters in the drive specifier */
363 /* (and move before the call to BackFix) */
364
365 if (strlen(v) != 2 || v[1] != ':')
366 return(FALSE) ;
367
368 v = BackFix(v) ;
369 drive = *v - 'A' ;
370
371 if (!fGetCDS(drive, &CDS) || /* If CDS doesn't exist or */
372 !TESTFLAG(CDS.flags,CDSLOCAL) || /* was not substed or */
373 drive == getdrv()) /* is the current drive */
374 dispmsg_terminate(MSG_BADPARM,cmdln_drive) ; /* ;AC000;M */
375
376 strcpy(CDS.text, "A:\\") ; /* Set-up text of curr directory */
377 CDS.text[0] += drive ;
378 CDS.cbEnd = 2 ; /* Set backup limit */
379
380 /* If physical, then mark as inuse and set-up DPB pointer */
381
382 CDS.flags = drive >= SysVars.cDrv ? FALSE : CDSINUSE ;
383 CDS.pDPB = drive >= SysVars.cDrv ? 0L : GetDPB(drive) ;
384
385 strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */
386 fPutCDS(drive, &CDS) ;
387 strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */
388 return(TRUE) ;
389}
390/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
391
392Insert(s, d)
393char *s, *d ;
394{
395 struct CDSType CDS ;
396 int drives, drived ;
397 char buf[MAXPATHLEN] ;
398
399 rootpath(d, buf) ;
400
401 if (strlen(d) == 2 && d[1] == ':')
402 dispmsg_terminate(MSG_BADPARM,cmdln_flspec) ; /* ;AC000;M Insure dest not just a drive */
403
404 if (strlen(buf) == 3) /* Dest must exist, try root 1st */
405 if (buf[1] != ':' || (buf[2]) != PathChr)
406 dispmsg_terminate(MSG_BADPARM,cmdln_flspec) ; /* ;AC000;M */
407
408 /* M003 - path verification was treated as an ELSE condition */
409 /* else Must be subdir... make sure */
410
411 if (open(buf,O_BINARY) != -1)
412 dispmsg_terminate(MSG_BADPARM,cmdln_flspec) ; /* ;AC000;M */
413 else
414 if (access(buf,NULL) == -1)
415 dispmsg_terminate(MSG_BADPATH,cmdln_flspec) ; /* ;AC000;M */
416
417 s = BackFix(s) ;
418 d = BackFix(buf) ;
419 drives = *s - 'A' ;
420 drived = *d - 'A' ;
421
422 if (fNet(drives)) /* Src can't be net drive, is reuse of CDS */
423 dispmsg_terminate(MSG_NETERR) ; /* ;AC000;M */
424
425 strcpy(fix_es_reg,NULL); /* ;AN000;P (Set es reg correct) */
426 if (fNet(drived)) /* Dest can't be a net drive either */
427 dispmsg_terminate(MSG_NETERR) ; /* ;AC000;M */
428
429 /* If src or dest invalid; or dest too long; or drives the same; or can't */
430 /* get CDS for source; or source is current drive; or drive is net, */
431 /* splices or substed already; or destination is not physical */
432
433 strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */
434 if (drives < 0 || drives >= SysVars.cCDS ||
435 drives == drived ||
436 !fGetCDS(drives, &CDS) ||
437 drives == getdrv() ||
438 TESTFLAG(CDS.flags,CDSNET|CDSSPLICE|CDSLOCAL))
439 dispmsg_terminate(MSG_BADPARM,cmdln_drive) ; /* ;AC000;M */
440
441 strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */
442 if (drived < 0 || drived >= SysVars.cCDS ||
443 strlen(d) >= DIRSTRLEN ||
444 !fPhysical(drived))
445 dispmsg_terminate(MSG_BADPARM,cmdln_flspec) ; /* ;AC000;M */
446
447 strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */
448 if (strlen(d) != 3) /* Chop trailing \ if not at root */
449 d[strlen(d)-1] = 0 ;
450
451 strcpy(CDS.text, d) ;
452 CDS.cbEnd = strlen(CDS.text) ;
453 if (CDS.cbEnd == 3)
454 CDS.cbEnd-- ;
455 CDS.flags = CDSINUSE|CDSLOCAL ;
456 if ((CDS.pDPB = GetDPB(drived)) == -1L)
457 dispmsg_terminate(MSG_BADPARM,cmdln_flspec) ; /* ;AC000;M */
458
459 strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */
460 CDS.ID = -1L ;
461 fPutCDS(drives, &CDS) ;
462 strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */
463 return ; /* ;AN000; */
464}
465/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
466
467Display() /* Display current list of substs */
468{
469 struct CDSType CDS ;
470 int i ;
471
472 for (i=0 ; fGetCDS(i, &CDS) ; i++)
473 if (TESTFLAG(CDS.flags,CDSLOCAL))
474 {
475 if (CDS.cbEnd == 2)
476 CDS.cbEnd ++ ;
477 CDS.text[CDS.cbEnd] = 0 ;
478 printf("%c: => %s\n", i+'A', CDS.text) ;
479 }
480 return ; /* ;AN000; */
481}
482/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
483/**************************************************************************/
484/* */
485/* SUBROUTINE NAME: load_msg */
486/* */
487/* SUBROUTINE FUNCTION: Load the set of SUBST Utility messages to */
488/* become available for display_msg call. */
489/* */
490/* ERROR EXIT: Utility will be terminated by sysloadmsg if */
491/* version check is incorrect. */
492/* */
493/* EXTERNAL REF: SYSLOADMSG */
494/* */
495/**************************************************************************/
496
497load_msg() /* ;AN000;M */
498{ /* ;AN000;M */
499 sysloadmsg(&inregs,&outregs) ; /* ;AN000;M Load utility messages */
500 if (outregs.x.cflag & CARRY) /* ;AN000;M If problem loading msgs */
501 { /* ;AN000;M */
502 sysdispmsg(&outregs,&outregs) ; /* ;AN000;M then display the err msg */
503 exit(ERRORLEVEL1) ; /* ;AN000;M */
504 } /* ;AN000;M */
505 return ; /* ;AN000;M */
506} /* ;AN000;M */
507/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
508/**************************************************************************/
509/* */
510/* SUBROUTINE NAME: display_msg */
511/* */
512/* SUBROUTINE FUNCTION: The correct message called by main is displayed */
513/* to standard out. */
514/* */
515/* INPUT: msg_num (message number to display) */
516/* outline (substitution parameter) */
517/* */
518/* OUTPUT: none */
519/* */
520/* ERROR EXIT: Display error message corresponding to number */
521/* returned in AX. */
522/* */
523/* EXTERNAL REF: SYSDISPMSG */
524/* */
525/**************************************************************************/
526
527display_msg(msg_num,outline) /* ;AN000;M */
528int msg_num ; /* ;AN000;M Message number #define'd */
529char *outline ; /* ;AN001; Substitution parameter */
530{ /* ;AN000;M */
531 unsigned char function ; /* ;AN000;M Y/N response or press key? */
532 unsigned int message, /* ;AN000;M Message number to display */
533 msg_class, /* ;AN000;M Which class of messages? */
534 sub_cnt, /* ;AN000;M Number of substitutions? */
535 handle ; /* ;AN000;M Display where? */
536
537 struct sublist /* ;AN000;M */
538 { /* ;AN000;M */
539 unsigned char size ; /* ;AN000;M Points to next sublist */
540 unsigned char reserved ; /* ;AN000;M Required for sysdispmsg */
541 unsigned far *value ; /* ;AN000;M Data pointer */
542 unsigned char id ; /* ;AN000;M Id of substitution parm (%1) */
543 unsigned char flags ; /* ;AN000;M Format of data - (a0sstttt) */
544 unsigned char max_width ; /* ;AN000;M Maximum field width */
545 unsigned char min_width ; /* ;AN000;M Minimum field width */
546 unsigned char pad_char ; /* ;AN000;M char to pad field */
547 } sublist ; /* ;AN000;M */
548
549 switch (msg_num) /* ;AN000;M Which msg to display? */
550 { /* ;AN000;M */
551 case MSG_PARMNUM : function = NO_INPUT ; /* ;AN000;M Y/N response or press key? */
552 message = 2 ; /* ;AN000;M Message number to display */
553 msg_class = UTILITY_CLASS ; /* ;AN000;M Which class of messages? */
554 sub_cnt = SUBCNT1 ; /* ;AN000;M Number of substitutions? */
555 handle = STDERR ; /* ;AN000;M Display where? */
556 break ; /* ;AN000;M */
557 case MSG_BADPATH : function = NO_INPUT ; /* ;AN000;M Y/N response or press key? */
558 message = 3 ; /* ;AN000;M Message number to display */
559 msg_class = EXT_ERR_CLASS ; /* ;AN000;M Which class of messages? */
560 sub_cnt = SUBCNT1 ; /* ;AN000;M Number of substitutions? */
561 handle = STDERR ; /* ;AN000;M Display where? */
562 break ; /* ;AN000;M */
563 case MSG_NOMEM : function = NO_INPUT ; /* ;AN000;M Y/N response or press key? */
564 message = 8 ; /* ;AN000;M Message number to display */
565 msg_class = EXT_ERR_CLASS ; /* ;AN000;M Which class of messages? */
566 sub_cnt = SUBCNT0 ; /* ;AN000;M Number of substitutions? */
567 handle = STDERR ; /* ;AN000;M Display where? */
568 break ; /* ;AN000;M */
569 case MSG_BADPARM : function = NO_INPUT ; /* ;AN000;M Y/N response or press key? */
570 message = 10 ; /* ;AN000;M Message number to display */
571 msg_class = PARSE_ERR_CLASS ; /* ;AN000;M Which class of messages? */
572 sub_cnt = SUBCNT1 ; /* ;AN000;M Number of substitutions? */
573 handle = STDERR ; /* ;AN000;M Display where? */
574 break ; /* ;AN000;M */
575 case MSG_NETERR : function = NO_INPUT ; /* ;AN000;M Y/N response or press key? */
576 message = 12 ; /* ;AN000;M Message number to display */
577 msg_class = UTILITY_CLASS ; /* ;AN000;M Which class of messages? */
578 sub_cnt = SUBCNT1 ; /* ;AN000;M Number of substitutions? */
579 handle = STDERR ; /* ;AN000;M Display where? */
580 break ; /* ;AN000;M */
581 case MSG_INVSWTCH: function = NO_INPUT ; /* ;AN000;M Y/N response or press key? */
582 message = 3 ; /* ;AN000;M Message number to display */
583 msg_class = PARSE_ERR_CLASS ; /* ;AN000;M Which class of messages? */
584 sub_cnt = SUBCNT1 ; /* ;AN000;M Number of substitutions? */
585 handle = STDERR ; /* ;AN000;M Display where? */
586 break ; /* ;AN000;M */
587 default : exit(ERRORLEVEL1) ; /* ;AN000;M */
588 break ; /* ;AN000;M */
589 } /* ;AN000;M */
590
591 switch (msg_num) /* ;AN000;M */
592 { /* ;AN000;M */
593 case MSG_NOMEM : inregs.x.ax = message ; /* ;AN000;M Insufficient memory */
594 inregs.x.bx = handle ; /* ;AN000;M STDERR */
595 inregs.x.cx = sub_cnt ; /* ;AN000;M SUBCNT0 */
596 inregs.h.dl = function ; /* ;AN000;M NO_INPUT */
597 inregs.h.dh = msg_class ; /* ;AN000;M Extended, Parse or Utility */
598 sysdispmsg(&inregs,&outregs) ; /* ;AN000;M Call common msg service */
599 break ; /* ;AN000;M */
600 case MSG_INVSWTCH: /* ;AN000;M Invalid switch */
601 case MSG_PARMNUM : /* ;AN000;M Incorrect num of parms */
602 case MSG_BADPARM : /* ;AN000;M Invalid parameter */
603 case MSG_BADPATH : sublist.value = (unsigned far *)outline ; /* ;AN000;M Path not found */
604 sublist.reserved = RESERVED ; /* ;AN000;M */
605 sublist.id = SUB_ID0 ; /* ;AN000;M */
606 sublist.flags = STR_INPUT ; /* ;AN000;M */
607 sublist.max_width = MAXWIDTH ; /* ;AN000;M */
608 sublist.min_width = MINWIDTH ; /* ;AN000;M */
609 sublist.pad_char = (unsigned char)BLNK ; /* ;AN000;M */
610 inregs.x.ax = message ; /* ;AN000;M Cannot SUBST a network drive */
611 inregs.x.bx = handle ; /* ;AN000;M STDERR */
612 inregs.x.si = (unsigned int)&sublist ; /* ;AN000;M Point to the sub buffer */
613 inregs.x.cx = sub_cnt ; /* ;AN000;M SUBCNT1 */
614 inregs.h.dl = function ; /* ;AN000;M STR_INPUT */
615 inregs.h.dh = msg_class ; /* ;AN000;M Extended, Parse or Utility */
616 sysdispmsg(&inregs,&outregs) ; /* ;AN000;M Call common msg service */
617 break ; /* ;AN000;M */
618 case MSG_NETERR : sublist.value = (unsigned far *)replparm_SUBST ; /* ;AN000;M Cannot SUBST a network drive */
619 sublist.reserved = RESERVED ; /* ;AN000;M */
620 sublist.id = SUB_ID1 ; /* ;AN000;M */
621 sublist.flags = STR_INPUT ; /* ;AN000;M */
622 sublist.max_width = MAXWIDTH ; /* ;AN000;M */
623 sublist.min_width = MINWIDTH ; /* ;AN000;M */
624 sublist.pad_char = (unsigned char)BLNK ; /* ;AN000;M */
625 inregs.x.ax = message ; /* ;AN000;M Cannot SUBST a network drive */
626 inregs.x.bx = handle ; /* ;AN000;M STDERR */
627 inregs.x.si = (unsigned int)&sublist ; /* ;AN000;M Point to the sub buffer */
628 inregs.x.cx = sub_cnt ; /* ;AN000;M SUBCNT1 */
629 inregs.h.dl = function ; /* ;AN000;M STR_INPUT */
630 inregs.h.dh = msg_class ; /* ;AN000;M Extended, Parse or Utility */
631 sysdispmsg(&inregs,&outregs) ; /* ;AN000;M Call common msg service */
632 break ; /* ;AN000;M */
633 default : exit(ERRORLEVEL1) ; /* ;AN000;M */
634 break ; /* ;AN000;M */
635 } /* ;AN000;M */
636
637 if (outregs.x.cflag & CARRY) /* ;AN000;M Is the carry flag set? */
638 { /* ;AN000;M Then setup regs for extd-err */
639 inregs.x.bx = STDERR ; /* ;AN000;M */
640 inregs.x.cx = SUBCNT0 ; /* ;AN000;M */
641 inregs.h.dl = NO_INPUT ; /* ;AN000;M */
642 inregs.h.dh = EXT_ERR_CLASS ; /* ;AN000;M */
643 sysdispmsg(&inregs,&outregs) ; /* ;AN000;M Call to display ext_err msg */
644 exit(ERRORLEVEL1) ; /* ;AN000;M */
645 } /* ;AN000;M */
646 return ; /* ;AN000;M */
647} /* ;AN000;M */
648/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
649/**************************************************************************/
650/* */
651/* SUBROUTINE NAME: dispmsg_terminate */
652/* */
653/* SUBROUTINE FUNCTION: Display the message, then terminate the utility.*/
654/* */
655/* INPUT: msg_num (#define'd message to display) */
656/* outline (substitution parameter) */
657/* */
658/**************************************************************************/
659
660dispmsg_terminate(msg_num,outline) /* ;AN000;P */
661int msg_num ; /* ;AN000;P Message number #define'd */
662char *outline ; /* ;AN001; Substitution parameter */
663{ /* ;AN000;P */
664 display_msg(msg_num,outline) ; /* ;AN000;P First, display the msg */
665 exit(ERRORLEVEL1) ; /* ;AN000;P Then, terminate utility */
666} /* ;AN000;P */
667/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
668/**************************************************************************/
669/* */
670/* SUBROUTINE NAME: Parser_Prep */
671/* */
672/* SUBROUTINE FUNCTION: Initialize all structures for the parser. */
673/* */
674/* INPUT: source (command line string) */
675/* */
676/* OUTPUT: none */
677/* */
678/* EXTERNAL REF: parse */
679/* */
680/**************************************************************************/
681
682Parser_Prep(source) /* ;AN000;P */
683char *source ; /* ;AN000;P Commandline */
684{ /* ;AN000;P */
685 p_p.p_parmsx_address = &p_px ; /* ;AN000;P Address of extended parm list */
686 p_p.p_num_extra = 0 ; /* ;AN000;P No extra declarations */
687
688 p_px.p_minp = MINPOSITION ; /* ;AN000;P */
689 p_px.p_maxp = MAXPOSITION ; /* ;AN000;P */
690 p_px.p_control1 = &p_con1 ; /* ;AN000;P Point to 1st control blk */
691 p_px.p_control2 = &p_con2 ; /* ;AN000;P Point to 2nd control blk */
692 p_px.p_maxs = 1 ; /* ;AN000;P Specify # of switches */
693 p_px.p_switch = &p_swi1 ; /* ;AN000;P Point to the switch blk */
694 p_px.p_maxk = 0 ; /* ;AN000;P Specify # of keywords */
695
696 p_con1.p_match_flag = DRVONLY_OPT ; /* ;AN000;P Drive only & optional */
697 p_con1.p_function_flag = NOCAPPING ; /* ;AN000;P Cap result by file table */
698 p_con1.p_result_buf = (unsigned int)&rslt1 ; /* ;AN000;P Point to result blk */
699 p_con1.p_value_list = (unsigned int)&novals ; /* ;AN000;P Point to no value list */
700 p_con1.p_nid = 0 ; /* ;AN000;P Not a switch id */
701
702 p_con2.p_match_flag = FILESPEC_OPT ; /* ;AN000;P File spec & optional */
703 p_con2.p_function_flag = CAPRESULT ; /* ;AN000;P Cap result by file table */
704 p_con2.p_result_buf = (unsigned int)&rslt2 ; /* ;AN000;P Point to result blk */
705 p_con2.p_value_list = (unsigned int)&novals ; /* ;AN000;P Point to no value list */
706 p_con2.p_nid = 0 ; /* ;AN000;P Not a switch id */
707
708 p_swi1.sp_match_flag = SWITCH_OPT ; /* ;AN000;P Optional (switch) */
709 p_swi1.sp_function_flag = NOCAPPING ; /* ;AN000;P Cap result by file table */
710 p_swi1.sp_result_buf = (unsigned int)&rslt3 ; /* ;AN000;P Point to result blk */
711 p_swi1.sp_value_list = (unsigned int)&novals ; /* ;AN000;P Point to no value list */
712 p_swi1.sp_nid = 1 ; /* ;AN000;P One switch allowed */
713 strcpy(p_swi1.sp_keyorsw,D_SWITCH) ; /* ;AN000;P Identify the switch */
714
715 inregs.x.cx = 0 ; /* ;AN000;P Operand ordinal */
716 inregs.x.di = (unsigned int)&p_p ; /* ;AN000;P Address of parm list */
717 inregs.x.si = (unsigned int)source ; /* ;AN000;P Make DS:SI point to source */
718 return ; /* ;AN000; */
719} /* ;AN000;P */
diff --git a/v4.0/src/CMD/SUBST/SUBST.LNK b/v4.0/src/CMD/SUBST/SUBST.LNK
new file mode 100644
index 0000000..f0a8493
--- /dev/null
+++ b/v4.0/src/CMD/SUBST/SUBST.LNK
@@ -0,0 +1,12 @@
1SUBST.OBJ+
2..\..\inc\ERRTST.OBJ+
3..\..\inc\SYSVAR.OBJ+
4..\..\inc\CDS.OBJ+
5..\..\inc\DPB.OBJ+
6_MSGRET.OBJ+
7_PARSE.OBJ
8SUBST
9NUL
10..\..\inc\comsubs.lib+
11..\..\mapper\mapper.lib;
12 \ No newline at end of file
diff --git a/v4.0/src/CMD/SUBST/SUBST.SKL b/v4.0/src/CMD/SUBST/SUBST.SKL
new file mode 100644
index 0000000..fa33102
--- /dev/null
+++ b/v4.0/src/CMD/SUBST/SUBST.SKL
@@ -0,0 +1,22 @@
1;SUBST Utility ;AN000;
2;Message Service Routine ;AN000;
3
4:util SUBST ;BEGIN UTIL ;AN000;
5
6:class 1 ;EXTENDED ERRORS ;AN000;
7;------- ---------------
8;:use EXTEND3 ;Path not found
9;:use EXTEND8 ;Insufficient memory
10
11:class 2 ;PARSE ERRORS ;AN000;
12;------- ------------
13;:use PARSE3 ;Invalid switch
14;:use PARSE10 ;Invalid parameter ;AN000;
15
16:class A ;COMMON & DEFINED MSGS ;AN000;
17;------- ------------
18:use 1 COMMON1 ;Incorrect DOS version ;AN000;
19:def 2 "Incorrect number of parameters",CR,LF ;AN000;
20:use 12 COMMON12 ;Cannot %1 a network drive ;AN000;
21
22:end ;END UTIL ;AN000;
diff --git a/v4.0/src/CMD/SUBST/SUBSTPAR.H b/v4.0/src/CMD/SUBST/SUBSTPAR.H
new file mode 100644
index 0000000..2f985d5
--- /dev/null
+++ b/v4.0/src/CMD/SUBST/SUBSTPAR.H
@@ -0,0 +1,155 @@
1/*  */
2/*----------------------------------------------------------------------+
3| |
4| This file contains the structures and defines that are needed to use |
5| the parser from a C program. |
6| ** customized for the JOIN and SUBST utilities ** |
7| |
8| Date: 5-21-87 |
9| |
10+----------------------------------------------------------------------*/
11
12
13struct p_parms
14 {
15 struct p_parmsx *p_parmsx_address; /* address of p_parmsx */
16 unsigned char p_num_extra; /* number of extra stuff */
17 };
18
19struct p_parmsx
20 {
21 unsigned char p_minp; /* Minimum positional number */
22 unsigned char p_maxp; /* Maximum positional number */
23 struct p_control_blk *p_control1; /* Address of the 1st CONTROL block */
24 struct p_control_blk *p_control2; /* Address of the 2nd CONTROL block */
25 unsigned char p_maxs; /* Maximun switches */
26 struct p_switch_blk *p_switch; /* Address of the SWITCH block */
27 unsigned char p_maxk; /* Maximum keywords */
28 };
29
30
31struct p_control_blk
32 {
33 unsigned int p_match_flag; /* Controls type matched */
34 unsigned int p_function_flag; /* Function should be taken */
35 unsigned int p_result_buf; /* Result buffer address */
36 unsigned int p_value_list; /* Value list address */
37 unsigned char p_nid; /* # of keyword/SW synonyms */
38 };
39
40struct p_switch_blk
41 {
42 unsigned int sp_match_flag; /* Controls type matched */
43 unsigned int sp_function_flag; /* Function should be taken */
44 unsigned int sp_result_buf; /* Result buffer address */
45 unsigned int sp_value_list; /* Value list address */
46 unsigned char sp_nid; /* # of keyword/SW synonyms */
47 unsigned char sp_keyorsw[3]; /* keyword or sw */
48 };
49
50/* Match_Flags */
51
52#define P_Num_Val 0x8000 /* Numeric Value */
53#define P_SNum_Val 0x4000 /* Signed numeric value */
54#define P_Simple_S 0x2000 /* Simple string */
55#define P_Date_S 0x1000 /* Date string */
56#define P_Time_S 0x0800 /* Time string */
57#define P_Cmpx_S 0x0400 /* Complex string */
58#define P_File_Spc 0x0200 /* File Spec */
59#define P_Drv_Only 0x0100 /* Drive Only */
60#define P_Qu_String 0x0080 /* Quoted string */
61#define P_Ig_Colon 0x0010 /* Ignore colon at end in match */
62#define P_Repeat 0x0002 /* Repeat allowed */
63#define P_Optional 0x0001 /* Optional */
64
65/*----------------------------------------------------------------------+
66| |
67| Function flags |
68| |
69+----------------------------------------------------------------------*/
70
71#define P_CAP_File 0x0001 /* CAP result by file table */
72#define P_CAP_Char 0x0002 /* CAP result by character table */
73#define P_Rm_Colon 0x0010 /* Remove ":" at the end */
74
75
76
77#define P_nval_None 0 /* no value list ID */
78#define P_nval_Range 1 /* range list ID */
79#define P_nval_Value 2 /* value list ID */
80#define P_nval_String 3 /* string list ID */
81#define P_Len_Range 9 /* Length of a range choice(two DD plus one DB) */
82#define P_Len_Value 5 /* Length of a value choice(one DD plus one DB) */
83#define P_Len_String 3 /* Length of a string choice(one DW plus one DB) */
84
85
86/*----------------------------------------------------------------------+
87| |
88| Result block structure |
89| |
90+----------------------------------------------------------------------*/
91
92struct p_result_blk
93 {
94 unsigned char P_Type; /* Type returned */
95 unsigned char P_Item_Tag; /* Matched item tag */
96 unsigned int P_SYNONYM_Ptr; /* pointer to Synonym list returned */
97 unsigned int p_result_buff[2]; /* result value */
98 };
99
100struct p_fresult_blk
101 {
102 unsigned char fP_Type; /* Type returned */
103 unsigned char fP_Item_Tag; /* Matched item tag */
104 unsigned int fP_SYNONYM_Ptr; /* pointer to Synonym list returned */
105 char far * fp_result_buff; /* result value */
106 };
107
108/*----------------------------------------------------------------------+
109| |
110| type |
111| |
112+----------------------------------------------------------------------*/
113
114#define P_EOL 0 /* End of line */
115#define P_Number 1 /* Number */
116#define P_List_Idx 2 /* List Index */
117#define P_String 3 /* String */
118#define P_Complex 4 /* Complex */
119#define P_File_Spec 5 /* File Spec */
120#define P_Drive 6 /* Drive */
121#define P_Date_F 7 /* Date */
122#define P_Time_F 8 /* Time */
123#define P_Quoted_String 9 /* Quoted String */
124
125#define P_No_Tag 0x0FF /* No ITEM_TAG found */
126
127/*----------------------------------------------------------------------+
128| |
129| Value list structure |
130| |
131+----------------------------------------------------------------------*/
132
133struct noval
134 {
135 unsigned char null;
136 };
137
138/*----------------------------------------------------------------------+
139| |
140| following return code will be returned in the AX register. |
141| |
142+----------------------------------------------------------------------*/
143
144#define P_No_Error 0 /* No error */
145#define P_Too_Many 1 /* Too many operands */
146#define P_Op_Missing 2 /* Required operand missing */
147#define P_Not_In_SW 3 /* Not in switch list provided */
148#define P_Not_In_Key 4 /* Not in keyword list provided */
149#define P_Out_Of_Range 6 /* Out of range specified */
150#define P_Not_In_Val 7 /* Not in value list provided */
151#define P_Not_In_Str 8 /* Not in string list provided */
152#define P_Syntax 9 /* Syntax error */
153#define P_RC_EOL 0x0ffff /* End of command line */
154
155
diff --git a/v4.0/src/CMD/SUBST/_MSGRET.ASM b/v4.0/src/CMD/SUBST/_MSGRET.ASM
new file mode 100644
index 0000000..cded0ff
--- /dev/null
+++ b/v4.0/src/CMD/SUBST/_MSGRET.ASM
@@ -0,0 +1,250 @@
1page 60,132
2name _msgret
3title C to Message Retriever
4;-------------------------------------------------------------------
5;
6; MODULE: _msgret
7;
8; PURPOSE: Supplies an interface between C programs and
9; the DOS 3.3 message retriever
10;
11; CALLING FORMAT:
12; sysloadmsg(&inregs,&outregs);
13; sysgetmsg(&inregs,&outregs);
14; sysdispmsg(&inregs,&outregs);
15;
16; DATE: 5-21-87
17;
18;-------------------------------------------------------------------
19
20 INCLUDE SYSMSG.INC ;PERMIT SYSTEM MESSAGE HANDLER DEFINITION;AN000;
21
22 MSG_UTILNAME <SUBST> ;IDENTIFY THE COMPONENT ;AN000;
23
24 .8087 ;AN000;
25_TEXT SEGMENT BYTE PUBLIC 'CODE' ;AN000;
26_TEXT ENDS ;AN000;
27_DATA SEGMENT WORD PUBLIC 'DATA' ;AN000;
28_DATA ENDS ;AN000;
29CONST SEGMENT WORD PUBLIC 'CONST' ;AN000;
30CONST ENDS ;AN000;
31_BSS SEGMENT WORD PUBLIC 'BSS' ;AN000;
32_BSS ENDS ;AN000;
33DGROUP GROUP CONST, _BSS, _DATA ;AN000;
34 ASSUME CS: _TEXT, DS: _TEXT, SS: DGROUP, ES: DGROUP ;AN000;
35
36
37 public _sysloadmsg ;AN000;
38 public _sysgetmsg ;AN000;
39 public _sysdispmsg ;AN000;
40
41;-------------------------------------------------------------------
42;-------------------------------------------------------------------
43
44_DATA segment ;AN000;
45.XLIST ;AN000;
46.XCREF ;AN000;
47 MSG_SERVICES <MSGDATA> ;DATA AREA FOR THE MESSAGE HANDLER ;AN000;
48.LIST ;AN000;
49.CREF ;AN000;
50_DATA ends ;AN000;
51
52
53_TEXT segment ;AN000;
54
55;-------------------------------------------------------------------
56
57; = = = = = = = = = = = =
58
59 ;DEFAULT=CHECK DOS VERSION ;AN000;
60 ;DEFAULT=NEARmsg ;AN000;
61 ;DEFAULT=INPUTmsg ;AN000;
62 ;DEFAULT=NUMmsg ;AN000;
63 ;DEFAULT=NO TIMEmsg ;AN000;
64 ;DEFAULT=NO DATEmsg ;AN000;
65; MSG_SERVICES <LOADmsg,GETmsg,DISPLAYmsg,CHARmsg,NUMmsg,TIMEmsg,DATEmsg,INPUTmsg,FARmsg>;AN000;
66; MSG_SERVICES <SUBST.CLA,SUBST.CL1,SUBST.CL2> ;MSG TEXT ;AN000;
67.XLIST ;AN000;
68.XCREF ;AN000;
69; MSG_SERVICES <MSGDATA> ;DATA AREA FOR THE MESSAGE HANDLER ;AN000;
70 MSG_SERVICES <LOADmsg,GETmsg,DISPLAYmsg,CHARmsg,NUMmsg,TIMEmsg,DATEmsg,INPUTmsg,FARmsg>;AN000;
71 MSG_SERVICES <SUBST.CLA,SUBST.CL1,SUBST.CL2> ;MSG TEXT ;AN000;
72.LIST ;AN000;
73.CREF ;AN000;
74;-------------------------------------------------------------------
75
76_sysloadmsg proc near ;AN000;
77
78 push bp ; save user's base pointer ;AN000;
79 mov bp,sp ; set bp to current sp ;AN000;
80 push di ; save some registers ;AN000;
81 push si ;AN000;
82
83; copy C inregs into proper registers
84
85 mov di,[bp+4] ; fix di (arg 0) ;AN000;
86
87;-------------------------------------------------------------------
88
89 mov ax,[di+0ah] ; load di ;AN000;
90 push ax ; the di value from inregs is now on stack;AN000;
91
92 mov ax,[di+00] ; get inregs.x.ax ;AN000;
93 mov bx,[di+02] ; get inregs.x.bx ;AN000;
94 mov cx,[di+04] ; get inregs.x.cx ;AN000;
95 mov dx,[di+06] ; get inregs.x.dx ;AN000;
96 mov si,[di+08] ; get inregs.x.si ;AN000;
97 pop di ; get inregs.x.di from stack ;AN000;
98
99 push bp ; save base pointer ;AN000;
100
101;-------------------------------------------------------------------
102 call sysloadmsg ; call the message retriever ;AN000;
103;-------------------------------------------------------------------
104
105 pop bp ; restore base pointer ;AN000;
106 push di ; the di value from call is now on stack;AN000;
107 mov di,[bp+6] ; fix di (arg 1) ;AN000;
108
109 mov [di+00],ax ; load outregs.x.ax ;AN000;
110 mov [di+02],bx ; load outregs.x.bx ;AN000;
111 mov [di+04],cx ; load outregs.x.cx ;AN000;
112 mov [di+06],dx ; load outregs.x.dx ;AN000;
113 mov [di+08],si ; load outregs.x.si ;AN000;
114
115 lahf ; get flags into ax ;AN000;
116 mov al,ah ; move into low byte ;AN000;
117 mov [di+0ch],ax ; load outregs.x.cflag ;AN000;
118
119 pop ax ; get di from stack ;AN000;
120 mov [di+0ah],ax ; load outregs.x.di ;AN000;
121
122;-------------------------------------------------------------------
123
124 pop si ; restore registers ;AN000;
125 pop di ;AN000;
126 mov sp,bp ; restore sp ;AN000;
127 pop bp ; restore user's bp ;AN000;
128 ret ;AN000;
129
130_sysloadmsg endp ;AN000;
131
132
133_sysgetmsg proc near ;AN000;
134
135 push bp ; save user's base pointer ;AN000;
136 mov bp,sp ; set bp to current sp ;AN000;
137 push di ; save some registers ;AN000;
138 push si ;AN000;
139 ;AN000;
140; copy C inregs into proper registers
141
142 mov di,[bp+4] ; fix di (arg 0) ;AN000;
143
144;-------------------------------------------------------------------
145
146 mov ax,[di+0ah] ; load di ;AN000;
147 push ax ; the di value from inregs is now on stack;AN000;
148
149 mov ax,[di+00] ; get inregs.x.ax ;AN000;
150 mov bx,[di+02] ; get inregs.x.bx ;AN000;
151 mov cx,[di+04] ; get inregs.x.cx ;AN000;
152 mov dx,[di+06] ; get inregs.x.dx ;AN000;
153 mov si,[di+08] ; get inregs.x.si ;AN000;
154 pop di ; get inregs.x.di from stack ;AN000;
155
156 push bp ; save base pointer ;AN000;
157
158;-------------------------------------------------------------------
159 call sysgetmsg ; call the message retriever ;AN000;
160;-------------------------------------------------------------------
161
162 pop bp ; restore base pointer ;AN000;
163 push di ; the di value from call is now on stack;AN000;
164 mov di,[bp+6] ; fix di (arg 1) ;AN000;
165
166 mov [di+00],ax ; load outregs.x.ax ;AN000;
167 mov [di+02],bx ; load outregs.x.bx ;AN000;
168 mov [di+04],cx ; load outregs.x.cx ;AN000;
169 mov [di+06],dx ; load outregs.x.dx ;AN000;
170 mov [di+08],si ; load outregs.x.si ;AN000;
171
172 lahf ; get flags into ax ;AN000;
173 mov al,ah ; move into low byte ;AN000;
174 mov [di+0ch],ax ; load outregs.x.cflag ;AN000;
175
176 pop ax ; get di from stack ;AN000;
177 mov [di+0ah],ax ; load outregs.x.di ;AN000;
178
179;-------------------------------------------------------------------
180
181 pop si ; restore registers ;AN000;
182 pop di ;AN000;
183 mov sp,bp ; restore sp ;AN000;
184 pop bp ; restore user's bp ;AN000;
185 ret ;AN000;
186
187_sysgetmsg endp ;AN000;
188
189_sysdispmsg proc near ;AN000;
190
191 push bp ; save user's base pointer ;AN000;
192 mov bp,sp ; set bp to current sp ;AN000;
193 push di ; save some registers ;AN000;
194 push si ;AN000;
195
196; copy C inregs into proper registers
197
198 mov di,[bp+4] ; fix di (arg 0) ;AN000;
199
200;-------------------------------------------------------------------
201
202 mov ax,[di+0ah] ; load di ;AN000;
203 push ax ; the di value from inregs is now on stack;AN000;
204
205 mov ax,[di+00] ; get inregs.x.ax ;AN000;
206 mov bx,[di+02] ; get inregs.x.bx ;AN000;
207 mov cx,[di+04] ; get inregs.x.cx ;AN000;
208 mov dx,[di+06] ; get inregs.x.dx ;AN000;
209 mov si,[di+08] ; get inregs.x.si ;AN000;
210 pop di ; get inregs.x.di from stack ;AN000;
211
212 push bp ; save base pointer ;AN000;
213
214;-------------------------------------------------------------------
215 call sysdispmsg ; call the message retriever ;AN000;
216;-------------------------------------------------------------------
217
218 pop bp ; restore base pointer ;AN000;
219 push di ; the di value from call is now on stack;AN000;
220 mov di,[bp+6] ; fix di (arg 1) ;AN000;
221
222 mov [di+00],ax ; load outregs.x.ax ;AN000;
223 mov [di+02],bx ; load outregs.x.bx ;AN000;
224 mov [di+04],cx ; load outregs.x.cx ;AN000;
225 mov [di+06],dx ; load outregs.x.dx ;AN000;
226 mov [di+08],si ; load outregs.x.si ;AN000;
227
228 lahf ; get flags into ax ;AN000;
229 mov al,ah ; move into low byte ;AN000;
230 mov [di+0ch],ax ; load outregs.x.cflag ;AN000;
231
232 pop ax ; get di from stack ;AN000;
233 mov [di+0ah],ax ; load outregs.x.di ;AN000;
234
235;-------------------------------------------------------------------
236
237 pop si ; restore registers ;AN000;
238 pop di ;AN000;
239 mov sp,bp ; restore sp ;AN000;
240 pop bp ; restore user's bp ;AN000;
241 ret ;AN000;
242
243_sysdispmsg endp ;AN000;
244
245include msgdcl.inc
246
247_TEXT ends ; end code segment ;AN000;
248 end ;AN000;
249
250 \ No newline at end of file
diff --git a/v4.0/src/CMD/SUBST/_PARSE.ASM b/v4.0/src/CMD/SUBST/_PARSE.ASM
new file mode 100644
index 0000000..8c44df5
--- /dev/null
+++ b/v4.0/src/CMD/SUBST/_PARSE.ASM
@@ -0,0 +1,121 @@
1page 60,132
2name _parse
3title C to PARSER interface
4;-------------------------------------------------------------------
5;
6; MODULE: _parse
7;
8; PURPOSE: Supplies an interface between C programs and
9; the DOS 3.3 parser
10;
11; **(Customized for the SUBST utility)
12;
13; CALLING FORMAT:
14; parse(&inregs,&outregs);
15;
16; DATE: 5-21-87
17;
18;-------------------------------------------------------------------
19
20; extrn sysparse:far
21
22 public _parse ;AN000;
23
24;-------------------------------------------------------------------
25
26; set for SUBST
27; -------------
28
29FarSW equ 0 ; make sysparse be a NEAR proc ;AN000;
30TimeSW equ 0 ; Check time format ;AN000;
31FileSW equ 1 ; Check file specification ;AN000;
32CAPSW equ 1 ; Perform CAPS if specified ;AN000;
33CmpxSW equ 0 ; Check complex list ;AN000;
34NumSW equ 0 ; Check numeric value ;AN000;
35KeySW equ 0 ; Support keywords ;AN000;
36SwSW equ 1 ; Support switches ;AN000;
37Val1SW equ 0 ; Support value definition 1 ;AN000;
38Val2SW equ 0 ; Support value definition 2 ;AN000;
39Val3SW equ 0 ; Support value definition 3 ;AN000;
40DrvSW equ 1 ; Support drive only format ;AN000;
41QusSW equ 0 ; Support quoted string format ;AN000;
42;-------------------------------------------------------------------
43
44DGROUP GROUP _DATA
45PGROUP GROUP _TEXT
46
47_DATA segment byte public 'DATA' ;AN000;
48BASESW = 1 ;SPECIFY, PSDATA POINTED TO BY "DS"
49INCSW = 0 ;PSDATA.INC IS ALREADY INCLUDED
50 INCLUDE PSDATA.INC ;PARSER'S WORK SPACE
51_DATA ends ;AN000;
52
53_TEXT segment byte public 'CODE' ;AN000;
54
55 ASSUME CS: PGROUP ;AN000;
56 ASSUME DS: DGROUP ;AN000;
57
58;-------------------------------------------------------------------
59include parse.asm ; include the parser ;AN000;
60;-------------------------------------------------------------------
61
62_parse proc near ;AN000;
63
64 push bp ; save user's base pointer ;AN000;
65 mov bp,sp ; set bp to current sp ;AN000;
66 push di ; save some registers ;AN000;
67 push si ;AN000;
68
69; copy C inregs into proper registers
70
71 mov di,[bp+4] ; fix di (arg 0) ;AN000;
72
73;-------------------------------------------------------------------
74
75 mov ax,[di+0ah] ; load di ;AN000;
76 push ax ; the di value from inregs is now on stack;AN000;
77
78 mov ax,[di+00] ; get inregs.x.ax ;AN000;
79 mov bx,[di+02] ; get inregs.x.bx ;AN000;
80 mov cx,[di+04] ; get inregs.x.cx ;AN000;
81 mov dx,[di+06] ; get inregs.x.dx ;AN000;
82 mov si,[di+08] ; get inregs.x.si ;AN000;
83 pop di ; get inregs.x.di from stack ;AN000;
84
85 push bp ; save base pointer ;AN000;
86
87;-------------------------------------------------------------------
88 call sysparse ; call the parser ;AN000;
89;-------------------------------------------------------------------
90
91 pop bp ; restore base pointer ;AN000;
92 push di ; the di value from call is now on stack;AN000;
93 mov di,[bp+6] ; fix di (arg 1) ;AN000;
94
95 mov [di+00],ax ; load outregs.x.ax ;AN000;
96 mov [di+02],bx ; load outregs.x.bx ;AN000;
97 mov [di+04],cx ; load outregs.x.cx ;AN000;
98 mov [di+06],dx ; load outregs.x.dx ;AN000;
99 mov [di+08],si ; load outregs.x.si ;AN000;
100
101 lahf ; get flags into ax ;AN000;
102 mov al,ah ; move into low byte ;AN000;
103 mov [di+0ch],ax ; load outregs.x.cflag ;AN000;
104
105 pop ax ; get di from stack ;AN000;
106 mov [di+0ah],ax ; load outregs.x.di ;AN000;
107
108;-------------------------------------------------------------------
109
110 pop si ; restore registers ;AN000;
111 pop di ;AN000;
112 mov sp,bp ; restore sp ;AN000;
113 pop bp ; restore user's bp ;AN000;
114 ret ;AN000;
115
116_parse endp ;AN000;
117
118_TEXT ends ; end code segment ;AN000;
119 end ;AN000;
120
121 \ No newline at end of file