Minix1.5/commands/ibm/libpack.c

Compare this file to the similar file:
Show the results in this format:

/* 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);
}