272 lines
4.5 KiB
C
272 lines
4.5 KiB
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);
|
|
}
|