From:	CSBVAX::CSBVAX::MRGATE::"SMTP::VAXMFG.TECH.NWU.EDU::CHOJNACKI"  2-MAR-1989 21:59
To:	MRGATE::"ARISIA::EVERHART"
Subj:	March 2 UNMACRO source 6/8


Received: from vaxmfg.tech.nwu.edu by accuvax.nwu.edu id aa12760;
          2 Mar 89 12:02 CST
Date: Thu, 2 Mar 89 12:14 CST
From: Bob Chojnacki <CHOJNACKI@vaxmfg.tech.nwu.edu>
Subject: March 2 UNMACRO source 6/8
To: EVERHART%ARISIA.decnet@ge-crd.arpa
X-VMS-To: IN%"EVERHART%ARISIA.decnet@ge-crd.arpa"
Message-ID:  <8903021203.aa12760@accuvax.nwu.edu>

+-+-+-+ Beginning of part 6 +-+-+-+
X      current_arg++; --argc;
X    `125
X  `125
X/*
X  Open image file
X*/
X  if (argc == 2) `123
X    strcpy(in_file, argv[current_arg]);
X  `125 else if (argc == 1) `123
X    fprintf(stderr, "Image file: ");
X    scanf("%s", in_file);
X    do `123`125 while (getchar() != '\n');
X  `125 else `123
X    usage();
X  `125
X  j = strlen(in_file);
X  for (i=0; i<j; i++)
X    in_file[i] = toupper(in_file[i]);
X  if ((sfp = fopen(in_file, "rb")) != (FILE *) NULL) `123
X  `125 else `123
X    strcpy(in_file_exe, in_file); strcat(in_file_exe, ".EXE");
X    if ((sfp = fopen(in_file_exe, "rb")) == (FILE *) NULL) `123
X      fprintf(stderr, "error opening %s for binary read\n",
X        in_file);
X      perror("UNMACRO reading image file");
X      exit(1);
X    `125
X  `125
X/*
X  find the end of file
X*/
X  if (fseek(sfp, 0l, SEEK_END)) `123
X    fprintf(stderr, "Error seeking to the end of %s\n", in_file);
X    perror("UNMACRO");
X    fclose(sfp);
X    exit(1);
X  `125
X  tot_blocks = (ftell(sfp)+511)/512;
X  if (fseek(sfp, 0l, SEEK_SET)) `123
X    fprintf(stderr, "error seeking to the beginning of %s\n", in_file);
X    perror("UNMACRO");
X    fclose(sfp);
X    exit(1);
X  `125
X  if (tot_blocks)
X    fprintf(stderr, "%d blocks found in %s.\n", tot_blocks, in_file);
X  else `123
X    fprintf(stderr, "Zero length file.\n");
X    fclose(sfp);
X    exit(1);
X  `125
X  clearerr(sfp);
X/*
X  Get image header
X*/
X  header();
X  fprintf(stderr, "Memory size of image is %X pages (%d.)\n",
X   mem_pages, mem_pages);
X/*
X  Allocate image and bytetype buffers
X*/
X  if (!(image = malloc(mem_pages*512))) `123
X    fprintf(stderr, "insufficient memory for image\n");
X    exit(1);
X  `125
X  if (!(bytetype = malloc(mem_pages*512))) `123
X    fprintf(stderr, "insufficient memory for image mask\n");
X    exit(1);
X  `125
X/*
X  read in file
X*/
X  base = lowest_vpn*512;
X  fprintf(stderr,"isd ");
X  for (i=0; i<h_nisd; i++) `123
X    fprintf(stderr,"%d ",i);
V    if (!(h_isd[i]->flags & ISD_GLOBAL) && !(h_isd[i]->flags & 0xff000000)) `12
X3
X      if (h_isd[i]->flags & ISD_DZERO) `123
X        memset(&image[top], 0, h_isd[i]->pages*512);
X        memset(&bytetype[top], C0_BLKB, h_isd[i]->pages*512);
X      `125 else `123
X        if (feof(sfp))
X          fprintf(stderr, "end of image file detected\n");
X        fread(&image[top], 512, h_isd[i]->pages, sfp);
X/* if this section is writeable then assume data */
X`009if (h_isd[i]->flags & ISD_WRITE)
X`009  memset(&bytetype[top], C0_BYTE, h_isd[i]->pages*512);
X`009else
X`009  memset(&bytetype[top], C0_INSTRUCTION, h_isd[i]->pages*512);
X      `125
X      top += 512*h_isd[i]->pages;
X    `125
X  `125
X  fprintf(stderr, "\n");
X  top += base-1;
X  fprintf(stderr, "base, top = %08X, %08X\n", base, top);
X  fclose(sfp);
X/*
X  put .ENTRY's on transfer addresses in memory
X*/
X  if ((h_transfer1 >= base) && (h_transfer1 <= top))
X    bytetype[h_transfer1-base] = C0_ENTRY;
X  if ((h_transfer2 >= base) && (h_transfer2 <= top))
X    bytetype[h_transfer2-base] = C0_ENTRY;
X  if ((h_transfer3 >= base) && (h_transfer3 <= top))
X    bytetype[h_transfer3-base] = C0_ENTRY;
X/*
X  display disassembled source
X*/
X  pc = base;
X  do `123
X    ctlc_int = 0;
X/*
X  get command
X*/
X    if (commands(command)) `123
X      comderr("UNMACRO>", 0, unmacrocommands, sizeof_unmacrocommands);
X    `125 else `123
X      switch (command[0]) `123
X/*
X  DISASSEMBLE
X*/
X       case C_DISASSEMBLE:
X`009switch (command[1]) `123
X`009 case C0_UNTIL:
X`009  switch (command[2]) `123
X`009   case C0x22_END:
X`009    while ((pc <= top) && !ctlc_int) `123
X`009      if (bytetype[pc-base] < 0)
X`009`009printf("L%X:", pc);
X`009      if (pos(bytetype[pc-base]) == C0_INSTRUCTION) `123
X`009`009disassemble();
X`009      `125 else `123
X`009`009undata();
X`009      `125
X`009    `125
X`009    printf("\n");
X`009    break;
X`009   case C0x22_PC:
X`009    fprintf(stderr, "pc, command[3] = %08X, %08X\n", pc, command[3]);
X`009    while ((pc <= command[3]) && (pc <= top) && !ctlc_int) `123
X`009      if (bytetype[pc-base] < 0)
X`009`009printf("L%X:", pc);
X`009      if (pos(bytetype[pc-base]) == C0_INSTRUCTION) `123
X`009`009disassemble();
X`009      `125 else `123
X`009`009undata();
X`009      `125
X`009    `125
X`009    printf("\n");
X`009    break;
X`009   case C0x22_DATA:
X`009    while ((pc <= top) && (pos(bytetype[pc-base]) ==
X`009     C0_INSTRUCTION) && !ctlc_int) `123
X`009      if (bytetype[pc-base] < 0)
X`009`009printf("L%X:", pc);
X`009      disassemble();
X`009    `125
X`009    printf("\n");
X`009    break;
X`009  `125
X`009  break;
X`009 case C0_ALL:
X`009  pc = base;
X`009  while ((pc <= top) && !ctlc_int) `123
X`009    if (bytetype[pc-base] < 0)
X`009      printf("L%X:", pc);
X`009    if (pos(bytetype[pc-base]) == C0_INSTRUCTION) `123
X`009      disassemble();
X`009    `125 else `123
X`009      undata();
X`009    `125
X`009  `125
X`009  break;
X`009 case C0_INSTRUCTION:
X`009  if (bytetype[pc-base] < 0)
X`009    printf("L%X:", pc);
X`009  disassemble();
X`009  printf("\n");
X`009  break;
X`009 default:
X`009  if ((command[1] >= C0_BYTE) && (command[1] < C0_UNTIL)) `123
X`009    pre_pc = pc;
X`009    force_undata(command[1]);
X`009    pc = pre_pc;
X`009  `125 else if (pos(bytetype[pc-base]) == C0_INSTRUCTION) `123
X`009    if (bytetype[pc-base] < 0)
X`009      printf("L%X:", pc);
X`009    disassemble();
X`009  `125 else `123
X`009    if (bytetype[pc-base] < 0)
X`009      printf("L%X:", pc);
X`009    undata();
X`009  `125
X`009  printf("\n");
X`009`125
X`009break;
X/*
X  SET
X*/
X       case C_SET:
X`009switch(command[1]) `123
X`009 case C1_BYTE:
X`009  bytetype[pc-base] = command[2];
X`009  break;
X`009 case C1_WORD:
X`009  bytetype[pc-base] = command[2];
X`009  bytetype[pc-base+1] = command[2];
X`009  break;
X`009 case C1_LONG:
X`009  bytetype[pc-base] = command[2];
X`009  bytetype[pc-base+1] = command[2];
X`009  bytetype[pc-base+2] = command[2];
X`009  bytetype[pc-base+3] = command[2];
X`009  break;
X`009 case C1_QUAD:
X`009  bytetype[pc-base] = command[2];
X`009  bytetype[pc-base+1] = command[2];
X`009  bytetype[pc-base+2] = command[2];
X`009  bytetype[pc-base+3] = command[2];
X`009  bytetype[pc-base+4] = command[2];
X`009  bytetype[pc-base+5] = command[2];
X`009  bytetype[pc-base+6] = command[2];
X`009  bytetype[pc-base+7] = command[2];
X`009  break;
X`009 case C1_OCTA:
X`009  bytetype[pc-base] = command[2];
X`009  bytetype[pc-base+1] = command[2];
X`009  bytetype[pc-base+2] = command[2];
X`009  bytetype[pc-base+3] = command[2];
X`009  bytetype[pc-base+4] = command[2];
X`009  bytetype[pc-base+5] = command[2];
X`009  bytetype[pc-base+6] = command[2];
X`009  bytetype[pc-base+7] = command[2];
X`009  bytetype[pc-base+8] = command[2];
X`009  bytetype[pc-base+9] = command[2];
X`009  bytetype[pc-base+10] = command[2];
X`009  bytetype[pc-base+11] = command[2];
X`009  bytetype[pc-base+12] = command[2];
X`009  bytetype[pc-base+13] = command[2];
X`009  bytetype[pc-base+14] = command[2];
X`009  bytetype[pc-base+15] = command[2];
X`009  break;
X`009 case C1_RANGE:
X`009  for (i=0; i<command[3]; i++)
X`009    bytetype[pc-base+i] = command[2];
X`009  break;
X`009 case C1_LABEL:
X`009  bytetype[pc-base] = neg(bytetype[pc-base]);
X`009  break;
X`009 case C1_UNLABEL:
X`009  bytetype[pc-base] = pos(bytetype[pc-base]);
X`009  break;
X`009`125
X`009break;
X/*
X  SHOW
X*/
X       case C_SHOW:
X`009switch(command[1]) `123
X`009 case C1_BYTE:
X`009 case C1_WORD:
X`009 case C1_LONG:
X`009 case C1_QUAD:
X`009 case C1_OCTA:
X`009  fprintf(stderr, "%s", setshowbyte[pos(bytetype[pc-base])]);
X`009  if (bytetype[pc-base] < 0) `123
X`009    fprintf(stderr, " (labeled)\n");
X`009  `125 else `123
X`009    fprintf(stderr, "\n");
X`009  `125
X`009`125
X`009printf("\n");
X`009break;
X/*
X  GOTO
X*/
X       case C_GOTO:
X`009if (command[1] < base) `123
X`009  fprintf(stderr, "Base of program is %08X\n", base);
X`009`125 else if (command[1] > top) `123
X`009  fprintf(stderr, "Top of program is %08X\n", top);
X`009`125 else `123
X`009  pc = command[1];
X`009`125
X`009break;
X/*
X  SAVE
X*/
X       case C_SAVE:
X`009if (strlen(arg2)) `123
X`009  strcpy(savefile, arg2);
X`009`125 else `123
X`009  fprintf(stderr, "File to save image mask to: ");
X`009  scanf("%s", savefile);
X`009  do `123`125 while (getchar() != '\n');
X`009`125
X`009if ((sfp = fopen(savefile, "wb")) == (FILE *) NULL) `123
X`009  fprintf(stderr, "error opening %s for binary write\n",
X`009   savefile);
X`009  perror("SAVE");
X`009`125 else `123
X`009  fwrite(bytetype, 512, mem_pages, sfp);
X`009  fclose(sfp);
X`009`125
X`009break;
X/*
X  UNSAVE
X*/
X       case C_UNSAVE:
X`009if (strlen(arg2)) `123
X`009  strcpy(savefile, arg2);
X`009`125 else `123
X`009  fprintf(stderr, "File to read image mask from: ");
X`009  scanf("%s", savefile);
X`009  do `123`125 while (getchar() != '\n');
X`009`125
X`009if ((sfp = fopen(savefile, "rb")) == (FILE *) NULL) `123
X`009  fprintf(stderr, "error opening %s for binary read\n",
X`009   savefile);
X`009  perror("UNSAVE");
X`009`125 else `123
X`009  fread(bytetype, 512, mem_pages, sfp);
X`009  fclose(sfp);
X`009`125
X`009break;
X/*
X  DUMP
X*/
X       case C_DUMP:
X`009dump(image, pc-base, top-base, pc);
X`009break;
X/*
X  STATS
X*/
X       case C_STATS:
X`009fprintf(stderr, "Stats for image %s\n", in_file);
X        disph(stderr);
X`009break;
X/*
X  SEARCH
X*/
X       case C_SEARCH:
X`009fprintf(stderr, "size of string (bytes): ");
X`009scanf("%d", &ssize);
X`009do `123`125 while (getchar() != '\n');
X`009if (ssize <= 0) `123
X`009  break;
X`009`125 else if (ssize >= sizeof(sstring)) `123
X`009  fprintf(stderr, "string size must be less than %d bytes\n",
X`009   sizeof(sstring));
X`009  break;
X`009`125
X`009for (i = 0; i < ssize; i++) `123
X`009  fprintf(stderr, "byte %d (decimal): ", i);
X`009  scanf("%d", &sstring[i]);
X`009  do `123`125 while (getchar() != '\n');
X`009`125
X`009for (; pc <= top; pc++) `123
X`009  for (i = 0; i < ssize; i++) `123
X`009    if (sstring[i] != image[pc-base+i])
X`009      break;
X`009  `125
X`009  if (i == ssize)
X`009    break;
X`009`125
X`009if (i == ssize) `123
X`009  fprintf(stderr, "string found at pc = %08X\n", pc);
X`009`125
X`009break;
X/*
X  HEADER dump
X*/
X       case C_HEADER:
X`009if (h_blocks) `123
X`009  for (i = 0; i < h_blocks; i++) `123
X`009    fprintf(stderr, "\nheader block %d\n\n", i);
X`009    dump(hb[i], 0, 512, 512*i);
X`009    dump(hb[i], 256, 512, 512*i+256);
X`009  `125
X`009`125 else `123
X`009  fprintf(stderr, "\nThere is no image header.\n");
X`009`125
X`009break;
X/*
X  HELP
X*/
X       case C_HELP:
X`009strcpy(helptmp, helpbuf);
X`009if (strlen(arg2)) `123
X`009  strcat(helptmp, " ");
X`009  strcat(helptmp, arg2);
X`009`125
X`009if (strlen(arg3)) `123
X`009  strcat(helptmp, " ");
X`009  strcat(helptmp, arg3);
X`009`125
X`009if (strlen(arg4)) `123
X`009  strcat(helptmp, " ");
X`009  strcat(helptmp, arg4);
X`009`125
X`009help.length = strlen(helptmp);
X`009Lib$Spawn(&help);
X`009break;
X/*
X  WRITE results to a file
X*/
X       case C_WRITE:
X`009if (strlen(arg2)) `123
X`009  strcpy(out_file, arg2);
X`009`125 else `123
X`009  fprintf(stderr, "File to save disassembled code to: ");
X`009  scanf("%s", out_file);
X`009  do `123`125 while (getchar() != '\n');
X`009`125
X`009if (freopen(out_file, "w", stdout) == (FILE *) NULL) `123
X`009  fprintf(stderr, "error reopening '%s' for write\n", out_file);
X`009  perror("WRITE");
X`009  exit(1);
X`009`125
X`009pre_pc = pc;
X`009pc = base;
X`009printf(";++\n");
X`009printf(";Stats for image %s\n", in_file);
X`009disph(stdout);
X`009printf(";--\n;++\n");
X`009if (h_blocks) `123
X`009  for (i = 0; i < h_blocks; i++) `123
X`009    printf(";header block %d\n;\n", i);
X`009    fdump(hb[i], 0, 512, 512*i);
X`009    fdump(hb[i], 256, 512, 512*i+256);
X`009  `125
X`009`125 else `123
X`009  printf(";There is no image header.\n");
X`009`125
X`009printf(";--\n");
X`009while (pc <= top) `123
X`009  if (bytetype[pc-base] < 0)
X`009    printf("L%X:", pc);
X`009  if (pos(bytetype[pc-base]) == C0_INSTRUCTION) `123
X`009    disassemble();
X`009  `125 else `123
X`009    undata();
X`009  `125
X`009`125
X`009printf("\t.end L%X\n", h_transfer1);
X`009pc = pre_pc;
X`009if (freopen("SYS$OUTPUT", "w", stdout) == (FILE *) NULL) `123
X`009  fprintf(stderr, "error reopening SYS$OUTPUT for write\n");
X`009  perror("WRITE");
X`009  exit(1);
X`009`125
X`009break;
X/*
X  SYMBOL
X*/
X       case C_SYMBOL:
X`009switch(command[1]) `123
X`009 case C13_DEFINE:
X          fprintf(stderr, "Symbol name (max %d chars): ", SYMNAMALLO);
X`009  sprintf(tmpline, "%%%ds", SYMNAMALLO);
X          scanf(tmpline, tmpsym); do `123`125 while (getchar() != '\n');
X          fprintf(stderr, "Symbol value: ");
X          scanf("%08X", &i); do `123`125 while (getchar() != '\n');
X`009  sym_add(tmpsym, i);
X          break;
X`009 case C13_LIST:
X`009  fprintf(stderr, "%d symbols defined\n", sym_count);
X          if (sym_count) `123
X            fprintf(stderr, "Symbol table:\n");
X            for (i=0; i<sym_count; i++)
X              fprintf(stderr, "%08X = '%s'\n", sym_value[i], sym_name[i]);
X          `125
X          break;
X`009 case C13_REMOVE:
X`009  fprintf(stderr, "SYMBOL REMOVE not working yet.  Sorry.\n");
X          break;
X        `125
X`009break;
X      `125
X    `125
X  `125 while ((command[0] != C_QUIT) && (command[0] != C_EXIT));
X  exit(1);
X`125
X/*
X  get a long word
X*/
Xlw(b)
Xint *b;
X`123
X  return(*b);
X`125
X/*
X  Dump a block
X*/
Xdump(address, start, limit, virtual)
Xchar *address;
Xint start;
Xint limit;
Xint virtual;
X`123
X  int i, j;
X
X  for (i=0; i<256; i+=16) `123
X    if (start+16 > limit)
X      break;
X    for (j=15; j>=0; --j)
X      fprintf(stderr, "%02X ", address[start+i+j] & 0xff);
X    fprintf(stderr, " ");
X    for (j=0; j<16; j++)
X      if (!iscntrl(address[start+i+j] & 0x7f))
X        fprintf(stderr, "%c", address[start+i+j] & 0x7f);
X      else
X        fprintf(stderr, ".");
X    fprintf(stderr, " %08X\n", virtual+i);
X  `125
X`125
X/*
X  Dump a block to the disassembly listing file
X*/
Xfdump(address, start, limit, virtual)
Xchar *address;
Xint start;
Xint limit;
Xint virtual;
X`123
X  int i, j;
X
X  for (i=0; i<256; i+=16) `123
X    if (start+16 > limit)
X      break;
X    printf(";");
X    for (j=15; j>=0; --j)
X      printf("%02X ", address[start+i+j] & 0xff);
X    printf(" ");
X    for (j=0; j<16; j++)
X      if (!iscntrl(address[start+i+j] & 0x7f))
X        printf("%c", address[start+i+j] & 0x7f);
X      else
X        printf(".");
X    printf(" %08X\n", virtual+i);
X  `125
X`125
X
X/*
X  "usage" error message
X*/
Xusage()
X`123
X  fprintf(stderr, "usage: unmacro [-h] imagefile[.exe]\n");
X  fprintf(stderr, "       unmacro -? for short help\n");
X  exit(1);
X`125
X
X/*
X  control-c interrupt handler
-+-+-+-+-+ End of part 6 +-+-+-+-+-
