home *** CD-ROM | disk | FTP | other *** search
- /* zap.c - program to inspect/patch binary files */
-
- static char SCCS_id[] = "@(#)@ zap 1.9 zap.c";
-
- static char cprght[] = "\
- @(#) Written by Johan Vromans at Multihouse Research, Gouda, the Netherlands.\n\
- @(#) Copyright 1987 Johan Vromans.\n\
- @(#) Distribution free as long as you give credit to the original author.\n\
- @(#) Military use and explicit resale prohibited.\n\
- @(#) Usage of this program is always at your own risk.";
-
- #include <stdio.h>
- #include <ctype.h>
- #include <signal.h>
-
- #ifndef TRUE
- # define TRUE 1
- # define FALSE 0
- #endif
-
- /* define SWAB=1 for byte swapping machines, such as vax and pdp-11 */
- /* otherwise, define it to 0 */
- /* if unknown, don't define it (or set it to 2) - zap will find out */
- /* when known, it is up to the C compiler to optimize unneeded code */
-
- #ifndef SWAB
- /* SWAB not defined - use info for machines we know */
- # ifdef vax /* DEC VAX */
- # define SWAB 1
- # endif
- # ifdef pdp11 /* DEC PDP-11 */
- # define SWAB 1
- # endif
- # ifdef hp9000s200 /* Hewlett-Packard HP9000/200 (M68xxx) */
- # define SWAB 0
- # endif
- # ifdef hp9000s500 /* Hewlett-Packard HP9000/500 (FocusII) */
- # define SWAB 0
- # endif
- # ifdef M_I86 /* Intel 86 family */
- # define SWAB 1
- # endif
- #endif
-
- #ifdef SWAB
- # if SWAB > 1 /* explicitly unknown */
- # undef SWAB
- # endif
- #endif
-
- #ifndef SWAB
- int swab = FALSE; /* use dynamic method */
- #else
- # define swab SWAB /* leave it to the compiler to eliminate */
- #endif
-
- /* About swabbing -
- *
- * Representation of data
- *
- * swabbing non-swabbing
- * type numeric character character
- * byte 0x61 'a' 'a'
- * word 0x6162 'ba' 'ab'
- * longword 0x61626364 'dcba' 'abcd'
- */
-
- #ifdef MSDOS
- # ifdef LINT_ARGS
-
- /* function defs as generated by MS-C V4.0 */
-
- /*global*/ int main (int, char**);
- /*global*/ int decod (char*, long*);
- /*global*/ unsigned int gv_file (long);
- /*global*/ int locate (long);
- /*global*/ int enter (long, int);
- /*global*/ int get_value (long);
- /*global*/ int put_value (long, long);
- /*global*/ int ptv_file (long, char);
- /*global*/ int push_loc (long);
- /*global*/ long pop_loc (void);
- /*global*/ int quit_search (void);
- /*global*/ int search (void);
- /*global*/ int verify (void);
- /*global*/ int gt_line (char*, char*, long, long, char, char*);
- /*global*/ int gt_val (char*, long*);
- /*global*/ char* pr_val (long, int);
- /*global*/ int zap (char*);
- /*global*/ int cant (char*);
- /*global*/ int remark (char*, long);
- /*global*/ int error (char*);
- /*global*/ int swabcheck (void);
-
- # endif
- #endif
-
- long lseek ();
- char *strcpy ();
- char *calloc ();
- char *realloc ();
- void exit();
- #define V_printf (void) printf
- #define V_fprintf (void) fprintf
- #define V_sprintf (void) sprintf
- #ifdef lint
- void clearerr ();
- #endif
-
- char *my_name = "zap"; /* identification */
- char *usage = "usage: zap [-cdrsvw] file";
-
- /* option flags */
-
- int f_check = FALSE; /* request checksum */
- int f_sum = FALSE; /* print checksum */
- int f_write = FALSE; /* read-write */
- int f_silent = FALSE; /* silent */
- int f_batch = FALSE; /* running batch mode */
- int f_verbose = FALSE; /* give more info */
-
- /* main routine */
-
- main (argc, argv)
- int argc; /* # arguments + 1 */
- char *argv[]; /* argument pointers */
-
- {
- int file_cnt; /* number of files processed */
- char *arg_ptr; /* argument pointer */
- char c; /* current option character */
-
- swabcheck (); /* verify or establish swabbing mode */
-
- /* ignore first argument (program name) */
-
- argc--;
- argv++;
-
- f_batch = !isatty (0);
- file_cnt = 0; /* haven't seen one yet */
-
- while (argc-- > 0) /* through arguments */
- {
- /* fetch a pointer to the current argument, and
- * increase argv
- */
-
- arg_ptr = *argv;
- argv++;
-
- if (*arg_ptr == '-') /* must be an option */
- {
- while (c = *++arg_ptr) /* get option character */
- switch (c)
- {
-
- case 'C' :
- case 'c' :
- f_check = TRUE; /* request checksum */
- break;
-
- case 'D' :
- case 'd' :
- f_sum = TRUE; /* print checksum */
- break;
-
- case 'R' :
- case 'r' :
- f_write = FALSE; /* read-only */
- break;
-
- case 'S' :
- case 's' :
- f_silent = TRUE; /* a little more quiet */
- break;
-
- case 'V' :
- case 'v' :
- V_printf ("zap version 1.9\n");
- #ifndef SWAB
- if (!f_verbose)
- remark ("you may recompile with \"-DSWAB=%ld\"",
- (long)swab);
- #endif
- f_verbose = TRUE; /* a little less quiet */
- break;
- case 'W' :
- case 'w' :
- f_write = TRUE; /* allow write access */
- break;
-
- default : error (usage);
- break;
- }
-
- /* this ends the option processing */
- }
- else
- {
- /* it must be a file specification */
-
- file_cnt++; /* now we've seen one */
-
- zap (arg_ptr);
-
- /* this ends the file processing */
- }
-
- /* this ends the argument processing */
- }
-
- /* if there were no filespecs, give error */
-
- if (!file_cnt)
- error (usage);
-
- /* that's it */
-
- #ifdef vaxc
- return (1);
- #else
- return (0);
- #endif
- }
-
- /* current type values. note - value is also size of type */
-
- int cur_type;
- #define BYTE 1
- #define WORD 2
- #define LWORD 4
-
- char dp_type [] = " \\/ |";
-
- /* current display mode */
-
- int cur_printmode;
- #define OCTAL 0
- #define DECIMAL 1
- #define HEX 2
- #define ASCII 3
-
- char *defffmt[] = { "0%05lo", "%6ld", "x%05lx", "0%05lo" };
- char *deffmt[] = { "0%lo", "%ld", "x%lx", "0%lo" };
-
- #define BYTEVAL(x) ((x) & 0xff)
-
- /* current file */
-
- FILE *zf;
-
- /* get (decimal, hex or octal) value from input line */
- /* a zero return value means : ok */
-
- int decod (buf, lp)
- char *buf;
- long *lp;
- {
- long num;
- char *cp;
- int dooct = FALSE;
- int dohex = FALSE;
- int doasc = FALSE;
-
- num = 0;
- cp = buf;
- if (*cp == ';') /* select mode */
- {
- cp++;
- if (*cp == 'x' || *cp == 'X')
- dohex = TRUE;
- else
- if (*cp == 'o' || *cp == 'O')
- dooct = TRUE;
- else
- if (*cp == 'd' || *cp == 'D')
- ;
- else
- if (*cp == 'a' || *cp == 'A')
- doasc = TRUE;
- else
- V_printf ("input error");
- cp++;
- }
- else
- {
- while (*cp == '0')
- {
- dooct = TRUE;
- cp++;
- }
- if (*cp == 'x' || *cp == 'X')
- {
- cp++;
- dohex = TRUE;
- }
- }
-
- if (dohex)
- {
- while (isxdigit (*cp))
- {
- num = num * 16
- + (isdigit (*cp)
- ? *cp - '0'
- : (*cp | 0x20) - 'a' + 10);
- cp++;
- }
- }
- else
- if (dooct)
- {
- while (isdigit (*cp) && *cp < '8')
- {
- num = num * 8 + *cp - '0';
- cp++;
- }
- }
- else
- if (doasc)
- {
- int i;
- for (i = 0; i < cur_type && *cp; i++)
- {
- if (swab)
- num += ((long)(*cp++)) << (i << 3);
- else
- num = (num << 8) + *cp++;
- }
- }
- else
- {
- while (isdigit (*cp))
- {
- num = num * 10 + *cp - '0';
- cp++;
- }
- }
-
- *lp = num;
- if (!*cp)
- return (0);
- if (*cp == '^')
- return (-1); /* special return value for zap */
- else
- return (1);
- }
-
- /* retrieve byte from file */
-
- unsigned gv_file (addr)
- long addr;
- {
- long l;
-
- if (fseek (zf, addr, 0))
- remark ("cannot position to %ld", addr);
-
- (void) clearerr (zf);
- l = fgetc (zf);
-
- if (l == EOF)
- remark (ferror(zf) ? "cannot read at %ld" : "read beyond eof", addr);
-
- return (BYTEVAL(l));
- }
-
- #define BUF_INC 512
- int tbl_max = BUF_INC;
-
- struct ntry
- {
- long addr;
- char val;
- char old;
- }
- *tbl, /* value table */
- *tbl_cur, /* last referenced entry in table */
- *tbl_free, /* next free entry in table */
- *tbl_ptr; /* work pointer into table */
-
- int locate (adr)
- long adr;
- {
- /* lookup address in table. return tbl_cur at correct entry
- * or next higher */
-
- if (tbl_cur >= tbl && tbl_cur < tbl_free && tbl_cur->addr == adr)
- /* just looked up */
- return (TRUE);
-
- for (tbl_cur = tbl; tbl_cur != tbl_free; tbl_cur++)
- {
- if (tbl_cur->addr > adr)
- break;
- if (tbl_cur->addr == adr)
- return (TRUE);
- }
- return (FALSE);
- }
-
- enter (addr, val)
- long addr;
- int val;
- {
- char old;
-
- /* lookup address */
- if (locate (addr))
- {
- /* store value, if different from file value */
- if (val != tbl_cur->old)
- {
- tbl_cur->val = val;
- return;
- }
- /* else delete entry from table */
- for (tbl_ptr=tbl_cur; tbl_ptr < tbl_free-1; tbl_ptr++)
- tbl_ptr[0] = tbl_ptr[1];
- tbl_free--;
- return;
- }
-
- /* if not found, tbl_cur points at next higher address entry */
- /* insert new entry at appropriate position */
-
- old = gv_file (addr);
- if (val == old) /* no-op if new == old */
- return;
-
- /* check for space in table, otherwise extend it */
- if (tbl_free == &tbl[tbl_max])
- {
- tbl_max += BUF_INC;
- if ((tbl = (struct ntry*) realloc ((char*) tbl, (unsigned) tbl_max * sizeof (*tbl))) == NULL)
- error ("table overflow");
- }
-
- for (tbl_ptr=tbl_free-1; tbl_ptr >= tbl_cur; tbl_ptr--)
- tbl_ptr[1] = tbl_ptr[0];
-
- tbl_cur->addr = addr;
- tbl_cur->val = val;
- tbl_cur->old = old;
-
- tbl_free++;
- }
-
- /* retrieve value from table */
-
- int get_value (addr)
- long addr;
- {
- int val;
-
- if (locate (addr))
- val = tbl_cur->val;
- else
- val = gv_file (addr);
-
- return (val);
- }
-
- /* put byte into table */
-
- #define put_byte enter
-
- /* put value into table */
-
- put_value (addr, val)
- long addr;
- long val;
- {
- int i;
-
- for (i=0; i<cur_type; i++)
- {
- register long temp = addr + ((swab) ? i : (cur_type-i-1));
- put_byte (temp, (int)BYTEVAL(val));
- val >>= 8;
- }
- }
-
- ptv_file (addr, val)
- long addr;
- char val;
- {
- char c;
-
- c = val;
-
- if (fseek (zf, addr, 0))
- remark ("cannot position to %ld", addr);
-
- (void) clearerr (zf);
- (void) fputc (c, zf);
- if (ferror(zf) || feof(zf))
- remark ("cannot write at %ld", addr);
- }
-
- char buf [132];
- char *pr_val();
-
- #define PREV_MAX 256 /* size of previous goto table */
- long prevs [PREV_MAX]; /* previous goto table */
- int prevcnt; /* next free index in previous table */
-
- push_loc (loc)
- long loc;
- {
- int i;
- if (prevcnt == PREV_MAX)
- {
- for (i=0; i<prevcnt; i++)
- prevs[i] = prevs[i+1];
- prevcnt--;
- }
- prevs[prevcnt++] = loc;
- }
-
- long pop_loc ()
- {
- if (prevcnt > 0)
- return (prevs[--prevcnt]);
- return (0);
- }
-
- long last_value; /* last printed value */
- long sstart; /* search starting value */
- long ennd; /* search ending value */
- long interrupted; /* search was terminated */
- int diddots; /* dots were displayed */
-
- int quit_search ()
- {
- interrupted = sstart;
- sstart = ennd;
- }
-
- foundit (addr)
- long addr;
- {
- if (diddots)
- V_printf ("\n");
- V_printf ("Found at ");
- V_printf (defffmt[cur_printmode], addr);
- V_printf ("\n");
- diddots = FALSE;
- push_loc (addr);
- }
-
- /* search value in file */
-
- search ()
- {
- int bt; /* first byte thereof */
- long first;
- union {
- long ll;
- char ss[4];
- } uu;
-
- if (!gt_val ("Search for ? ", &uu.ll))
- return;
-
- if (!gt_val ("Start at ? ", &sstart))
- return;
-
- if (!gt_val ("Stop at ? ", &ennd))
- return;
-
- /* temporary using first to hold EOF value */
- first = lseek (fileno(zf), 0l, 2);
- if (ennd == 0)
- {
- if (f_verbose)
- {
- V_fprintf (stderr, "EOF at ");
- V_fprintf (stderr, deffmt[cur_printmode], first);
- V_fprintf (stderr, "\n");
- }
- ennd = first - cur_type + 1;
- }
-
- if (sstart > ennd)
- {
- remark ("start > end", 0L);
- return;
- }
-
- if (ennd > first)
- {
- if (f_verbose)
- remark ("end > EOF, truncated", 0L);
- ennd = first;
- }
- /* end of using first to hold EOF value */
-
- #ifndef SEARCH_ACTUAL
- if (fseek (zf, sstart, 0))
- {
- V_fprintf (stderr, "cannot position to ");
- V_fprintf (stderr, deffmt[cur_printmode], sstart);
- V_fprintf (stderr, "\n");
- return;
- }
- #endif
-
- (void) signal (SIGINT, quit_search);
-
- /* shift to align */
- if (!swab)
- {
- if (cur_type == BYTE)
- uu.ss[0] = uu.ss[3];
- else
- if (cur_type == WORD)
- {
- uu.ss[0] = uu.ss[2];
- uu.ss[1] = uu.ss[3];
- }
- }
- bt = BYTEVAL(uu.ss[0]);
-
- first = sstart;
- diddots = interrupted = FALSE;
-
- while (sstart < ennd)
- {
-
- /* print a dot for every 1K processed */
- if (!f_silent && (((first - sstart) & 0x3ff) == 0) && sstart > first)
- {
- V_printf (".");
- (void) fflush (stdout);
- diddots = TRUE;
- }
-
- #ifdef SEARCH_ACTUAL
-
- /* searching the actual values (very slow) */
-
- if (get_value (sstart) == bt)
- {
- if (
- ( cur_type == BYTE /* looking for byte is easy */
- )
- || ( cur_type == WORD /* word needs another byte */
- && (get_value (sstart+1L) == BYTEVAL(uu.ss[1]))
- )
- || ( cur_type == LWORD /* lword needs three other bytes */
- && (get_value (sstart+1L) == BYTEVAL(uu.ss[1]))
- && (get_value (sstart+2L) == BYTEVAL(uu.ss[2]))
- && (get_value (sstart+3L) == BYTEVAL(uu.ss[3]))
- )
- )
- foundit (sstart);
- }
- start++;
-
- #else
-
- /* searching the old contents of the file */
-
- if (fgetc (zf) == bt)
- {
- int chr;
- if (cur_type == BYTE) /* looking for byte is easy */
- foundit (sstart);
- else
- {
- chr = fgetc (zf);
- if (chr == BYTEVAL(uu.ss[1]))
- {
- if (cur_type == WORD)
- {
- foundit (sstart);
- ungetc (chr, zf);
- }
- else
- {
- chr = fgetc (zf);
- if (chr == BYTEVAL(uu.ss[2]))
- {
- chr = fgetc (zf);
- if (chr == BYTEVAL(uu.ss[3]))
- foundit (sstart);
- }
- fseek (zf, sstart+1L, 0);
- }
- }
- else
- ungetc (chr, zf);
- }
- }
- sstart++;
- if (ferror (zf) || feof (zf))
- quit_search ();
-
- #endif
-
- } /* while (sstart < ennd) */
-
- if (diddots)
- V_printf ("\n");
- (void) signal (SIGINT, SIG_DFL);
- if (!f_batch && interrupted)
- {
- V_printf ("Interrupted at ");
- V_printf (defffmt[cur_printmode], sstart);
- V_printf ("\n");
- }
- }
-
- /* print verification list */
-
- verify ()
- {
- long addr = 0;
-
- /* display all modifications entered until now. display in portions
- * of cur_printmode. align to lower cur_type boundary
- */
- for (tbl_ptr = tbl; tbl_ptr != tbl_free; tbl_ptr++)
- if (tbl_ptr->addr >= addr)
- {
- addr = tbl_ptr->addr & ~(cur_type-1);
- V_printf ("vfy: ");
- V_printf (defffmt[cur_printmode], addr);
- V_printf ("%c %-7s => ", dp_type[cur_type], pr_val (addr, FALSE));
- V_printf ("%-7s\n", pr_val (addr, TRUE));
- addr += cur_type;
- }
- }
-
- int gt_line (dst, prompt, arg1, arg2, arg3, arg4)
- char *dst;
- char *prompt;
- long arg1;
- long arg2;
- char arg3;
- char *arg4;
- {
- if (prompt != NULL && !f_silent)
- V_printf (prompt, arg1, arg2, arg3, arg4);
- (void) fflush (stdout);
- if (!gets (dst))
- {
- if (f_batch && !f_silent)
- V_printf ("[eof]\n");
- #ifndef vaxc
- (void) putchar ('\n');
- #endif
- return (NULL);
- }
- if (f_batch && !f_silent)
- V_printf ("%s\n", dst);
- if (dst[0] == '^' && dst[1] == 'Z' && dst[2] == '\0')
- return (FALSE);
- else
- return (TRUE);
- }
-
- int gt_val (prompt, l)
- char *prompt;
- long *l;
- {
- *l = 0l;
- while (gt_line (buf, prompt, 0L, 0L, '\0', NULL))
- {
- if (!decod (buf, l))
- return (TRUE);
- }
- return (FALSE);
- }
-
- /* display value, using current settings (result is in static area) */
-
- char *pr_val (addr, cur)
- long addr;
- int cur; /* 1 = use current, 0 = use previous */
- {
- static char dst [64];
- char *cp;
- long val;
- int i;
- # define getbyte(addr) BYTEVAL((cur) ? get_value (addr) : gv_file (addr))
-
- last_value = 0;
- if (cur_printmode == ASCII)
- {
- cp = dst;
- for (i=0; i<cur_type; i++)
- {
- val = getbyte (addr);
- addr++;
- if (val >= ' ' && val < 0177 && val != '\\')
- *cp++ = val;
- else
- {
- *cp++ = '\\';
- switch ((int)BYTEVAL(val))
- {
- case '\b': *cp++ = 'b';
- break;
- case '\n': *cp++ = 'n';
- break;
- case '\t': *cp++ = 't';
- break;
- case '\f': *cp++ = 'f';
- break;
- case '\r': *cp++ = 'r';
- break;
- case '\\': *cp++ = '\\';
- break;
- default: V_sprintf (cp, "%o", val);
- while (*cp) cp++;
- break;
- }
- }
- *cp++ = ' ';
- }
- *cp = '\0';
- }
- else
- {
- val = 0l;
- switch (cur_type)
- {
- case BYTE:
- val = getbyte (addr);
- break;
- case WORD:
- if (swab) {
- val = getbyte (addr+1L);
- val = (val << 8) | getbyte (addr );
- }
- else {
- val = getbyte (addr );
- val = (val << 8) | getbyte (addr+1L);
- }
- break;
- case LWORD:
- if (swab) {
- val = getbyte (addr+3L);
- val = (val << 8) | getbyte (addr+2L);
- val = (val << 8) | getbyte (addr+1L);
- val = (val << 8) | getbyte (addr );
- }
- else {
- val = getbyte (addr );
- val = (val << 8) | getbyte (addr+1L);
- val = (val << 8) | getbyte (addr+2L);
- val = (val << 8) | getbyte (addr+3L);
- }
- break;
- }
- if ((last_value = val) != 0 || cur_printmode != OCTAL)
- V_sprintf (dst, deffmt[cur_printmode], val);
- else
- (void) strcpy (dst, "0");
- }
-
- return (dst);
- }
-
- zap (fname)
- char *fname;
-
- {
- long base; /* base of patching sequence */
- long offset; /* offset from base */
- long val; /* holding variable for values */
- int i; /* scratch */
- char chr; /* scratch */
- int check; /* checksum value */
- int need_head; /* header toggle */
- int checkwrite = TRUE; /* check for write access */
- int goon = TRUE; /* until ^Y is used */
- static char *fmt [] = {
- "0%05lo 0%05lo%c %-7s ",
- "%6ld %6ld%c %-7s ",
- "x%05ld x%05lx%c %-7s ",
- "0%05lo 0%05lo%c %-7s " };
-
- /* open file */
-
- #ifdef MSDOS
- if ((zf = fopen (fname, (f_write) ? "rb+" : "rb")) == NULL)
- #else
- if ((zf = fopen (fname, (f_write) ? "r+" : "r")) == NULL)
- #endif
- cant (fname);
-
- /* set defaults and allocate table */
-
- cur_type = BYTE;
- cur_printmode = OCTAL;
- if (!tbl)
- tbl = (struct ntry*) calloc ((unsigned)tbl_max, sizeof (struct ntry));
- if (!tbl)
- error ("no room for table");
- tbl_cur = tbl_free = tbl;
- prevcnt = 0; /* reset previous location table */
-
- /* loop 1 : loop on Base values */
-
- while (goon && gt_val ("Base ? ", &base))
- {
- /* loop 2 : loop on offset values */
-
- while (goon && gt_val ("Offset ? ", &offset))
- {
- need_head = TRUE;
-
- /* loop 3 : loop on patch commands */
-
- while (goon)
- {
- if (need_head && !f_silent)
- V_printf ("Base Offset Value New\n");
- need_head = FALSE;
-
- if (!gt_line (buf, fmt[cur_printmode], base, offset,
- dp_type[cur_type], pr_val (base+offset, TRUE)))
- break;
-
- switch (buf[0])
- {
- case '\0':
- /* close current, advance and open new location */
- offset += cur_type;
- break;
- case '/':
- /* re-open current using new type */
- cur_type = WORD;
- break;
- case '\\':
- /* re-open current using new type */
- cur_type = BYTE;
- break;
- case '|':
- /* re-open current using new type */
- cur_type = LWORD;
- break;
- case '^':
- if (buf[1] == '\0')
- {
- /* close current, backup and open new location */
- offset -= cur_type;
- break;
- }
- if (buf[1] != 'Y' || buf[2] != '\0')
- break;
- /* FALL THROUGH */
- case '\031': /* ^Y */
- goon = FALSE;
- break;
- case '>':
- /* goto new location */
- if (!decod (&buf[1], &val))
- {
- push_loc (base+offset);
- offset = buf[1] ? val : last_value;
- }
- break;
- case '<':
- /* goto location */
- if (buf[1] == '\0' && prevcnt > 0)
- offset = pop_loc () - base;
- break;
- case ';':
- /* change current display mode ... */
- chr = buf[1];
- if (isupper (chr))
- chr = tolower (chr);
- if (chr == 'o')
- cur_printmode = OCTAL;
- else
- if (chr == 'd')
- cur_printmode = DECIMAL;
- else
- if (chr == 'x')
- cur_printmode = HEX;
- else
- /* ... or store ascii bytes ... */
- if (chr == 'a')
- {
- cur_printmode = ASCII;
- for (i=2; chr=buf[i]; i++)
- {
- if (checkwrite && !f_write)
- {
- need_head = TRUE;
- checkwrite = FALSE;
- remark ("no write access", 0L);
- }
- put_byte (base+offset, chr);
- offset++;
- }
- }
- else
- /* ... or print modifications ... */
- if (chr == 'v')
- {
- verify ();
- need_head = TRUE;
- }
- else
- /* ... or search values */
- if (chr == 's')
- {
- search ();
- need_head = TRUE;
- }
-
- break;
- default:
- if ((i = decod (buf, &val)) <= 0)
- {
- if (checkwrite && !f_write)
- {
- need_head = TRUE;
- checkwrite = FALSE;
- remark ("no write access", 0L);
- }
- put_value (base+offset, val);
- if (!i)
- offset += cur_type;
- else
- offset -= cur_type;
- }
- }
- /* loop on patch commands */
- }
- /* loop on offset values */
- }
- /* loop on base values */
- }
-
- /* compute checksum, if requested */
-
- if (f_check || f_sum)
- {
- check = 0;
- for (tbl_cur = tbl; tbl_cur != tbl_free; tbl_cur++)
- check ^= (BYTEVAL(tbl_cur->val) | ((tbl_cur->old << 8) & 0xff00));
- if (f_sum)
- {
- V_printf ("Checksum = ");
- V_printf (deffmt[cur_printmode], check);
- V_printf ("\n");
- }
- }
-
- /* apply patches, after checksum verification */
-
- tbl_cur = tbl;
-
- if (f_write)
- {
- /* verify checksum */
-
- if (f_check)
- while (gt_val ("Checksum ? ", &val))
- if (val == check || f_batch)
- break;
-
- if (!(f_check && val != check))
- for (tbl_cur = tbl; tbl_cur != tbl_free; tbl_cur++)
- ptv_file (tbl_cur->addr, tbl_cur->val);
- }
-
- if (tbl_cur != tbl_free)
- error ("no modifications made");
-
- if (!f_silent && f_write && tbl == tbl_free)
- remark ("no modifications requested", 0L);
-
- /* close file and exit */
-
- (void) fclose (zf);
- }
-
- cant (s)
- char *s;
- {
- V_fprintf (stderr, "%s: cannot open %s\n", my_name, s);
- exit (1);
- }
-
- remark (s, a)
- char *s;
- long a;
- {
- V_fprintf (stderr, "%s: ", my_name);
- V_fprintf (stderr, s, a);
- V_fprintf (stderr, "\n");
- }
-
- error (s)
- char *s;
- {
- V_fprintf (stderr, "%s: %s\n", my_name, s);
- exit (1);
- }
-
- swabcheck ()
- {
- union {
- short s;
- char a[2];
- } u;
- u.s = 0x1357;
- #ifdef SWAB
- #if SWAB
- if (!(u.a[0] == 0x57 && u.a[1] == 0x13))
- error ("please recompile with \"-DSWAB=0\"");
- #else
- if (!(u.a[0] == 0x13 && u.a[1] == 0x57))
- error ("please recompile with \"-DSWAB=1\"");
- #endif
- #else
- swab = (u.a[0] == 0x57 && u.a[1] == 0x13);
- #endif
- #ifdef lint
- SCCS_id[0] = cprght[0] = '\0';
- #endif
- }
-