/* ----------------------------------------------------------------------- XPCBPATH Version 1.0, June 4, 1994. (c) 1994 Key Software Products. All Rights Reserved. This software is copyrighted. You are free to use it as you like, except: (1) If modified, you must keep the copyright notice in the source and executable code, and this comment in the source. (2) It may not be incorporated into a commercial product without the author's permission. ----------------------------------------------------------------------- This software has been compiled with the DeSmet C88 compiler and linker. ----------------------------------------------------------------------- */ #include #define PGM_NAME "XPCBPATH" #define VERSION "1.2" #define MAX_ENTRIES 100 #define STACK_SIZE 1024 #define PCBSIZE 31 #define DOSSIZE 80 /* drive+colon+path+slash+file+period+ext+null */ #define ENDOF(bfr) &bfr[strlen(bfr)] typedef struct PATH { char old[PCBSIZE] ; char new[DOSSIZE] ; } PATH ; char path[DOSSIZE] ; char rest[DOSSIZE] ; int entries = 0 ; PATH subst[MAX_ENTRIES] ; /* These functions must be in the resident portion of the code segment */ /* If we use the ones in the library, they'll be tacked on to the end */ /* of this code, and then discarded when we go TSR! */ #define strlen _strlen #define strncpy _strncpy #define toupper _toupper #define strncmpi _strncmpi void Sign_On(void) ; int showcs(void) ; int showds(void) ; void lmove(int, int, int, int, int) ; int strlen(char *) ; void strncpy(char *, char *, int) ; char toupper(char) ; int strncmpi(char *, char *, int) ; char *Fix_Path(char *, int) ; void TSR(int, int) ; void CS_End(void) ; int Substitute(int, char *[]) ; void Announce(int, char *, char *) ; void Usage(char *) ; void Int21() { #ifndef _lint #asm ;---------------------------------------------------------- New_Int21: ;---------------------------------------------------------- pushf ; Preserve flags sti cmp ah,3Bh ; Set current directory? je Subst cmp ah,3Dh ; Open file? je Subst cmp ax,4300h ; Get file attributes? je Subst cmp ah,4Eh ; Find first? je Subst popf ; Restore flags db 0EAh ; JMP FAR DIRECT Old_Int21 dw 0 ; offset dw 0 ; segment save_ss dw 0 save_sp dw 0 stack_seg dw 0 stack_ptr dw 0 Subst: add sp,2 ; Discard flags saved above ; Important input registers: AX, CX, DS:DX mov save_ss,ss ; preserve stack mov save_sp,sp mov ss,stack_seg ; establish my stack mov sp,stack_ptr push bx ; preserve irrelevant registers push si push di push es push ax ; preserve relevant registers push cx push ds ; parameter #2 (segment) push dx ; parameter #1 (offset) mov ds,stack_seg ; establish my data segment call Fix_Path_ ; returns DS:AX => new path mov dx,ax pop di ; save original DX in DI pop si ; save original DS in SI pop cx ; restore other relevant registers pop ax pushf ; Simulate INT 21h cli lcall DWORD Old_Int21 ; Don't change CF or AX after here! mov dx,di ; restore REAL DX mov ds,si ; restore REAL DS pop es ; restore irrelevant registers pop di pop si pop bx mov ss,save_ss mov sp,save_sp lret 2 #end #endif } int showds() { #ifndef _lint #asm mov ax,ds #end #endif } int showcs() { #ifndef _lint #asm mov ax,cs #end #endif } void lmove(bytes, src_off, src_seg, dst_off, dst_seg) int bytes ; int src_off ; int src_seg ; int dst_off ; int dst_seg ; { #ifndef _lint #asm push ds mov cx,#bytes les di,#dst_off lds si,#src_off cld rep movsb pop ds #end #endif } char *Fix_Path(off, seg) char *off ; int seg ; { int i, len ; PATH *p ; lmove(sizeof(path), off, seg, path, showds()) ; p = subst ; for (i = 0; i < entries; i++, p++) { /* Presort during load guarantees finding longest match */ if (!strncmpi(path, p->old, len = strlen(p->old))) { strncpy(rest, path + len, sizeof(rest) - 1) ; strncpy(path, p->new, sizeof(path) - 1) ; len = strlen(p->new) ; strncpy(path + len, rest, (DOSSIZE - 1) - len) ; break ; } } return path ; } int strlen(str) char *str ; { int len ; len = 0 ; while (*str++) len++ ; return len ; } void strncpy(dst, src, len) char *dst ; char *src ; int len ; { while (len-- && *src) *dst++ = *src++ ; *dst = '\0' ; } char toupper(ch) char ch ; { if ('a' <= ch && ch <= 'z') ch = ch - 'a' + 'A' ; return ch ; } int strncmpi(str1, str2, n) char *str1 ; char *str2 ; int n ; { int ch1, ch2, diff ; while (*str1 && *str2 && n--) { ch1 = toupper(*str1++) ; ch2 = toupper(*str2++) ; diff = ch1 - ch2 ; if (diff) return diff ; } return 0 ; } void TSR(stk_ptr, stk_seg) int stk_ptr ; int stk_seg ; { #ifndef _lint #asm mov ax,#stk_ptr mov WORD stack_ptr,ax mov ax,#stk_seg mov stack_seg,ax xor ax,ax mov ds,ax ; preserve old int 21h vector les ax,[4*21h] mov Old_Int21[0],ax mov Old_Int21[2],es ; modify int 21h vector cli mov WORD [4*21h+0],OFFSET New_Int21 mov WORD [4*21h+2],cs sti ; terminate but stay resident mov dx,stack_seg mov ax,cs sub dx,ax ; DX = para size of cseg mov ax,stack_ptr add ax,256+15 ; PSP plus rounding mov cl,4 shr ax,cl ; AX = stack paragraphs add dx,ax mov ax,3100h int 21h #end #endif } void main(argc, argv) int argc ; char *argv[] ; { int size, dseg ; Sign_On() ; entries = Substitute(argc, argv) ; dseg = showcs() + (((int) CS_End + 15) >> 4) ; size = subst + entries ; lmove(size, 0, showds(), 0, dseg) ; TSR(size + STACK_SIZE, dseg) ; } void CS_End() /* Only initialization code below here! */ { } int Substitute(argc, argv) int argc ; char *argv[] ; { int i, j, entries, len1, len2 ; static char bfr[100] ; char *p ; PATH temp ; FILE *fp ; if (argc != 2) Usage("Wrong number of command line arguments") ; fp = fopen(argv[1], "r") ; if (!fp) Usage("Can't find file") ; puts("") ; entries = 0 ; while (fgets(bfr, sizeof(bfr), fp)) { if (p = strchr(bfr, '\n')) *p = '\0' ; while (isspace(*bfr)) strcpy(bfr, bfr + 1) ; if (p = strpbrk(bfr, " \t")) { char *old, *new ; old = bfr ; *p++ = '\0' ; while (isspace(*p)) p++ ; new = p ; if (p = strpbrk(new, " \t")) *p = '\0' ; strncpy(subst[entries].old, old, PCBSIZE - 1) ; strncpy(subst[entries].new, new, DOSSIZE - 1) ; entries++ ; if (entries >= MAX_ENTRIES) break ; } } fclose(fp) ; for (i = 0; i < entries - 1; i++) { for (j = i + 1; j < entries; j++) { len1 = strlen(subst[i].old) ; len2 = strlen(subst[j].old) ; if (len1 < len2 || ((len1==len2) && strcmpi(subst[i].old, subst[j].old) < 0)) { temp = subst[i] ; subst[i] = subst[j] ; subst[j] = temp ; } } } for (i = 0; i < entries; i++) { Announce(i + 1, subst[i].old, subst[i].new) ; } return entries ; } void Announce(entry, old, new) int entry ; char *old ; char *new ; { char bfr[100], *p ; strcpy(bfr, "\t ") ; p = &bfr[1] ; if (entry < 100) p++ ; if (entry < 10) p++ ; ltoa((long) entry, p, 10) ; strcat(bfr, ": ") ; strcat(bfr, old) ; strcat(bfr, "\t ==> ") ; strcat(bfr, new) ; puts(bfr) ; } void Sign_On() { char bfr[100] ; strcpy(bfr, "\n") ; strcat(bfr, PGM_NAME) ; strcat(bfr, " v") ; strcat(bfr, VERSION) ; strcat(bfr, " (c) 1994 Key Software Products. All Rights Reserved."); puts(bfr) ; } void Usage(msg) char *msg ; { char bfr[100] ; strcpy(bfr, "\n\tError: ") ; strcat(bfr, msg) ; puts(bfr) ; strcpy(bfr, "\n\tUsage: ") ; strcat(bfr, PGM_NAME) ; strcat(bfr, " ") ; puts(bfr) ; exit(255) ; }