Minix1.5/commands/ibm/libpack.c
/* libpack - pack ASCII assembly code */
/* Packs common strings found in PC Minix assembly code into single */
/* byte abbreviations. The abbreviations all have their high bit set. */
/* Do not alter the order of the entries in "table"; asld depends on it.*/
/* External interfaces */
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
/* Constants */
#define MAXLINE 256 /* maximum input line length */
#define ABBREVS 128 /* number of abbreviations */
#define COMMENT '|' /* comment character */
/* Structures and types */
struct node {
char *string; /* pointer to original string */
size_t length; /* length of original string */
struct node *next; /* next node with same hash value */
};
typedef unsigned short TWOBYTES; /* CHEAT - used to return two bytes */
/* Local interfaces */
static void error_exit(/* int rc, char *msg */);
static void hash_init(/* void */); /* initializes hash table */
static void pack_line(/* char *line */); /* packs an input line */
static TWOBYTES abbreviate_string(/* char *s */); /* abbreviates a string */
/* Macros */
#define HASH(word) ((*(word) + *((word) + 1)) & 0x7f)
#define HIBYTE(n) ((n) >> 8)
#define LOBYTE(n) ((n) & 0xff)
#define MAKETWOBYTES(hi, lo) ((((hi) & 0xff) << 8) | ((lo) & 0xff))
/* Static storage */
static char *table[] = {
"push ax",
"ret",
"mov bp,sp",
"push bp",
"pop bp",
"mov sp,bp",
".text",
"xor ax,ax",
"push 4(bp)",
"pop bx",
"pop si",
"cbw",
"movb al,(bx)",
"pop ax",
"xorb ah,ah",
"mov ax,#1",
"call _callm1",
"add sp,#16",
"mov bx,4(bp)",
"push 6(bp)",
"mov -2(bp),ax",
"I0013:",
"call .cuu",
"mov ax,-2(bp)",
"add 4(bp),#1",
"or ax,ax",
"jmp I0011",
"mov bx,8(bp)",
"push dx",
"mov cx,#2",
"mov bx,#2",
"I0011:",
"I0012:",
"push -2(bp)",
"mov ax,4(bp)",
"mov ax,-4(bp)",
"add sp,#6",
"and ax,#255",
"push bx",
"mov bx,-2(bp)",
"loop 2b",
"jcxz 1f",
".word 4112",
"mov ax,(bx)",
"mov -4(bp),ax",
"jmp I0013",
".data",
"mov bx,6(bp)",
"mov (bx),ax",
"je I0012",
".word 8224",
".bss",
"mov ax,#2",
"call _len",
"call _callx",
".word 28494",
".word 0",
"push -4(bp)",
"movb (bx),al",
"mov bx,ax",
"mov -2(bp),#0",
"I0016:",
".word 514",
".word 257",
"mov ",
"push ",
".word ",
"pop ",
"add ",
"4(bp)",
"-2(bp)",
"(bx)",
".define ",
".globl ",
"movb ",
"xor ",
"jmp ",
"cmp ",
"6(bp)",
"-4(bp)",
"-6(bp)",
"#16",
"_callm1",
"call ",
"8(bp)",
"xorb ",
"and ",
"sub ",
"-8(bp)",
"jne ",
".cuu",
"lea ",
"inc ",
"_M+10",
"#255",
"loop",
"jcxz",
"ax,#",
"bx,#",
"cx,#",
"ax,",
"bx,",
"cx,",
"dx,",
"si,",
"di,",
"bp,",
"ax",
"bx",
"cx",
"dx",
"si",
"di",
"bp",
"sp",
"dec ",
"neg ",
"_execve",
",#0",
NULL
};
/* This table is used to look up strings. */
struct node node[ABBREVS];
struct node *hash[ABBREVS]; /* hash table */
/* Code */
int main(argc, argv)
int argc;
char *argv[];
{
char line[MAXLINE];
switch (argc) {
case 1:
break;
case 2:
if (freopen(argv[1], "r", stdin) == NULL)
error_exit(ENOENT, "libpack: could not open file\n");
break;
default:
error_exit(EINVAL, "Usage: libpack [file]\n");
}
hash_init();
while (fgets(line, MAXLINE, stdin) != NULL) {
pack_line(line);
fputs(line, stdout);
}
exit(0);
}
static void error_exit(rc, msg)
int rc;
char *msg;
{
fputs(msg, stderr);
exit(rc);
}
static void hash_init()
{
int i;
register char **p;
register struct node *np;
for (i = 0, p = table; i < ABBREVS && *p != NULL; i++, p++) {
if (hash[HASH(*p)] == NULL) {
hash[HASH(*p)] = &node[i];
} else {
for (np = hash[HASH(*p)]; np->next != NULL; np = np->next)
;
np->next = &node[i];
}
np = &node[i];
np->string = *p;
np->length = strlen(*p);
np->next = NULL;
}
}
static void pack_line(line)
char *line;
{
register char *ip;
register char *op;
int in_white;
TWOBYTES n;
for (ip = line; *ip != '\0'; ++ip) /* translate tabs */
if (*ip == '\t') *ip = ' ';
op = line;
in_white = 1;
for (ip = line; *ip != '\0'; ++ip) { /* pack strings in line */
if (*ip == COMMENT)
break;
if (isspace(*ip)) {
if (!in_white) {
*op++ = ' ';
in_white = 1;
}
continue;
}
in_white = 0;
n = abbreviate_string(ip);
*op++ = LOBYTE(n);
ip += HIBYTE(n);
}
if (op != line) { /* finish nicely */
if (op[-1] == ' ')
--op;
*op++ = '\n';
}
*op = '\0';
}
static TWOBYTES abbreviate_string(ip)
register char *ip;
{
register struct node *np;
for (np = hash[HASH(ip)]; np != NULL; np = np->next)
if (strncmp(ip, np->string, np->length) == 0)
return MAKETWOBYTES(np->length - 1, 128 + (np - node));
return MAKETWOBYTES(0, *ip);
}