| 1 | /*\r |
| 2 | * (C) Copyright 2002, Brian Knittel.\r |
| 3 | * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN\r |
| 4 | * RISK basis, there is no warranty of fitness for any purpose, and the rest of the\r |
| 5 | * usual yada-yada. Please keep this notice and the copyright in any distributions\r |
| 6 | * or modifications.\r |
| 7 | *\r |
| 8 | * This is not a supported product, but I welcome bug reports and fixes.\r |
| 9 | * Mail to sim@ibm1130.org\r |
| 10 | */\r |
| 11 | \r |
| 12 | // ---------------------------------------------------------------------------------\r |
| 13 | // BINDUMP - dumps card deck files in assembler object format\r |
| 14 | //\r |
| 15 | // Usage:\r |
| 16 | /// bindump deckfile lists object header info & sector break cards\r |
| 17 | // bindump -v deckfile lists object data records as well\r |
| 18 | // bindump -p deckfile for system program, lists phase IDs in the deck\r |
| 19 | // bindump -s deckfile >outfile for system program, sorts the phases & writes to stdout\r |
| 20 | \r |
| 21 | #include <stdio.h>\r |
| 22 | #include <stdlib.h>\r |
| 23 | #ifdef _WIN32\r |
| 24 | # include <windows.h>\r |
| 25 | # include <io.h>\r |
| 26 | # include <fcntl.h>\r |
| 27 | #endif\r |
| 28 | \r |
| 29 | #include "util_io.h"\r |
| 30 | \r |
| 31 | #ifndef TRUE\r |
| 32 | #define BOOL int\r |
| 33 | #define TRUE 1\r |
| 34 | #define FALSE 0\r |
| 35 | #endif\r |
| 36 | \r |
| 37 | typedef enum {R_ABSOLUTE = 0, R_RELATIVE = 1, R_LIBF = 2, R_CALL = 3} RELOC;\r |
| 38 | \r |
| 39 | BOOL verbose = FALSE;\r |
| 40 | BOOL phid = FALSE;\r |
| 41 | BOOL sort = FALSE;\r |
| 42 | unsigned short card[80], buf[54], cardtype;\r |
| 43 | \r |
| 44 | // bindump - dump a binary (card format) deck to verify sbrks, etc\r |
| 45 | \r |
| 46 | void bail (char *msg);\r |
| 47 | void dump (char *fname);\r |
| 48 | void dump_data (char *fname);\r |
| 49 | void dump_phids (char *fname);\r |
| 50 | char *getname (unsigned short *ptr);\r |
| 51 | char *getseq (void);\r |
| 52 | int hollerith_to_ascii (unsigned short h);\r |
| 53 | void process (char *fname);\r |
| 54 | void show_raw (char *name);\r |
| 55 | void show_data (void);\r |
| 56 | void show_core (void);\r |
| 57 | void show_endc (void);\r |
| 58 | void show_81 (void);\r |
| 59 | void show_main (void);\r |
| 60 | void show_sub (void);\r |
| 61 | void show_ils (void);\r |
| 62 | void show_iss (void);\r |
| 63 | void show_end (void);\r |
| 64 | void sort_phases (char *fname);\r |
| 65 | void trim (char *s);\r |
| 66 | void unpack (unsigned short *card, unsigned short *buf);\r |
| 67 | void verify_checksum(unsigned short *buf);\r |
| 68 | \r |
| 69 | int main (int argc, char **argv)\r |
| 70 | {\r |
| 71 | char *arg;\r |
| 72 | static char usestr[] = "Usage: bindump [-psv] filename...";\r |
| 73 | int i;\r |
| 74 | \r |
| 75 | for (i = 1; i < argc; i++) {\r |
| 76 | arg = argv[i];\r |
| 77 | if (*arg == '-') {\r |
| 78 | arg++;\r |
| 79 | while (*arg) {\r |
| 80 | switch (*arg++) {\r |
| 81 | case 'v':\r |
| 82 | verbose = TRUE;\r |
| 83 | break;\r |
| 84 | case 'p':\r |
| 85 | phid = TRUE; // print only phase ID's\r |
| 86 | break;\r |
| 87 | case 's':\r |
| 88 | sort = TRUE; // sort deck by phases, writing to stdout\r |
| 89 | break;\r |
| 90 | default:\r |
| 91 | bail(usestr);\r |
| 92 | }\r |
| 93 | }\r |
| 94 | }\r |
| 95 | }\r |
| 96 | \r |
| 97 | for (i = 1; i < argc; i++) {\r |
| 98 | arg = argv[i];\r |
| 99 | if (*arg != '-')\r |
| 100 | process(arg);\r |
| 101 | }\r |
| 102 | return 0;\r |
| 103 | }\r |
| 104 | \r |
| 105 | void process (char *nm)\r |
| 106 | {\r |
| 107 | #ifdef _WIN32\r |
| 108 | WIN32_FIND_DATA fd;\r |
| 109 | HANDLE hFind;\r |
| 110 | char *c, buf[256];\r |
| 111 | \r |
| 112 | if (strchr(nm, '*') == NULL && strchr(nm, '?') == NULL)\r |
| 113 | dump(nm);\r |
| 114 | \r |
| 115 | else if ((hFind = FindFirstFile(nm, &fd)) == INVALID_HANDLE_VALUE)\r |
| 116 | fprintf(stderr, "No files matching '%s'\n", nm);\r |
| 117 | \r |
| 118 | else {\r |
| 119 | if ((c = strrchr(nm, '\\')) == NULL)\r |
| 120 | c = strrchr(nm, ':');\r |
| 121 | \r |
| 122 | do {\r |
| 123 | if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)\r |
| 124 | continue;\r |
| 125 | \r |
| 126 | if (c == NULL)\r |
| 127 | dump(fd.cFileName);\r |
| 128 | else {\r |
| 129 | strcpy(buf, nm);\r |
| 130 | strcpy(buf + (c-nm+1), fd.cFileName);\r |
| 131 | dump(buf);\r |
| 132 | }\r |
| 133 | \r |
| 134 | } while (FindNextFile(hFind, &fd));\r |
| 135 | \r |
| 136 | FindClose(hFind);\r |
| 137 | }\r |
| 138 | #else\r |
| 139 | dump(nm); // on unices, sh globs for us\r |
| 140 | #endif\r |
| 141 | }\r |
| 142 | \r |
| 143 | void dump (char *fname)\r |
| 144 | {\r |
| 145 | if (sort)\r |
| 146 | sort_phases(fname);\r |
| 147 | else if (phid)\r |
| 148 | dump_phids(fname);\r |
| 149 | else\r |
| 150 | dump_data(fname);\r |
| 151 | }\r |
| 152 | \r |
| 153 | struct tag_card {\r |
| 154 | int phid, seq;\r |
| 155 | unsigned short card[80];\r |
| 156 | };\r |
| 157 | \r |
| 158 | int cardcomp (const void *a, const void *b)\r |
| 159 | {\r |
| 160 | short diff;\r |
| 161 | \r |
| 162 | diff = ((struct tag_card *) a)->phid - ((struct tag_card *) b)->phid;\r |
| 163 | \r |
| 164 | return diff ? diff : (((struct tag_card *) a)->seq - ((struct tag_card *) b)->seq);\r |
| 165 | }\r |
| 166 | \r |
| 167 | void sort_phases (char *fname)\r |
| 168 | {\r |
| 169 | int i, ncards, cardtype, len, seq = 0, phid;\r |
| 170 | struct tag_card *deck;\r |
| 171 | FILE *fd;\r |
| 172 | BOOL saw_sbrk = TRUE;\r |
| 173 | \r |
| 174 | if ((fd = fopen(fname, "rb")) == NULL) {\r |
| 175 | perror(fname);\r |
| 176 | return;\r |
| 177 | }\r |
| 178 | \r |
| 179 | fseek(fd, 0, SEEK_END);\r |
| 180 | len = ftell(fd); // get length of file\r |
| 181 | fseek(fd, 0, SEEK_SET);\r |
| 182 | \r |
| 183 | if (len <= 0 || (len % 160) != 0) {\r |
| 184 | fprintf(stderr, "%s is not a binard deck image\n");\r |
| 185 | fclose(fd);\r |
| 186 | return;\r |
| 187 | }\r |
| 188 | \r |
| 189 | ncards = len / 160;\r |
| 190 | \r |
| 191 | if ((deck = (struct tag_card *) malloc(ncards*sizeof(struct tag_card))) == NULL) {\r |
| 192 | fprintf(stderr, "%s: can't sort, insufficient memory\n");\r |
| 193 | fclose(fd);\r |
| 194 | return;\r |
| 195 | }\r |
| 196 | \r |
| 197 | phid = 0;\r |
| 198 | for (i = 0; i < ncards; i++) {\r |
| 199 | if (fxread(deck[i].card, sizeof(card[0]), 80, fd) != 80) {\r |
| 200 | free(deck);\r |
| 201 | fprintf(stderr, "%s: error reading deck\n");\r |
| 202 | fclose(fd);\r |
| 203 | return;\r |
| 204 | }\r |
| 205 | \r |
| 206 | unpack(deck[i].card, buf);\r |
| 207 | deck[i].seq = seq++;\r |
| 208 | deck[i].phid = phid;\r |
| 209 | \r |
| 210 | verify_checksum(buf);\r |
| 211 | \r |
| 212 | cardtype = (buf[2] >> 8) & 0xFF;\r |
| 213 | \r |
| 214 | if (cardtype == 1 || cardtype == 2) { // start of deck is same as sector break\r |
| 215 | saw_sbrk = TRUE;\r |
| 216 | }\r |
| 217 | else if (cardtype == 0) {\r |
| 218 | fprintf(stderr, "%s is a core image deck\n");\r |
| 219 | free(deck);\r |
| 220 | fclose(fd);\r |
| 221 | return;\r |
| 222 | }\r |
| 223 | else if (cardtype == 0x0A && saw_sbrk) {\r |
| 224 | phid = (int) (signed short) buf[10];\r |
| 225 | if (phid < 0)\r |
| 226 | phid = -phid;\r |
| 227 | \r |
| 228 | deck[i].phid = phid; // this belongs to the new phase\r |
| 229 | deck[i-1].phid = phid; // as does previous card\r |
| 230 | saw_sbrk = FALSE;\r |
| 231 | }\r |
| 232 | }\r |
| 233 | fclose(fd);\r |
| 234 | \r |
| 235 | qsort(deck, ncards, sizeof(struct tag_card), cardcomp); // sort the deck\r |
| 236 | \r |
| 237 | #ifdef _WIN32\r |
| 238 | _setmode(_fileno(stdout), _O_BINARY); // set standard output to binary mode\r |
| 239 | #endif\r |
| 240 | \r |
| 241 | for (i = 0; i < ncards; i++) // write to stdout\r |
| 242 | fxwrite(deck[i].card, sizeof(card[0]), 80, stdout);\r |
| 243 | \r |
| 244 | free(deck);\r |
| 245 | }\r |
| 246 | \r |
| 247 | void dump_phids (char *fname)\r |
| 248 | {\r |
| 249 | FILE *fp;\r |
| 250 | BOOL first = TRUE;\r |
| 251 | BOOL saw_sbrk = TRUE, neg;\r |
| 252 | short id;\r |
| 253 | \r |
| 254 | if ((fp = fopen(fname, "rb")) == NULL) {\r |
| 255 | perror(fname);\r |
| 256 | return;\r |
| 257 | }\r |
| 258 | \r |
| 259 | printf("\n%s:\n", fname);\r |
| 260 | \r |
| 261 | while (fxread(card, sizeof(card[0]), 80, fp) > 0) {\r |
| 262 | unpack(card, buf);\r |
| 263 | verify_checksum(buf);\r |
| 264 | \r |
| 265 | cardtype = (buf[2] >> 8) & 0xFF;\r |
| 266 | \r |
| 267 | if (cardtype == 1 && ! first) { // sector break\r |
| 268 | saw_sbrk = TRUE;\r |
| 269 | continue;\r |
| 270 | }\r |
| 271 | else {\r |
| 272 | switch (cardtype) {\r |
| 273 | case 0x00:\r |
| 274 | printf(" This is a core image deck\n");\r |
| 275 | goto done;\r |
| 276 | break;\r |
| 277 | case 0x01:\r |
| 278 | case 0x02:\r |
| 279 | case 0x03:\r |
| 280 | case 0x04:\r |
| 281 | case 0x05:\r |
| 282 | case 0x06:\r |
| 283 | case 0x07:\r |
| 284 | case 0x0F:\r |
| 285 | break;\r |
| 286 | \r |
| 287 | case 0x0A:\r |
| 288 | if (saw_sbrk) {\r |
| 289 | id = buf[10];\r |
| 290 | if (id < 0)\r |
| 291 | id = -id, neg = TRUE;\r |
| 292 | else\r |
| 293 | neg = FALSE;\r |
| 294 | printf(" : %3d / %02x%s\n", id, id, neg ? " (neg)" : "");\r |
| 295 | saw_sbrk = FALSE;\r |
| 296 | }\r |
| 297 | break;\r |
| 298 | \r |
| 299 | default:\r |
| 300 | show_raw("??? ");\r |
| 301 | }\r |
| 302 | }\r |
| 303 | done:\r |
| 304 | first = FALSE;\r |
| 305 | }\r |
| 306 | \r |
| 307 | fclose(fp);\r |
| 308 | }\r |
| 309 | \r |
| 310 | void dump_data (char *fname)\r |
| 311 | {\r |
| 312 | FILE *fp;\r |
| 313 | BOOL first = TRUE;\r |
| 314 | char str[80];\r |
| 315 | int i;\r |
| 316 | \r |
| 317 | if ((fp = fopen(fname, "rb")) == NULL) {\r |
| 318 | perror(fname);\r |
| 319 | return;\r |
| 320 | }\r |
| 321 | \r |
| 322 | printf("\n%s:\n", fname);\r |
| 323 | \r |
| 324 | while (fxread(card, sizeof(card[0]), 80, fp) > 0) {\r |
| 325 | unpack(card, buf);\r |
| 326 | verify_checksum(buf);\r |
| 327 | \r |
| 328 | cardtype = (buf[2] >> 8) & 0xFF;\r |
| 329 | \r |
| 330 | if (cardtype == 1 && ! first) { // sector break\r |
| 331 | for (i = 4; i < 72; i++)\r |
| 332 | str[i] = hollerith_to_ascii(card[i]);\r |
| 333 | \r |
| 334 | str[i] = '\0';\r |
| 335 | trim(str+4);\r |
| 336 | printf("*SBRK %s\n", str+4);\r |
| 337 | continue;\r |
| 338 | }\r |
| 339 | else {\r |
| 340 | switch (cardtype) {\r |
| 341 | case 0x00:\r |
| 342 | if (first)\r |
| 343 | show_raw("CORE");\r |
| 344 | if (verbose)\r |
| 345 | show_core();\r |
| 346 | break;\r |
| 347 | \r |
| 348 | case 0x01:\r |
| 349 | show_raw("ABS ");\r |
| 350 | show_main();\r |
| 351 | break;\r |
| 352 | case 0x02:\r |
| 353 | show_raw("REL ");\r |
| 354 | show_main();\r |
| 355 | break;\r |
| 356 | case 0x03:\r |
| 357 | show_raw("LIB ");\r |
| 358 | show_sub();\r |
| 359 | break;\r |
| 360 | case 0x04:\r |
| 361 | show_raw("SUB ");\r |
| 362 | show_sub();\r |
| 363 | break;\r |
| 364 | case 0x05:\r |
| 365 | show_raw("ISSL");\r |
| 366 | show_iss();\r |
| 367 | break;\r |
| 368 | case 0x06:\r |
| 369 | show_raw("ISSC");\r |
| 370 | show_iss();\r |
| 371 | break;\r |
| 372 | case 0x07:\r |
| 373 | show_raw("ILS ");\r |
| 374 | show_ils();\r |
| 375 | break;\r |
| 376 | case 0x0F:\r |
| 377 | show_raw("END ");\r |
| 378 | show_end();\r |
| 379 | break;\r |
| 380 | case 0x80:\r |
| 381 | show_raw("ENDC");\r |
| 382 | show_endc();\r |
| 383 | break;\r |
| 384 | case 0x81:\r |
| 385 | show_raw("81 ");\r |
| 386 | show_81();\r |
| 387 | break;\r |
| 388 | case 0x0A:\r |
| 389 | if (verbose)\r |
| 390 | show_data();\r |
| 391 | break;\r |
| 392 | default:\r |
| 393 | show_raw("??? ");\r |
| 394 | }\r |
| 395 | }\r |
| 396 | \r |
| 397 | first = FALSE;\r |
| 398 | }\r |
| 399 | \r |
| 400 | fclose(fp);\r |
| 401 | }\r |
| 402 | \r |
| 403 | void show_data (void)\r |
| 404 | {\r |
| 405 | int i, n, jrel, rflag, nout, ch, reloc;\r |
| 406 | BOOL first = TRUE;\r |
| 407 | \r |
| 408 | n = buf[2] & 0x00FF;\r |
| 409 | \r |
| 410 | printf("%04x: ", buf[0]);\r |
| 411 | \r |
| 412 | jrel = 3;\r |
| 413 | nout = 0;\r |
| 414 | rflag = buf[jrel++];\r |
| 415 | for (i = 0; i < n; i++) {\r |
| 416 | if (nout >= 8) {\r |
| 417 | rflag = buf[jrel++];\r |
| 418 | if (first) {\r |
| 419 | printf(" %s", getseq());\r |
| 420 | first = FALSE;\r |
| 421 | }\r |
| 422 | printf("\n ");\r |
| 423 | nout = 0;\r |
| 424 | }\r |
| 425 | reloc = (rflag >> 14) & 0x03;\r |
| 426 | ch = (reloc == R_ABSOLUTE) ? ' ' :\r |
| 427 | (reloc == R_RELATIVE) ? 'R' :\r |
| 428 | (reloc == R_LIBF) ? 'L' : '@';\r |
| 429 | \r |
| 430 | printf("%04x%c ", buf[9+i], ch);\r |
| 431 | rflag <<= 2;\r |
| 432 | nout++;\r |
| 433 | }\r |
| 434 | putchar('\n');\r |
| 435 | }\r |
| 436 | \r |
| 437 | void show_core (void)\r |
| 438 | {\r |
| 439 | int i, n, nout;\r |
| 440 | BOOL first = TRUE;\r |
| 441 | \r |
| 442 | n = buf[2] & 0x00FF;\r |
| 443 | \r |
| 444 | printf("%04x: ", buf[0]);\r |
| 445 | \r |
| 446 | nout = 0;\r |
| 447 | for (i = 0; i < n; i++) {\r |
| 448 | if (nout >= 8) {\r |
| 449 | if (first) {\r |
| 450 | printf(" %s", getseq());\r |
| 451 | first = FALSE;\r |
| 452 | }\r |
| 453 | printf("\n ");\r |
| 454 | nout = 0;\r |
| 455 | }\r |
| 456 | printf("%04x ", buf[9+i]);\r |
| 457 | nout++;\r |
| 458 | }\r |
| 459 | putchar('\n');\r |
| 460 | }\r |
| 461 | \r |
| 462 | void info (int i, char *nm, char type)\r |
| 463 | {\r |
| 464 | if (nm)\r |
| 465 | printf("%s ", nm);\r |
| 466 | \r |
| 467 | switch (type) {\r |
| 468 | case 'd':\r |
| 469 | printf("%d ", buf[i]);\r |
| 470 | break;\r |
| 471 | \r |
| 472 | case 'x':\r |
| 473 | printf("%04x ", buf[i]);\r |
| 474 | break;\r |
| 475 | \r |
| 476 | case 'b':\r |
| 477 | printf("%02x ", buf[i] & 0xFF);\r |
| 478 | break;\r |
| 479 | \r |
| 480 | case 'n':\r |
| 481 | printf("%s ", getname(buf+i));\r |
| 482 | break;\r |
| 483 | \r |
| 484 | default:\r |
| 485 | bail("BAD TYPE");\r |
| 486 | }\r |
| 487 | }\r |
| 488 | \r |
| 489 | void show_main (void)\r |
| 490 | {\r |
| 491 | printf(" ");\r |
| 492 | info(2, "prec", 'b');\r |
| 493 | info(4, "common", 'd');\r |
| 494 | info(6, "work", 'd');\r |
| 495 | info(8, "files", 'd');\r |
| 496 | info(9, "name", 'n');\r |
| 497 | info(11, "pta", 'x');\r |
| 498 | putchar('\n');\r |
| 499 | }\r |
| 500 | \r |
| 501 | void show_sub (void)\r |
| 502 | {\r |
| 503 | int i, n;\r |
| 504 | \r |
| 505 | printf(" ");\r |
| 506 | info( 2, "prec", 'b');\r |
| 507 | \r |
| 508 | n = buf[5] / 3;\r |
| 509 | for (i = 0; i < n; i++) {\r |
| 510 | info( 9+3*i, "ent", 'n');\r |
| 511 | info(11+3*i, NULL, 'x');\r |
| 512 | }\r |
| 513 | \r |
| 514 | putchar('\n');\r |
| 515 | }\r |
| 516 | \r |
| 517 | void show_iss (void)\r |
| 518 | {\r |
| 519 | printf(" ");\r |
| 520 | info(12, "level", 'd');\r |
| 521 | putchar('\n');\r |
| 522 | }\r |
| 523 | \r |
| 524 | void show_ils (void)\r |
| 525 | {\r |
| 526 | printf(" ");\r |
| 527 | info( 2, "prec", 'b');\r |
| 528 | info( 5, "nint6", 'd');\r |
| 529 | info( 9, "ent", 'n');\r |
| 530 | info(11, NULL, 'x');\r |
| 531 | info(14, "nint", 'd');\r |
| 532 | info(15, "il1", 'd');\r |
| 533 | info(16, "il2", 'd');\r |
| 534 | putchar('\n');\r |
| 535 | }\r |
| 536 | \r |
| 537 | void show_end (void)\r |
| 538 | {\r |
| 539 | printf(" ");\r |
| 540 | info(0, "size", 'd');\r |
| 541 | info(3, "pta", 'x');\r |
| 542 | putchar('\n');\r |
| 543 | }\r |
| 544 | \r |
| 545 | void show_endc(void)\r |
| 546 | {\r |
| 547 | printf(" ");\r |
| 548 | info(52, "IX3", 'x');\r |
| 549 | info(53, "pta", 'x');\r |
| 550 | putchar('\n');\r |
| 551 | }\r |
| 552 | \r |
| 553 | void show_81(void)\r |
| 554 | {\r |
| 555 | }\r |
| 556 | \r |
| 557 | void show_raw (char *name)\r |
| 558 | {\r |
| 559 | int i;\r |
| 560 | printf("*%s", name);\r |
| 561 | \r |
| 562 | for (i = 0; i < 12; i++)\r |
| 563 | printf(" %04x", buf[i]);\r |
| 564 | \r |
| 565 | printf(" %s\n", getseq());\r |
| 566 | }\r |
| 567 | \r |
| 568 | char * getseq (void)\r |
| 569 | {\r |
| 570 | static char seq[10];\r |
| 571 | int i;\r |
| 572 | \r |
| 573 | for (i = 0; i < 8; i++)\r |
| 574 | seq[i] = hollerith_to_ascii(card[72+i]);\r |
| 575 | \r |
| 576 | seq[i] = '\0';\r |
| 577 | return seq;\r |
| 578 | }\r |
| 579 | \r |
| 580 | \r |
| 581 | void bail (char *msg)\r |
| 582 | {\r |
| 583 | fprintf(stderr, "%s\n", msg);\r |
| 584 | exit(1);\r |
| 585 | }\r |
| 586 | \r |
| 587 | void unpack (unsigned short *icard, unsigned short *obuf)\r |
| 588 | {\r |
| 589 | int i, j;\r |
| 590 | unsigned short wd1, wd2, wd3, wd4;\r |
| 591 | \r |
| 592 | for (i = j = 0; i < 54; i += 3, j += 4) {\r |
| 593 | wd1 = icard[j];\r |
| 594 | wd2 = icard[j+1];\r |
| 595 | wd3 = icard[j+2];\r |
| 596 | wd4 = icard[j+3];\r |
| 597 | \r |
| 598 | obuf[i ] = (wd1 & 0xFFF0) | ((wd2 >> 12) & 0x000F);\r |
| 599 | obuf[i+1] = ((wd2 << 4) & 0xFF00) | ((wd3 >> 8) & 0x00FF);\r |
| 600 | obuf[i+2] = ((wd3 << 8) & 0xF000) | ((wd4 >> 4) & 0x0FFF);\r |
| 601 | }\r |
| 602 | }\r |
| 603 | \r |
| 604 | void verify_checksum (unsigned short *obuf)\r |
| 605 | {\r |
| 606 | // unsigned short sum;\r |
| 607 | \r |
| 608 | if (obuf[1] == 0) // no checksum\r |
| 609 | return;\r |
| 610 | \r |
| 611 | // if (sum != card[1])\r |
| 612 | // printf("Checksum %04x doesn't match card %04x\n", sum, card[1]);\r |
| 613 | }\r |
| 614 | \r |
| 615 | typedef struct {\r |
| 616 | unsigned short hollerith;\r |
| 617 | char ascii;\r |
| 618 | } CPCODE;\r |
| 619 | \r |
| 620 | static CPCODE cardcode_029[] =\r |
| 621 | {\r |
| 622 | 0x0000, ' ',\r |
| 623 | 0x8000, '&', // + in 026 Fortran\r |
| 624 | 0x4000, '-',\r |
| 625 | 0x2000, '0',\r |
| 626 | 0x1000, '1',\r |
| 627 | 0x0800, '2',\r |
| 628 | 0x0400, '3',\r |
| 629 | 0x0200, '4',\r |
| 630 | 0x0100, '5',\r |
| 631 | 0x0080, '6',\r |
| 632 | 0x0040, '7',\r |
| 633 | 0x0020, '8',\r |
| 634 | 0x0010, '9',\r |
| 635 | 0x9000, 'A',\r |
| 636 | 0x8800, 'B',\r |
| 637 | 0x8400, 'C',\r |
| 638 | 0x8200, 'D',\r |
| 639 | 0x8100, 'E',\r |
| 640 | 0x8080, 'F',\r |
| 641 | 0x8040, 'G',\r |
| 642 | 0x8020, 'H',\r |
| 643 | 0x8010, 'I',\r |
| 644 | 0x5000, 'J',\r |
| 645 | 0x4800, 'K',\r |
| 646 | 0x4400, 'L',\r |
| 647 | 0x4200, 'M',\r |
| 648 | 0x4100, 'N',\r |
| 649 | 0x4080, 'O',\r |
| 650 | 0x4040, 'P',\r |
| 651 | 0x4020, 'Q',\r |
| 652 | 0x4010, 'R',\r |
| 653 | 0x3000, '/',\r |
| 654 | 0x2800, 'S',\r |
| 655 | 0x2400, 'T',\r |
| 656 | 0x2200, 'U',\r |
| 657 | 0x2100, 'V',\r |
| 658 | 0x2080, 'W',\r |
| 659 | 0x2040, 'X',\r |
| 660 | 0x2020, 'Y',\r |
| 661 | 0x2010, 'Z',\r |
| 662 | 0x0820, ':',\r |
| 663 | 0x0420, '#', // = in 026 Fortran\r |
| 664 | 0x0220, '@', // ' in 026 Fortran\r |
| 665 | 0x0120, '\'',\r |
| 666 | 0x00A0, '=',\r |
| 667 | 0x0060, '"',\r |
| 668 | 0x8820, 'c', // cent\r |
| 669 | 0x8420, '.',\r |
| 670 | 0x8220, '<', // ) in 026 Fortran\r |
| 671 | 0x8120, '(',\r |
| 672 | 0x80A0, '+',\r |
| 673 | 0x8060, '|',\r |
| 674 | 0x4820, '!',\r |
| 675 | 0x4420, '$',\r |
| 676 | 0x4220, '*',\r |
| 677 | 0x4120, ')',\r |
| 678 | 0x40A0, ';',\r |
| 679 | 0x4060, 'n', // not\r |
| 680 | 0x2820, 'x', // what?\r |
| 681 | 0x2420, ',',\r |
| 682 | 0x2220, '%', // ( in 026 Fortran\r |
| 683 | 0x2120, '_',\r |
| 684 | 0x20A0, '>',\r |
| 685 | 0x2060, '>',\r |
| 686 | };\r |
| 687 | \r |
| 688 | int hollerith_to_ascii (unsigned short h)\r |
| 689 | {\r |
| 690 | int i;\r |
| 691 | \r |
| 692 | h &= 0xFFF0;\r |
| 693 | \r |
| 694 | for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++)\r |
| 695 | if (cardcode_029[i].hollerith == h)\r |
| 696 | return cardcode_029[i].ascii;\r |
| 697 | \r |
| 698 | return '?';\r |
| 699 | }\r |
| 700 | \r |
| 701 | // ---------------------------------------------------------------------------------\r |
| 702 | // trim - remove trailing whitespace from string s\r |
| 703 | // ---------------------------------------------------------------------------------\r |
| 704 | \r |
| 705 | void trim (char *s)\r |
| 706 | {\r |
| 707 | char *nb;\r |
| 708 | \r |
| 709 | for (nb = s-1; *s; s++)\r |
| 710 | if (*s > ' ')\r |
| 711 | nb = s;\r |
| 712 | \r |
| 713 | nb[1] = '\0';\r |
| 714 | }\r |
| 715 | \r |
| 716 | int ascii_to_ebcdic_table[128] = \r |
| 717 | {\r |
| 718 | 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f,\r |
| 719 | 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f,\r |
| 720 | 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61,\r |
| 721 | 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f,\r |
| 722 | \r |
| 723 | 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,\r |
| 724 | 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d,\r |
| 725 | 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96,\r |
| 726 | 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07,\r |
| 727 | };\r |
| 728 | \r |
| 729 | char *getname (unsigned short *ptr)\r |
| 730 | {\r |
| 731 | static char str[6];\r |
| 732 | int i, j, ch;\r |
| 733 | long v;\r |
| 734 | \r |
| 735 | v = (ptr[0] << 16L) | ptr[1];\r |
| 736 | \r |
| 737 | for (i = 0; i < 5; i++) {\r |
| 738 | ch = ((v >> 24) & 0x3F) | 0xC0; // recover those lost two bits\r |
| 739 | v <<= 6;\r |
| 740 | \r |
| 741 | str[i] = ' ';\r |
| 742 | \r |
| 743 | for (j = 0; j < (sizeof(ascii_to_ebcdic_table)/sizeof(ascii_to_ebcdic_table[0])); j++) {\r |
| 744 | if (ascii_to_ebcdic_table[j] == ch) {\r |
| 745 | str[i] = j;\r |
| 746 | break;\r |
| 747 | }\r |
| 748 | }\r |
| 749 | }\r |
| 750 | \r |
| 751 | str[5] = '\0';\r |
| 752 | return str;\r |
| 753 | }\r |
| 754 | \r |
| 755 | \r |