mirror of
https://github.com/kenrector/sds-kit.git
synced 2026-01-11 23:43:17 +00:00
495 lines
12 KiB
C
Executable File
495 lines
12 KiB
C
Executable File
/***********************************************************************
|
|
*
|
|
* Build up a deck. Remove blank and invalid cards.
|
|
*
|
|
***********************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
int sequence = 0;
|
|
int cardno = 1;
|
|
int image_mode = 0;
|
|
int fcard = 0;
|
|
int lcard = -1;
|
|
int ccard = 0;
|
|
char *label = NULL;
|
|
int wrdnum;
|
|
|
|
const unsigned short ascii_to_hol[128] = {
|
|
/* Control */
|
|
0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,0xf000, /*0-37*/
|
|
/*Control*/
|
|
0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,
|
|
/*Control*/
|
|
0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,
|
|
/*Control*/
|
|
0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,
|
|
/* sp ! " # $ % & ' */
|
|
0x000, 0x482, 0x006, 0x282, 0x442, 0x222, 0x800, 0x022, /* 40 - 77 */
|
|
/* ( ) * + , - . / */
|
|
0x222, 0x822, 0x422, 0x800, 0x242, 0x400, 0x842, 0x300,
|
|
/* 0 1 2 3 4 5 6 7 */
|
|
0x200, 0x100, 0x080, 0x040, 0x020, 0x010, 0x008, 0x004,
|
|
/* 8 9 : ; < = > ? */
|
|
0x002, 0x001, 0x012, 0x40A, 0x80A, 0x042, 0x00A, 0x882,
|
|
/* @ A B C D E F G */
|
|
0x022, 0x900, 0x880, 0x840, 0x820, 0x810, 0x808, 0x804, /* 100 - 137 */
|
|
/* H I J K L M N O */
|
|
0x802, 0x801, 0x500, 0x480, 0x440, 0x420, 0x410, 0x408,
|
|
/* P Q R S T U V W */
|
|
0x404, 0x402, 0x401, 0x280, 0x240, 0x220, 0x210, 0x208,
|
|
/* X Y Z [ \ ] ^ _ */
|
|
0x204, 0x202, 0x201, 0x812, 0x20A, 0x412, 0x406, 0x082,
|
|
/* ` a b c d e f g */
|
|
0x212, 0x900, 0x880, 0x840, 0x820, 0x810, 0x808, 0x804, /* 140 - 177 */
|
|
/* h i j k l m n o */
|
|
0x802, 0x801, 0x500, 0x480, 0x440, 0x420, 0x410, 0x408,
|
|
/* p q r s t u v w */
|
|
0x404, 0x402, 0x401, 0x280, 0x240, 0x220, 0x210, 0x208,
|
|
/* x y z { | } ~ del*/
|
|
0x204, 0x202, 0x201, 0x206, 0x806,0xf000,0xf000,0xf000
|
|
};
|
|
|
|
unsigned char parity_table[64] = {
|
|
/* 0 1 2 3 4 5 6 7 */
|
|
0000, 0100, 0100, 0000, 0100, 0000, 0000, 0100,
|
|
0100, 0000, 0000, 0100, 0000, 0100, 0100, 0000,
|
|
0100, 0000, 0000, 0100, 0000, 0100, 0100, 0000,
|
|
0000, 0100, 0100, 0000, 0100, 0000, 0000, 0100,
|
|
0100, 0000, 0000, 0100, 0000, 0100, 0100, 0000,
|
|
0000, 0100, 0100, 0000, 0100, 0000, 0000, 0100,
|
|
0000, 0100, 0100, 0000, 0100, 0000, 0000, 0100,
|
|
0100, 0000, 0000, 0100, 0000, 0100, 0100, 0000
|
|
};
|
|
|
|
|
|
/* Dump card image to output file */
|
|
void dump_card(FILE *of, unsigned short image[80]) {
|
|
int t;
|
|
int i, j;
|
|
unsigned char out[160];
|
|
|
|
|
|
/* Fill in label columns */
|
|
if (label) {
|
|
char *p = label;
|
|
unsigned short temp;
|
|
for (i = 72; i < 80; i++) {
|
|
temp = ascii_to_hol[*p++];
|
|
if ((temp & 0xf000) == 0)
|
|
image[i] = temp;
|
|
|
|
}
|
|
}
|
|
|
|
/* Add sequence */
|
|
if (sequence) {
|
|
i = cardno;
|
|
j = 79;
|
|
while( i != 0) {
|
|
t = i % 10;
|
|
if (t == 0)
|
|
image[j] = 0x200;
|
|
else
|
|
image[j] = 1 << (9 - t);
|
|
j--;
|
|
i -= t;
|
|
i /= 10;
|
|
}
|
|
}
|
|
|
|
/* Fill buffer */
|
|
for (i = 0; i < 80; i++) {
|
|
unsigned short int col = image[i];
|
|
out[i*2] = (col >> 6) & 077;
|
|
out[i*2+1] = col & 077;
|
|
}
|
|
|
|
/* Now set parity */
|
|
for (i = 0; i < 160; i++)
|
|
out[i] |= 0100 ^ parity_table[(int)out[i]];
|
|
out[0] |= 0x80; /* Set record mark */
|
|
i = 160;
|
|
fwrite(out, 1, i, of);
|
|
cardno++;
|
|
}
|
|
|
|
/* Dump a text file as hollerith based images */
|
|
void dump_text(FILE *of, FILE *f) {
|
|
int col;
|
|
unsigned short image[80];
|
|
char ch;
|
|
unsigned short temp;
|
|
|
|
memset(image, 0, sizeof(image)); /* Clear image */
|
|
col = 0;
|
|
while(!feof(f)) {
|
|
ch = fgetc(f);
|
|
switch(ch) {
|
|
case '\0':
|
|
case '\r': break;
|
|
default:
|
|
temp = ascii_to_hol[ch];
|
|
if ((temp & 0xf000) == 0 && col < 80)
|
|
image[col++] = temp;
|
|
break;
|
|
case '\n':
|
|
dump_card(of, image);
|
|
memset(image, 0, sizeof(image));
|
|
col = 0;
|
|
break;
|
|
case '\t':
|
|
col = (col | 7) + 1; /* Mult of 8 */
|
|
break;
|
|
}
|
|
}
|
|
if (col != 0)
|
|
dump_card(of, image);
|
|
}
|
|
|
|
/* Produce a transfer card */
|
|
void transfer_card(char *addr, FILE *of) {
|
|
unsigned short image[80];
|
|
int loc = 0;
|
|
int i;
|
|
|
|
memset(image, 0, sizeof(image));
|
|
image[43] = 1;
|
|
if (*addr == '0') { /* Octal */
|
|
while(*addr != '\0') {
|
|
loc <<= 3;
|
|
loc += *addr++ - '0';
|
|
}
|
|
} else { /* Decimal */
|
|
while(*addr != '\0') {
|
|
loc *= 10;
|
|
loc += *addr++ - '0';
|
|
}
|
|
}
|
|
for(i = 71; i > 56; i--) {
|
|
if (loc & 1)
|
|
image[i] = 1;
|
|
loc >>= 1;
|
|
}
|
|
dump_card(of, image);
|
|
}
|
|
|
|
/* Set address for correction card */
|
|
void set_addr(char *addr, unsigned short image[80]) {
|
|
int loc = 0;
|
|
int i;
|
|
memset(image, 0, 80);
|
|
if (*addr == '0') {
|
|
while(*addr != '\0') {
|
|
loc <<= 3;
|
|
loc += *addr++ - '0';
|
|
}
|
|
} else {
|
|
while(*addr != '\0') {
|
|
loc *= 10;
|
|
loc += *addr++ - '0';
|
|
}
|
|
}
|
|
for(i = 35; i > 20; i--) {
|
|
if (loc & 1)
|
|
image[i] = 1;
|
|
loc >>= 1;
|
|
}
|
|
wrdnum = 0;
|
|
}
|
|
|
|
/* Add correction data */
|
|
int add_data(char *addr, unsigned short image[80]) {
|
|
int long long data = 0;
|
|
int i;
|
|
int digit = 2 << (wrdnum / 2);
|
|
int col = (wrdnum&1)?36:0;
|
|
|
|
if (addr == 0)
|
|
return 0;
|
|
if (*addr == '-') {
|
|
data = (long long)1 << 36;
|
|
addr++;
|
|
}
|
|
if (*addr == '0') {
|
|
while(*addr != '\0') {
|
|
data <<= 3;
|
|
data += *addr++ - '0';
|
|
}
|
|
} else if (*addr >= '1' && *addr <= '9') {
|
|
while(*addr != '\0') {
|
|
if (*addr < '0' || *addr > '9')
|
|
return 0;
|
|
data *= 10;
|
|
data += *addr++ - '0';
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
for(i = 35; i >= 0; i--) {
|
|
if (data & 1)
|
|
image[i+col] |= digit;
|
|
data >>= 1;
|
|
}
|
|
wrdnum++;
|
|
return 1;
|
|
}
|
|
|
|
/* Compute checksum and put word count into correction card */
|
|
void checksum(unsigned short image[80]) {
|
|
int long long data = wrdnum;
|
|
int i;
|
|
int row;
|
|
|
|
/* Word count into correct spot */
|
|
for(i = 17; i > 10; i--) {
|
|
if (data & 1)
|
|
image[i] |= 1;
|
|
data >>= 1;
|
|
}
|
|
|
|
/* Sum up all data on card */
|
|
data = 0;
|
|
for (row = 0; row < 12; row++) {
|
|
long long wd = 0;
|
|
int mask = 1 << row;
|
|
for (i = 0; i < 36; i++) {
|
|
wd <<= 1;
|
|
if (image[i] & mask)
|
|
wd |= 1;
|
|
}
|
|
data += wd;
|
|
if (data & ((long long)1 << 37))
|
|
data++;
|
|
data &= ((long long)1 << 37) - 1;
|
|
wd = 0;
|
|
for (i = 0; i < 36; i++) {
|
|
wd <<= 1;
|
|
if (image[i+36] & mask)
|
|
wd |= 1;
|
|
}
|
|
data += wd;
|
|
if (data & ((long long)1 << 37))
|
|
data++;
|
|
data &= ((long long)1 << 37) - 1;
|
|
}
|
|
|
|
/* Put sum into correct place */
|
|
for(i = 35; i >= 0; i--) {
|
|
if (data & 1)
|
|
image[i+36] |= 1;
|
|
data >>= 1;
|
|
}
|
|
}
|
|
|
|
/* Check if card should be copied to output file */
|
|
int good_card(unsigned short image[80]) {
|
|
int t;
|
|
int i, j;
|
|
unsigned long long wd;
|
|
int bl;
|
|
|
|
ccard++;
|
|
if (image_mode)
|
|
return 1;
|
|
for (t = i = 0; i < 80; i++) t |= image[i];
|
|
if (t == 0) {
|
|
return 0; /* Ignore blank cards */
|
|
} else if (ccard < fcard) { /* Before first card? */
|
|
return 0;
|
|
} else if (lcard > 0 && ccard > lcard) { /* After the last card? */
|
|
return 0;
|
|
} else {
|
|
wd = 0;
|
|
t = 1;
|
|
bl = 0;
|
|
/* Check first word of card */
|
|
for (j = 0, i = 0; i < 36; i++) {
|
|
wd = (wd << 1) | (image[i] & 1);
|
|
t &= image[i] & 1;
|
|
bl |= image[i] & 1;
|
|
}
|
|
/* Check 9R word */
|
|
for (; i < 72; i++) {
|
|
bl |= image[i] & 1;
|
|
}
|
|
/* If all ones, skip this */
|
|
if (t) {
|
|
return 0;
|
|
}
|
|
/* If no data in 9L/9R, skip */
|
|
if (bl == 0 || wd == 0200000000000LL) {
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* Pretty print card for show */
|
|
void print_card(unsigned short image[80]) {
|
|
int t;
|
|
int row;
|
|
int i, j;
|
|
|
|
for (t = i = 0; i < 80; i++) t |= image[i];
|
|
if (t == 0) {
|
|
printf("blank\n");
|
|
} else {
|
|
t = 0;
|
|
for(row=0; row < 12; row++) {
|
|
int mask = 1 << row;
|
|
for (j = 0, i = 0; i < 72; i++) {
|
|
t <<= 1;
|
|
if (image[i] & mask)
|
|
t |= 1;
|
|
if (j == 2) {
|
|
putchar('0' + t);
|
|
t = 0;
|
|
j = 0;
|
|
} else
|
|
j++;
|
|
if (i == 35)
|
|
putchar(' ');
|
|
}
|
|
putchar('\n');
|
|
}
|
|
putchar('-');
|
|
putchar('\n');
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int
|
|
main(int argc, char *argv[]) {
|
|
unsigned short image[80];
|
|
int col;
|
|
int t;
|
|
int i, j;
|
|
unsigned char ch;
|
|
int card;
|
|
char *n;
|
|
FILE *of = stdout;
|
|
FILE *f;
|
|
|
|
card = 0;
|
|
while((n = *++argv) != NULL) {
|
|
if (*n == '-') {
|
|
switch (n[1]) {
|
|
case 'o': /* Output file */
|
|
n = *++argv;
|
|
if ((of = fopen(n, "wb")) == NULL) {
|
|
fprintf(stderr, "Unable to open: %s for output\n", n);
|
|
exit(1);
|
|
}
|
|
break;
|
|
case 't': /* Tranfer card */
|
|
transfer_card(*++argv, of);
|
|
break;
|
|
case 'B': /* Truely Blank card. */
|
|
memset(image, 0, sizeof(image));
|
|
{
|
|
int seq = sequence;
|
|
char *lab = label;
|
|
sequence = 0;
|
|
label = NULL;
|
|
dump_card(of, image);
|
|
sequence = seq;
|
|
label = lab;
|
|
}
|
|
break;
|
|
case 'b': /* Blank card */
|
|
memset(image, 0, sizeof(image));
|
|
dump_card(of, image);
|
|
break;
|
|
case 'a': /* Ascii text card */
|
|
n = *++argv;
|
|
if ((f = fopen(n, "r")) == NULL) {
|
|
fprintf(stderr, "Unable to open: %s\n", n);
|
|
exit(1);
|
|
}
|
|
dump_text(of, f);
|
|
fclose(f);
|
|
break;
|
|
case 'i': /* Toggle image mode */
|
|
image_mode = !image_mode;
|
|
break;
|
|
case 'l': /* Set label */
|
|
label = *++argv;
|
|
break;
|
|
case 's': /* Sequence */
|
|
sequence = ! sequence;
|
|
break;
|
|
case 'c': /* Correction card */
|
|
memset(image, 0, sizeof(image));
|
|
set_addr(*++argv, image);
|
|
while(add_data(*++argv, image));
|
|
argv--; /* Back up one argumement */
|
|
checksum(image); /* Compute checksum */
|
|
dump_card(of, image);
|
|
break;
|
|
case 'f': /* Start card */
|
|
++argv;
|
|
if (*argv[0] == 't')
|
|
fcard = -1;
|
|
else
|
|
fcard = atoi(*argv);
|
|
break;
|
|
case 'e': /* Final card */
|
|
++argv;
|
|
if (*argv[0] == 't')
|
|
lcard = -1;
|
|
else
|
|
lcard = atoi(*argv);
|
|
break;
|
|
}
|
|
} else {
|
|
if ((f = fopen(n, "rb")) == NULL) {
|
|
fprintf(stderr, "Unable to open: %s\n", n);
|
|
exit(1);
|
|
}
|
|
|
|
memset(image, 0, sizeof(image));
|
|
col = 0;
|
|
t = 6;
|
|
while(!feof(f)) {
|
|
ch = fgetc(f);
|
|
if (ch & 0x80) {
|
|
if (col != 0) {
|
|
if (good_card(image)) {
|
|
dump_card(of, image);
|
|
card++;
|
|
}
|
|
}
|
|
memset(image, 0, sizeof(image));
|
|
col = 0;
|
|
t = 6;
|
|
}
|
|
image[col] |= (ch & 077) << t;
|
|
if (t) {
|
|
t = 0;
|
|
} else {
|
|
col++;
|
|
t = 6;
|
|
}
|
|
}
|
|
fclose(f);
|
|
if (col != 0) {
|
|
if (good_card(image)) {
|
|
dump_card(of, image);
|
|
card++;
|
|
}
|
|
}
|
|
ccard = 0;
|
|
fcard = 0;
|
|
lcard = -1;
|
|
}
|
|
}
|
|
fprintf(stderr, "%d cards in deck\n", cardno);
|
|
return (0);
|
|
|
|
}
|
|
|