/* MYLIB.C Generic Library Functions */ /* Public Domain -- Gregg Jennings 1989-1995 */ /* This source file may be freely used and distributed without restriction. */ #include #include #include #include #include #include "mylib.h" #include "console.h" /* for console I/O (my print() etc.) */ /* The following are for DISKED use. The #ifdefs are for marking the DISKED specific code. These Should be removed for general usage. */ #ifdef DISKED #include "disked.h" static void displval(int x, int base, int c); static int getlnum(unsigned int max, unsigned *num, int base); #endif #define _tohex(c) ( (c<='9') ? (c-'0') : (c-'7') ) /* Convert two ASCII hex-valid chars to one hex number. A '0' and a 'd' returns the value 0x0d. The second argument can be a '\r'. No checking for validity. ver 1.1 9/91 fixed ascii mask error, added _tohex() macro ver 1.0 12/90 */ unsigned char hexbyte(register int a,register int b) { a=toupper(a); b=toupper(b); if (b=='\r') { /* swap if '\r' */ b=a; a='0'; } return((unsigned char)((_tohex(a)*16)+_tohex(b))); } /* * Display a number to the console with leading zeros or space * and a certain length, and any base from 2 to 36. * * pn print int number * pln print long number * * Returns: number of digits. * * ver 1.0 9/91 eliminated all but 2 divisions pln(), 3 in pn() * ver 0.1 12/90 */ int pn(unsigned int n, int base) { int r=1; int i; if (n/base) r+=pn(n/base,base); i=n%base; output((i>9) ? i+'A'-10 : i+'0'); return(r); } int pln(unsigned long n, int base) { int r=1; long l; int i; if (((l=n/(long)base))>0) r+=pln(l,base); i=(int)(n%(long)base); if (i>9) output(i+'A'-10); else output(i+'0'); return(r); } /* * Display a number to the console with leading zeros or space * and a certain length, and any base from 2 to 36. * * pnlz print number leading zero * pnls print number leading space * plnlz print long number leading zero * plnls print long number leading space * * ver 1.0 9/91 */ void pnlz(unsigned int n, unsigned int length, int base) { register int t; for (t=length-getlen(n,base);t>0;t--) output('0'); pn(n,base); } void pnls(unsigned int n, unsigned int length, int base) { register int t; for (t=length-getlen(n,base);t>0;t--) output(' '); pn(n,base); } void plnlz(unsigned long n, unsigned int length, int base) { register int i; for (i=length-getlength(n,base);i>0;i--) output('0'); pln(n,base); } void plnls(unsigned long n, unsigned int length, int base) { register int i; for (i=length-getlength(n,base);i>0;i--) output(' '); pln(n,base); } /* * get the display length (number of digits) of a * number, i.e. 100 dec returns 3, 64 hex (100 dec) * returns 2 */ int getlen(register unsigned int n, register int base) { int j; for (j = 1; n >= (unsigned int)base; n /= base,++j) ; return(j); } /* Get length of number. Pass: long number, int base (1 to 26). Returns: the number of digits the number needs to be displayed. ver 0.1 12/90 ver 0.2 3/91 changed to long */ int getlength(unsigned long l, int base) { register int r; for (r=1;l>=(unsigned long)base;l/=(long)base,++r) ; return(r); } /* Convert a string containing escape sequences to their correct values. Returns: the converted string's length. ver 1.1 9/91 changed \x to fixed 2 chars (\x0d not \xd) ver 1.0 3/91 ver 0.1 12/90 */ int convert(register char *a) { register char *s; int j; s=a; for (j=0;*a!='\0';a++,j++) { if (*a=='\\') { switch (*++a) { case 'x': *(s+j)=hexbyte(*(a+1),*(a+2)); a+=2; break; case 'a': *(s+j)='\a'; break; case 'b': *(s+j)='\b'; break; case 'f': *(s+j)='\f'; break; case 'n': *(s+j)='\n'; break; case 'r': *(s+j)='\r'; break; case 't': *(s+j)='\t'; break; case 'v': *(s+j)='\v'; break; case '0': *(s+j)='\0'; break; case '\\': *(s+j)='\\'; break; default: break; } } else *(s+j)=*a; } *(s+j)='\0'; a=s; return(j); } /* Display the current directory in a combination DIR /P /W format. ver 0.3 9/91 call to lpd() ver 0.2 3/91 */ #ifdef DISKED extern unsigned int disk; extern unsigned avail_clusters; extern unsigned secs_cluster; extern unsigned sec_size; #endif void directory(void) { int files=0; struct _find_t file; struct _diskfree_t ds; long dsize,fsize = 0L; output('\n'); if (_dos_findfirst("*.*",0x3f,&file)==0) { do { pname(file.name); print(" "); if (file.attrib&_A_SUBDIR) print(" "); else if (file.attrib&_A_VOLID) print(" "); else { plnls(file.size,7,10); fsize+=file.size; } ++files; print((files%3==0) ? "\n" : " "); if (files%60==0) pause(); } while (_dos_findnext(&file)==0); /* while being found*/ } if (files==0) print("no files"); output('\n'); #ifdef DISKED if (avail_clusters==0) { _dos_getdiskfree(disk,&ds); dsize = ((long)ds.avail_clusters*(long)ds.sectors_per_cluster*(long)ds.bytes_per_sector); } else dsize = ((long)avail_clusters*(long)secs_cluster*(long)sec_size); #else { unsigned disk; _dos_getdrive(&disk); _dos_getdiskfree(disk,&ds); dsize = ((long)ds.avail_clusters*(long)ds.sectors_per_cluster*(long)ds.bytes_per_sector); } #endif print(" file space %ld, disk space %ld\n",fsize,dsize); } /* Displays the filename returned by _dos_findnext() in a nice format. ver 0.2 3/91 */ void pname(char *s) { register int i; register int j; i=0; output(' '); while (s[i]!='.' && s[i]!='\0') output(s[i++]); j= (s[i]!='\0') ? i+1 : i; while (i++<8) output(' '); if (s[j]) output('.'); else output(' '); while (i++<=11) output( (s[j]=='\0') ? ' ' : s[j++]); } /* Modified K&R index() for a non-null terminated string. ver 0.1 12/90 */ int search(unsigned char *s,unsigned char *t,size_t size, size_t len) { unsigned int i; register unsigned int j,k; if (size>len) { size-=len; for (i=0;i<=size;i++) { for (j=i,k=0;k len) { size-=len; for (i=0;i <= size;i++) { for (j=i,k=0;kmax) return(ERROR); *pl=l; return(TRUE); } int getnum(unsigned int max, unsigned *num, int base) { char tmpstr[7]; /* longest number is unsigned 6 digits */ char form[3]; /* format string for sscanf() */ int i; unsigned int u; unsigned int *pu=num; /* make sure we have enough space */ i = 0; form[i++] = '%'; (base == 10) ? (form[i] = 'u') : (form[i] = 'x'); form[++i] = '\0'; i = getstr(tmpstr,getlen(max,base),(base == 10) ? _DIGIT : _HEX); if (i < 0) { if (i == ERROR) i = 0; return i; } sscanf(tmpstr,form,&u); if (u > max) return ERROR; *pu = u; return TRUE; } /* Get a string from console, masking to hex or decimal numbers only or punctuation, depending on the mask value, with CP/M editing control keys. Pass: pointer to string, int max length, int mask. Returns: -2 on ESC or ^C -1 on no input ('\r') -3 on no input (space or ',') ver 1.1 17-Mar-1994 better input type checking ver 1.0 9/93 added -3 return ver 0.1 12/90 */ int getstr(char *s,unsigned int len,int mask) { register unsigned int i; register int c = 0; savecursor(); for (i = 0; i < len; ) { switch (c = input()) { case '\b': if (i) { output(c); output(' '); output(c); --i; } break; case 'U'-'@': /* ^U to delete */ if (i) { restcursor(); clreol(); i = 0; } break; case 0x1b: /* ESC to abort */ case 'C'-'@': /* ^C */ i = 0; goto end_input; /* goto's!?!?!? -- Yeah! They work! */ case ',': if (mask & _PUNCT) goto use_it; else goto end_input; case ' ': if (mask & _BLANK) goto use_it; else goto end_input; case '\r': /* end of input */ goto end_input; default: use_it: if (mask == _DIGIT && (!isdigit(c))) continue; if (mask == _HEX && (!isxdigit(c))) continue; if (!(mask & _CONTROL) && iscntrl(c)) continue; output(c); /* save and echo numbers */ s[i++] = (char)c; break; } } end_input: s[i] = '\0'; if (!i) return (c=='\r') ? ERROR : -3; return i; } /*** * Edit a buffer, in a debugger type format. Asks for the starting * point of the editing. Checks for end of buffer and wraps around. * Allows hex and ASCII substitutions, jumps to a buffer location, and * hex number fills. * * A complicated, horrible looking function but it works. * * Uses getnum(), bdos(), hexbyte(), dispval() and . * * 1.1 23-Mar-1995 fixed '=' test of > bufend ( >= !) * 1.0 15-Mar-1995 restructured (tabs and whitespsace) * changes for file tracking (getlnum(), displval()) * * GAJ initial * GAJ added ASCII subs * GAJ 1-8-89 added ^x * GAJ 1-9-89 added \c * GAJ 3-8-89 updated help * GAJ 12-8-90 cleaned up ****/ int change(register unsigned char *buffer, unsigned int bufend, int base) { unsigned int a; unsigned int b; int c; /* chars gotten from the console */ unsigned int n,i; /* x = buffer index, n = getval, i = general purpose*/ register unsigned int x; int inquote,ad; /* for inputing a string */ int l; char t[66]; if (bufend <= 0) return 0; n = 0; #ifdef DISKED if (ft_track) i = getlnum(bufend,&n,base); else #endif i = getnum(bufend,&n,base); if (i == ABORT) return 0; ad = getlen(bufend,base); x = n; inquote = FALSE; output('\n'); for (;;) { c = buffer[x]; #ifdef DISKED if (ft_track) displval(x,base,c); else #endif dispval(x,ad,base,c); /* display address, byte, and ASCII */ if (!inquote) a = input()&0xff; if (a=='\\') /* search */ { output(a); /* echo */ a = input()&0xff; /* get */ if (a=='^') /* control */ { output(a); /* echo */ b = input()&0xff; /* get */ if (isalpha(b)) /* letter */ { a = toupper(b); /* upper */ output(a); /* echo */ c = (a-'@'); /* convert */ } else continue; /* else redo */ } else if (a == '\'') /* get ASCII */ { output(a); b = input()&0xff; if (b >= ' ') /* is okay? */ { output(b); /* echo */ c = b; /* set */ } else continue; /* else redo */ } else if (isxdigit(a)) /* get hex */ { output(a); b = input()&0xff; /* get second */ if (isxdigit(b) || b == '\r') { if (b != '\r') output(b); c = hexbyte(a,b); /* convert */ } else continue; } /* search loop */ i = x; /* save place */ while (c != (int)buffer[++x]) { if (x == bufend) /* wrap at end */ x = 0; if (x == i) /* stop */ break; } continue; } else if (a == '\"') /* get string */ { output(a); inquote = FALSE; /* bool for continuing */ if ((l = getstr(t,63,_TEXT)) > 0) { for (i = 0; i < (unsigned)l; i++)/* copy string */ { buffer[x++] = t[i]; if (x == bufend) /* wrap around */ x = 0; } } else continue; if (l == 63) inquote = TRUE; continue; } else if (a == '^') /* get control */ { output(a); b = input()&0xff; if (isalpha(b)) { b = toupper(b); output(b); buffer[x] = (char)(b-'@'); } else continue; } else if (a == '\'') /* get ASCII */ { output(a); b = input()&0xff; if (b >= ' ') /* is okay? */ { output(b); /* yes, display and set */ buffer[x] = (char)b; } else continue; } else if (a == '=') /* jump to addr */ { output(a); #ifdef DISKED if (ft_track) i = getlnum(bufend,&n,base); else #endif i = getnum(bufend,&n,base); if (i < 1) continue; if (n >= bufend) continue; x = n; continue; } else if (a == '\r' || a == ' ') /* go to next */ ; else if (a == '\t') /* goto 0000: */ { x = 0; continue; } else if (a == '.' || a == ESC) /* exit */ break; else if (a == '\b') /* go to previous */ { if (--x == 0xffff) { x = (bufend-1); /* if end, wrap */ output('\n'); } continue; } else if (a=='/' || a=='?') { print("\n\n\txx enter hex value xx"); print("\n\t'c enter ASCII char c"); print("\n\t^c enter control char c"); print("\n\t\"s enter string s"); print("\n\tCR/SP next location"); print("\n\tBS previous location"); print("\n\tTAB goto location 00"); print("\n\t=n goto location n"); print("\n\t\\xx goto hex value xx"); print("\n\t\\\'c goto char c"); print("\n\t\\^c goto control char c"); print("\n\t-x1,x2 write x1, x2 times"); print("\n\t+x1,x2 replace all x1, with x2"); print("\n\t.|ESC end\n"); continue; } else if (a == '-') /* fill */ { output(a); if (getnum(0xff,&a,16) < 1) continue; output(','); if (getnum(bufend,&b,16) < 1) /* get second byte */ continue; n = x; /* save position */ for (i = 0; i < b; i++) /* all okay, fill it */ { buffer[x] = (char)a; if (++x == bufend) /* wrap around at end */ x = 0; } x = n; /* restore position */ continue; } else if (a == '+') /* fill */ { output(a); if (getnum(0xff,&a,16) < 1) /* get first byte */ continue; output(','); if (getnum(0xff,&b,16) < 1) /* get second byte */ continue; if (a==b) continue; for (i = 0; i < bufend; i++) /* all okay, fill it */ { if (buffer[i] == (unsigned char)a) buffer[i] = (unsigned char)b; } continue; } else if (isxdigit(a)) { output(a); b = input()&0xff; /* get second */ if (isxdigit(b) || b == '\r') { if (b != '\r') output(b); buffer[x] = hexbyte(a,b); /* convert */ } else continue; } else continue; if (++x == bufend) /* increment pointer, wrap if end */ { x = 0; output('\n'); } } output('\n'); return 1; } void dispval(int x, int len, int base, int c) { output('\n'); pnlz(x,len,base); output(':'); output(' '); pnlz(c,2,16); output(' '); if (isprint(c)) { output('\''); output(c); output('\''); } else if (iscntrl(c)) { output('^'); output(c+'@'); output(' '); } else put(3,' '); put(2,' '); } #ifdef DISKED static void displval(int x, int base, int c) { long l = filebytes(); if (base == 10) print("\n%08ld: ",(long)x + l); else print("\n%06lx: ",(long)x + l); print("%02x ",c); if (isprint(c)) print("'%c' ",c); else if (iscntrl(c)) print("^%c ",c+'@'); else print(" "); } static int getlnum(unsigned int max, unsigned *num, int base) { int i; long n,l = filebytes(); n = 0L; if ((i = getnumber(l + max,&n,base)) > 0) { if (n < l) *num = 0; else *num = (int)(n - l); } return i; } #endif void pause(void) { savecursor(); print(""); input(); restcursor(); clreol(); } /* view file to screen */ void viewfile(char *filename, int display) { char buf[255]; FILE *fh; int i = 1; if (stricmp(filename,"none") == 0 || filename[0] == '\0') return; if ((fh = fopen(filename,"r")) == NULL) { perror(filename); return; } if (display) print(" %s File Contents:\n",filename); output('\n'); while (!feof(fh)) { if (fgets(buf,255,fh) == NULL) break; print(buf); if (++i == 23) { print("\r"); i = input(); if (i == 0) input(); print(" \r"); if (i == ESC) break; else i = 0; } } fclose(fh); }