2 /**************************************************************************/
4 /* UTILITY NAME: Subst */
6 /* SOURCE FILE NAME: Subst.C */
8 /* STATUS: Subst Utility, DOS Version 4.0 */
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 */
15 /* SYNTAX: [d:][path]SUBST or */
16 /* [d:][path]SUBST d: d:path or */
17 /* [d:][path]SUBST d: /D */
19 /* [d:][path] to specify the drive and path that */
20 /* contains the SUBST command file */
22 /* d: specifies the drive letter that you want */
23 /* to use to refer to another drive or path. */
25 /* d:path to specify the drive or path that you */
26 /* want to refer to with a nickname. */
28 /* /D to delete a substitution. You must specify */
29 /* the letter of the drive whose substitution */
30 /* you want to delete. */
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 */
43 /* ERROR HANDLING: Error message displayed and utility is terminated. */
45 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
49 /* Converted to CMERGE 03/26/85 */
52 /* Changed low version check for specific 320. */
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. */
60 /* When there are only two operand make sure that there are no additional*/
61 /* switch characters. */
64 /* Altered pathname verification tests to so that the same error message */
68 /* Only allow 2 characters in the drive name specifier for delete (used */
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. */
77 /* AC000: Changed code for DOS Version 4.0 5/87 */
79 /* AN000: New code for DOS Version 4.0 5/87 */
80 /* AN000;M = message services */
81 /* AN000;P = parser service */
83 /* Ax001: Changed code req'd - PTM0003920 3/88 */
84 /* Incorrect message response */
86 /* Ax002: Changed code req'd - PTM0004045 3/88 */
87 /* Incomplete message response */
89 /**************************************************************************/
96 #include "substpar.h" /* ;AN000; Parser structures */
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 */
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 */
111 #define SWITCH_OPT 0x0000 /* ;AN000;P Optional switch */
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 */
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 */
140 /*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ MISCELLANEOUS ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
141 extern long GetDPB() ;
142 extern char fDelete() ; /* SM '87 compiler required extern */
143 extern char *malloc() ; /* SM '87 compiler required extern */
144 extern char *strbscan() ; /* SM '87 compiler required extern */
146 char cmdln_drive[64] = {0} ; /* ;AN002; Save user's input in */
147 char cmdln_flspec[64] = {0} ; /* ;AN002; order to pass to error */
148 char cmdln_invalid[64] = {0} ; /* ;AN002; */
149 char cmdln_switch[64] = {0} ; /* ;AN002; message, if needed */
150 char fix_es_reg[1] ; /* ;AN000;P Corrects es reg after type-"far" */
151 char p_drive[3] ; /* ;AN000;P Recvs drive ltr from parser */
152 char p_filespec[64] ; /* ;AN000;P Recvs filespec from parser */
153 char replparm_SUBST[] = "SUBST" ; /* ;AN000;P Cannot SUBST a network drv */
155 unsigned char source[MAX] = {0} ; /* ;AN000;P buffer for string manipulation */
157 int index ; /* ;AN000;P Used in creating cmdline string */
159 struct sysVarsType SysVars ;
161 /*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ PARSE STRUCTURES ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
162 struct p_parms p_p ; /* ;AN000;P # of extras & pts to descrptn */
163 struct p_parmsx p_px ; /* ;AN000;P min/max parms & pts to controls */
164 struct p_control_blk p_con1 ; /* ;AN000;P 1st posit parm in cmd str */
165 struct p_control_blk p_con2 ; /* ;AN000;P 2nd posit parm in cmd str */
166 struct p_switch_blk p_swi1 ; /* ;AN000;P /D switch in cmd str */
167 struct p_result_blk rslt1 ; /* ;AN000;P Result blk rtrnd from parser */
168 struct p_fresult_blk rslt2 ; /* ;AN000;P Result blk rtrnd from parser */
169 struct p_result_blk rslt3 ; /* ;AN000;P Result blk rtrnd from parser */
170 struct noval novals = {0} ; /* ;AN000;P Value list not used */
172 union REGS inregs, outregs ; /* ;AN000;P Define register variables */
174 /**************************************************************************/
176 /* SUBROUTINE NAME: main (program entry point) */
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 */
188 /* EXTERNAL ROUTINES: SYSLOADMSG */
192 /* INTERNAL ROUTINES: BackFix Load_Msg */
193 /* fDelete Display_Msg */
194 /* Insert Parser_Prep */
195 /* Display dispmsg_terminate */
197 /**************************************************************************/
203 char far * fptr ; /* ;AN000;P Pointer to parser's buffer */
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? */
211 /************************ BEGIN ***********************************************/
213 load_msg() ; /* ;AN000;M Point to msgs & chk DOS ver */
215 for (index = 1; index <= c; index++) /* ;AN000;P Loop through end of cmd line */
217 strcat(source,v[index]) ; /* ;AN000;P Add the argument */
218 strcat(source," ") ; /* ;AN000;P Separate with a space */
220 Parser_Prep(source) ; /* ;AN000;P Initialization for the parser */
222 while (more_to_parse) /* ;AN000;P test the flag */
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 */
228 if (outregs.x.dx == (unsigned short)&rslt1) /* ;AN000;P if result is drv ltr */
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; */
241 if (outregs.x.dx == (unsigned short)&rslt2) /* ;AN000;P if result is filespec */
243 for (fptr = rslt2.fp_result_buff; (char)*fptr != NULL; fptr++) /* ;AN000;P From beg of buf til nul */
245 p_filespec[fchar] = (char)*fptr ; /* ;AN000;P copy from rslt field buf */
246 fchar++ ; /* ;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; */
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; */
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 */
270 if (outregs.x.ax != P_RC_EOL) /* ;AN000;P there must be an error */
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; */
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 */
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 */
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 */
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 */
306 if (delflag && !pdrive_flg) /* ;AN000;P delete & no drive ? */
307 dispmsg_terminate(MSG_BADPARM,cmdln_switch) ; /* ;AN000;P display error msg & exit utility */
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 */
313 strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */
315 if (c == 1) /* display all tree aliases */
318 if (delflag) /* ;AC000;P Are we to delete a subst? */
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) */
325 Insert(p_drive,p_filespec) ; /* ;AC000;P */
329 /*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
338 while (*(p2 = strbscan(p1 = p2+1,"\\")) != NULL) ;
340 /* p1 points to char after last path sep. */
341 /* If this is a NULL, p already has a trailing path sep. */
344 if ((p1 = malloc(strlen(p)+2)) == NULL)
345 dispmsg_terminate(MSG_NOMEM) ; /* ;AN000;M */
354 /*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
362 /* M004 Only 2 characters in the drive specifier */
363 /* (and move before the call to BackFix) */
365 if (strlen(v) != 2 || v[1] != ':')
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 */
376 strcpy(CDS.text, "A:\\") ; /* Set-up text of curr directory */
377 CDS.text[0] += drive ;
378 CDS.cbEnd = 2 ; /* Set backup limit */
380 /* If physical, then mark as inuse and set-up DPB pointer */
382 CDS.flags = drive >= SysVars.cDrv ? FALSE : CDSINUSE ;
383 CDS.pDPB = drive >= SysVars.cDrv ? 0L : GetDPB(drive) ;
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) */
390 /*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
397 char buf[MAXPATHLEN] ;
401 if (strlen(d) == 2 && d[1] == ':')
402 dispmsg_terminate(MSG_BADPARM,cmdln_flspec) ; /* ;AC000;M Insure dest not just a drive */
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 */
408 /* M003 - path verification was treated as an ELSE condition */
409 /* else Must be subdir... make sure */
411 if (open(buf,O_BINARY) != -1)
412 dispmsg_terminate(MSG_BADPARM,cmdln_flspec) ; /* ;AC000;M */
414 if (access(buf,NULL) == -1)
415 dispmsg_terminate(MSG_BADPATH,cmdln_flspec) ; /* ;AC000;M */
422 if (fNet(drives)) /* Src can't be net drive, is reuse of CDS */
423 dispmsg_terminate(MSG_NETERR) ; /* ;AC000;M */
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 */
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 */
433 strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */
434 if (drives < 0 || drives >= SysVars.cCDS ||
436 !fGetCDS(drives, &CDS) ||
437 drives == getdrv() ||
438 TESTFLAG(CDS.flags,CDSNET|CDSSPLICE|CDSLOCAL))
439 dispmsg_terminate(MSG_BADPARM,cmdln_drive) ; /* ;AC000;M */
441 strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */
442 if (drived < 0 || drived >= SysVars.cCDS ||
443 strlen(d) >= DIRSTRLEN ||
445 dispmsg_terminate(MSG_BADPARM,cmdln_flspec) ; /* ;AC000;M */
447 strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */
448 if (strlen(d) != 3) /* Chop trailing \ if not at root */
451 strcpy(CDS.text, d) ;
452 CDS.cbEnd = strlen(CDS.text) ;
455 CDS.flags = CDSINUSE|CDSLOCAL ;
456 if ((CDS.pDPB = GetDPB(drived)) == -1L)
457 dispmsg_terminate(MSG_BADPARM,cmdln_flspec) ; /* ;AC000;M */
459 strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */
461 fPutCDS(drives, &CDS) ;
462 strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */
463 return ; /* ;AN000; */
465 /*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
467 Display() /* Display current list of substs */
472 for (i=0 ; fGetCDS(i, &CDS) ; i++)
473 if (TESTFLAG(CDS.flags,CDSLOCAL))
477 CDS.text[CDS.cbEnd] = 0 ;
478 printf("%c: => %s\n", i+'A', CDS.text) ;
480 return ; /* ;AN000; */
482 /*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
483 /**************************************************************************/
485 /* SUBROUTINE NAME: load_msg */
487 /* SUBROUTINE FUNCTION: Load the set of SUBST Utility messages to */
488 /* become available for display_msg call. */
490 /* ERROR EXIT: Utility will be terminated by sysloadmsg if */
491 /* version check is incorrect. */
493 /* EXTERNAL REF: SYSLOADMSG */
495 /**************************************************************************/
497 load_msg() /* ;AN000;M */
499 sysloadmsg(&inregs,&outregs) ; /* ;AN000;M Load utility messages */
500 if (outregs.x.cflag & CARRY) /* ;AN000;M If problem loading msgs */
502 sysdispmsg(&outregs,&outregs) ; /* ;AN000;M then display the err msg */
503 exit(ERRORLEVEL1) ; /* ;AN000;M */
505 return ; /* ;AN000;M */
507 /*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
508 /**************************************************************************/
510 /* SUBROUTINE NAME: display_msg */
512 /* SUBROUTINE FUNCTION: The correct message called by main is displayed */
513 /* to standard out. */
515 /* INPUT: msg_num (message number to display) */
516 /* outline (substitution parameter) */
520 /* ERROR EXIT: Display error message corresponding to number */
521 /* returned in AX. */
523 /* EXTERNAL REF: SYSDISPMSG */
525 /**************************************************************************/
527 display_msg(msg_num,outline) /* ;AN000;M */
528 int msg_num ; /* ;AN000;M Message number #define'd */
529 char *outline ; /* ;AN001; Substitution parameter */
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? */
537 struct sublist /* ;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 */
549 switch (msg_num) /* ;AN000;M Which msg to display? */
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 */
591 switch (msg_num) /* ;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 */
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 */
646 return ; /* ;AN000;M */
648 /*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
649 /**************************************************************************/
651 /* SUBROUTINE NAME: dispmsg_terminate */
653 /* SUBROUTINE FUNCTION: Display the message, then terminate the utility.*/
655 /* INPUT: msg_num (#define'd message to display) */
656 /* outline (substitution parameter) */
658 /**************************************************************************/
660 dispmsg_terminate(msg_num,outline) /* ;AN000;P */
661 int msg_num ; /* ;AN000;P Message number #define'd */
662 char *outline ; /* ;AN001; Substitution parameter */
664 display_msg(msg_num,outline) ; /* ;AN000;P First, display the msg */
665 exit(ERRORLEVEL1) ; /* ;AN000;P Then, terminate utility */
667 /*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
668 /**************************************************************************/
670 /* SUBROUTINE NAME: Parser_Prep */
672 /* SUBROUTINE FUNCTION: Initialize all structures for the parser. */
674 /* INPUT: source (command line string) */
678 /* EXTERNAL REF: parse */
680 /**************************************************************************/
682 Parser_Prep(source) /* ;AN000;P */
683 char *source ; /* ;AN000;P Commandline */
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 */
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 */
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 */
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 */
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 */
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; */