/* fv is a binary file editor written by Chris Hooper (cdh@mtu.edu)
 *	on 6-2-91 is has gone through many revisions since then.
 *	CHRISTOPHER D. HOOPER
 */
#include "main.h"

#define VERSION "@(#)fv  1.51  93/06/14  cdh"

WINDOW	*main_window;
WINDOW	*status_window;
char	out_string[1024];
FILE	*view_file;
char	*buffer;
int	*ibuffer;
int	found;
int	buf_size;
int	max_buf_size	= 0;
int	addis	 	= 0;
int	chdis	 	= 1;
int	wdis	 	= 1;
int	ronly		= 0;
int	mode		= STRING;
int	wdismode	= 0;
int 	dirty		= 0;
int	looping	 	= 1;
int	wpline	 	= 0;
int	caddr	 	= 0;
int	global_type	= 0;
int	global_direction = 0;
int	global_num	= 0;
int	marks		= 0;
int	searching	= 0;
int 	daddr		= -1;
char	global_search[MAXLEN];
int	global_special[MAXLEN];
int	local_search[MAX_HEX];
char	markchar[MARKS];
int	markpos[MARKS];
extern	int size;
char	*version = VERSION;
char 	*filename;
unsigned long last_viewed;
long	cursor_address;
int	alignment = 4;
unsigned long fend;

unsigned long file_end();

extern unsigned long file_sz[];

int main(argc, argv)
int argc;
char *argv[];
{
	char	ch;
	int	index, temp;
	int	write_mode = 0;
	int	anum=1;

	while (*version != ' ')
		version++;

	if (argc < 2) {
		fprintf(stderr, "No file specified.  ");
		print_usage(argv[0]);
	}

	while ((anum < argc) && (*argv[anum] == '-')) {
		argv[anum]++;
		while (*argv[anum] != '\0') {
		    if (*argv[anum] == 'r')
			ronly = 1;
		    else if (*argv[anum] == 'w') {
			if (!ronly)
				write_mode = 1;
		    } else if (*argv[anum] == 'v')
			fprintf(stdout, "%s%s\n", argv[0], version);
		    else if (*argv[anum] == 'V')
			for (index = 0; index < 6; index++)
			    fprintf(stdout, "%c%c%c%c",
				    (file_sz[index] >> 24 & 255) + 64,
				    (file_sz[index] >> 16 & 255) + 64,
				    (file_sz[index] >> 8 & 255) + 64,
				    (file_sz[index] & 255) + 64);
		    argv[anum]++;
		}
		anum++;
	}

	if (anum == argc)
		exit(0);

	for (index = 0; index < 6; index++)
			temp ^= file_sz[index];

		if (write_mode) {
		    view_file = fopen(argv[anum], "r+");
		    if (view_file == NULL)
			view_file = fopen(argv[anum], "w");
		    if (view_file == NULL) {
			fprintf(stderr, "Error: unable to open \"%s\" for writing.\n",
				argv[anum]);
			ronly = 1;
		    } else
			fclose(view_file);
		}

		if ((!ronly) && ((view_file = fopen(argv[anum], "r+")) == NULL))
			ronly = 1;

		if (ronly)
			fprintf(stdout, "viewing");
		else
			fprintf(stdout, "editing");
		fprintf(stdout, " file %s\n", argv[anum]);

		if (ronly)
			if ((view_file = fopen(argv[anum], "r")) == NULL) {
				fprintf(stderr, "Error: \"%s\" could not be opened.\n",
					argv[anum]);
				print_usage(argv[0]);
				exit(1);
			}

		signal(SIGINT, sigint);
		signal(SIGQUIT, sigint);
		signal(SIGWINCH, sigwinch);

		init();

	fend = file_end() & ((unsigned long) temp ^ 0xfef1c0cb);

	if (fend < HIGH_BUF_SIZE)
		max_buf_size = fend;

	if (max_buf_size == 0)
		max_buf_size = HIGH_BUF_SIZE;

	ibuffer = (int *) malloc(max_buf_size + MAXLEN);
	buffer	= (char *) ibuffer;

/*
	wpline	= (COLS - addis * 10) / (9 * wdis + chdis * 4);
	buf_size = (LINES - 1) * wpline * 4;

	main_window = newwin(LINES - 1, COLS, 1, 0);
	status_window = newwin(1, COLS, 0, 0);

	leaveok(main_window, TRUE);
	leaveok(status_window, TRUE);

	edit_mode();
*/
	filename = argv[anum];

	wmove(status_window, 0, 20);
	(void) sprintf(out_string, "of %s\n", filename);
	waddstr(status_window, out_string);
	last_viewed = caddr;

	if (!ronly) {
		if (show_addr(caddr, 0)) {
			caddr = last_viewed;
			(void) show_addr(caddr, 1);
		}
		looping = edit_file();
	}

	while (looping) {
		if (show_addr(caddr, 0)) {
			caddr = last_viewed;
			(void) show_addr(caddr, 1);
		}
		reread:
		ch = wgetch(main_window);
		switch (ch) {
		    case 'a':
		    case 'A':
			addis = !addis;

			temp = wpline;
			wpline = (COLS - addis * 10) / (9 * wdis + chdis * 4);
			buf_size = (LINES - 1) * wpline * 4;

			wmove(main_window, 0, 0);
			wclrtobot(main_window);
			break;
		    case '':
		    case 'b':
			last_viewed = caddr;
			caddr -= (buf_size / 4) * 4;
			if (caddr < 0)
				caddr = 0;
			break;
		    case 'B':
			temp = buf_size;
			index = 0;
			while (temp) {
				temp = temp>>1;
				index++;
			}
			buf_size = 2<<(index-2);
			wmove(main_window, buf_size / (wpline * 4), buf_size % (wpline * 4));
			wclrtobot(main_window);
			break;
		    case 'c':
			chdis = !chdis;
			temp = wpline;
			if (chdis == 0)
				wdis = 1;
			wpline = (COLS - addis * 10) / (9 * wdis + chdis * 4);
			buf_size = (LINES - 1) * wpline * 4;

			wmove(main_window, 0, 0);
			wclrtobot(main_window);
			break;
		    case '':
		    case 'd':
			last_viewed = caddr;
			caddr += (buf_size / 4) * 2;
			break;
		    case 'e':
			looping = edit_file();
			edit_mode();
			break;
		    case '':
		    case 'f':
			last_viewed = caddr;
			caddr += (buf_size / 4) * 4;
			break;
		    case 'G':
			temp = ((file_end() - buf_size) / 4) * 4;
			if (caddr != temp) {
				last_viewed = caddr;
				caddr = temp;
			} else
				goto reread;
			break;
		    case 'J':
		    case 'g':
			temp = (get_jump(caddr) / 4) * 4;
			edit_mode();
			if (caddr != temp) {
				last_viewed = caddr;
				caddr = temp;
			} else
				goto reread;
			break;
		    case 'h':
			last_viewed = caddr;
			caddr -= 4;
			if (caddr < 0)
				caddr = 0;
			break;
		    case 'H':
		    case '':
			help_me2();
			touchwin(main_window);
			touchwin(status_window);
			refresh();
			break;
		    case 'j':
			last_viewed = caddr;
			caddr += wpline * 4;
			break;
		    case 'k':
			last_viewed = caddr;
			caddr -= wpline * 4;
			if (caddr < 0)
				caddr = 0;
			break;
		    case '':
			clear();
			touchwin(main_window);
			touchwin(status_window);
			refresh();
			break;
		    case 'l':
			last_viewed = caddr;
			caddr += 4;
			break;
		    case 'm':
			set_mark(caddr);
			break;
		    case 'N':
			global_direction = !global_direction;
		    case 'n':
			last_viewed = caddr;
			caddr = (generic_search(caddr, global_direction) / 4) * 4;
			edit_mode();
			break;
		    case 'r':
			break;
		    case 't':
			wdismode = (wdismode + 1) % WDISMAX;
			break;
		    case '':
		    case 'u':
			last_viewed = caddr;
			caddr -= (buf_size / 4) * 2;
			if (caddr < 0)
				caddr = 0;
			if (last_viewed == 0)
				goto reread;
			break;
		    case 'w':
			wdis = !wdis;
			if (wdis == 0)
				chdis = 1;
			wpline = (COLS - addis * 10) / (9 * wdis + chdis * 4);
			buf_size = (LINES - 1) * wpline * 4;

			wmove(main_window, 0, 0);
			wclrtobot(main_window);
			break;
		    case 3:  /* ^C */
		    case 'q':
		    case 'Q':
		    case '':
		    case 'x':
			if (dirty)
				save_changes();
			looping = 0;
			break;
		    case ' ':
			temp = caddr;
			caddr = last_viewed;
			last_viewed = temp;
			break;
		    case '0':
			if (caddr != 0) {
				last_viewed = caddr;
				caddr = 0;
			} else
				goto reread;
			break;
		    case '\'':
			temp = get_mark(caddr);
			if (caddr != temp) {
				last_viewed = caddr;
				caddr = temp;
			} else
				goto reread;
			break;
		    case '+':
		    case '=':
			wpline++;
			if (wpline > (COLS - addis * 10) / (9 * wdis + chdis * 4))
				wpline = (COLS - addis * 10) / (9 * wdis + chdis * 4);
			buf_size = (LINES - 1) * wpline * 4;
			break;
		    case '-':
		    case '_':
			wpline--;
			if (wpline < 1)
				wpline = 1;
			buf_size = (LINES - 1) * wpline * 4;

			wmove(main_window, 0, 0);
			wclrtobot(main_window);
			break;
		    case '/':
		    case '?':
			last_viewed = caddr;
			if (mode == STRING)
				caddr = (find_str(caddr, ch == '?') / 4) * 4;
			else
				caddr = (find_hex(caddr, ch == '?') / 4) * 4;
			edit_mode();
			break;
		    case '\t':
			mode = !mode;
			edit_mode();
			break;
		    default:
			goto reread;
		}
	}

	de_init();
	exit(0);
}

unsigned long file_sz[] = {
0x03081209,0x13140f10,0x080512e0,0x04d2e008,0x0f0f1005,0x12cac0c0};

/************************************************************************/
/*									*/
/*			   Editor state machine				*/
/*									*/
/************************************************************************/

/* Additions to normal
	()	Screen move (Top/Bottom)
	<int>	repeat next cmd <int> times
	<cr>	edit location
	w	write buffer to disk

   Subtractions from normal
	w	word display
	c	character display
	+-	add/sub columns
	H	help
*/
int edit_file()
{
    char ch = ' ';
    int looptime = 1;
    int rollover=1;
    int wref=0, rfile=0, cref = 0;
    int temp;
    int temp2;
    int temp3;
    int addr;
    int running = 1;

    update_cursor(ON);
    wrefresh(main_window);
    edit_mode();

/* cursor_address */

    while (ch != 'e') {
	ch = wgetch(main_window);
	if (((ch >= '1') && (ch <= '9')) ||
	    ((ch == '0') && (rollover == 0))) {
	    if (rollover)
		looptime = ch - '0';
	    else
		looptime = looptime * 10 + ch - '0';
	    rollover = 0;
	} else {
	    if (rollover)
		looptime = 1;
	    else
		rollover = 1;

	    while (looptime) {
		looptime--;
		switch (ch) {
		    case 'a':
			wref	= 1;
			addis = !addis;

			wpline = (COLS - addis * 10) /
				 (9 * wdis + chdis * 4);
			buf_size = (LINES - 1) * wpline * 4;

			if ((cursor_address - caddr) >= buf_size) {
				cursor_address  = caddr + buf_size - 1;
				cursor_address -= cursor_address % alignment;
			}

			wmove(main_window, 0, 0);
			wclrtobot(main_window);
			break;
		    case 'A':
			write_mark(cursor_address, 1);
			wref = 1;
			break;
		    case '':
		    case 'b':
			last_viewed  = caddr;
			caddr	    -= buf_size;
			caddr	    -= caddr % alignment;
			if (caddr < 0)
				caddr = 0;
			if (cursor_address >= caddr + size) {
				cursor_address  = caddr + size - 1;
				cursor_address -= cursor_address % alignment;
			}
			rfile	= 1;
			break;
		    case 'c':
			rfile	= 1;
			chdis	= !chdis;
			temp	= wpline;
			if (chdis == 0)
				wdis = 1;

			wpline = (COLS - addis * 10) /
				 (9 * wdis + chdis * 4);
			buf_size = (LINES - 1) * wpline * 4;

			if (cursor_address >= caddr + size) {
				cursor_address  = caddr + buf_size - 1;
				cursor_address -= cursor_address % alignment;
			}
			wmove(main_window, 0, 0);
			wclrtobot(main_window);
			break;
		    case 'C':
			write_mark(cursor_address, 0);
			wref = 1;
			break;
		    case '':
		    case 'd':
			if (caddr < fend - buf_size / 2) {
				last_viewed  = caddr;
				caddr	    += buf_size / 2;
				caddr	    -= caddr % alignment;
				rfile	     = 1;
				if (cursor_address < caddr)
					cursor_address = caddr;
			}
			break;
		    case '':
		    case 'f':
			if (caddr < fend - buf_size) {
				last_viewed  = caddr;
				caddr	    += buf_size;
				caddr	    -= caddr % alignment;
				rfile	     = 1;
				if (cursor_address < caddr)
					cursor_address = caddr;
			}
			break;
		    case 'g':
			temp  = get_jump(caddr);
			temp -= temp % alignment;
			if ((temp >= caddr) && (temp <= caddr + size)) {
				update_cursor(OFF);
				cursor_address  = temp;
				cursor_address -= cursor_address % alignment;
				cref            = 1;
			} else if ((caddr != temp) &&
				   (temp >= 0) && (temp <= fend)) {
				last_viewed    = caddr;
				caddr          = temp;
				caddr	      -= caddr % alignment;
				cursor_address = caddr;
				rfile          = 1;
			}
			break;
		    case 'G':
			update_cursor(OFF);
			temp  = fend - buf_size;
			temp -= temp % alignment;
			if ((caddr != temp) && (temp > 0)) {
				last_viewed    = caddr;
				caddr          = temp;
				caddr	      -= caddr % alignment;
				rfile          = 1;
			} else
				cref = 1;
			cursor_address  = caddr + size - 1;
			cursor_address -= cursor_address % alignment;
			break;
		    case 'h':
			update_cursor(OFF);
			cref = 1;
			if (cursor_address >= alignment - 1) {
			    cursor_address -= alignment;
			    if (cursor_address < caddr) {
				last_viewed = caddr;
				caddr	   -= buf_size / 2;
				caddr      -= caddr % alignment;
				rfile       = 1;
				if (caddr < 0)
					caddr = 0;
			    }
			}
			break;
		    case 'H':
			last_viewed = caddr;
			caddr      += alignment;
			if (caddr > fend - alignment) {
				caddr  = fend - alignment;
				caddr -= caddr % alignment;
			}
			rfile = 1;
			if (cursor_address < caddr)
				cursor_address = caddr;
			break;
		    case '':
			help_me();
			touchwin(main_window);
			wrefresh(main_window);
			break;
		    case 'j':
			update_cursor(OFF);
			cref = 1;
			if (cursor_address < (fend - wpline * alignment)) {
			    cursor_address += wpline * alignment;
			    if (cursor_address >= caddr + buf_size) {
				last_viewed = caddr;
				caddr      += buf_size / 2;
				caddr      -= caddr % alignment;
				rfile       = 1;
				if (caddr > fend) {
					caddr = fend;
					caddr -= caddr % alignment;
				}
			    }
			}
			break;
		    case 'J':
			update_cursor(OFF);
			if (caddr > 0) {
			    last_viewed = caddr;
			    caddr -= alignment * wpline;
			    if (caddr < 0)
				caddr = 0;
			    if (cursor_address >= caddr + size) {
				cursor_address  = caddr + size - 1;
				cursor_address -= cursor_address % alignment;
			    }
			}
			rfile  = 1;
			break;
		    case 'k':
			update_cursor(OFF);
			cref = 1;
			if (cursor_address >= wpline * alignment) {
			    cursor_address -= wpline * alignment;
			    if (cursor_address < caddr) {
				last_viewed = caddr;
				caddr      -= buf_size / 2;
				caddr      -= caddr % alignment;
				rfile       = 1;
				if (caddr < 0)
					caddr = 0;
			    }
			}
			break;
		    case 'K':
			update_cursor(OFF);
			if (caddr < fend - alignment * wpline) {
				last_viewed = caddr;
				caddr      += alignment * wpline;
				if (cursor_address < caddr)
					cursor_address = caddr;
			}
			rfile  = 1;
			break;
		    case 'l':
			update_cursor(OFF);
			cref = 1;
			if (cursor_address < (fend - alignment)) {
			    cursor_address += alignment;
			    if (cursor_address >= (caddr + buf_size)) {
				last_viewed = caddr;
				caddr      += buf_size / 2;
				caddr      -= caddr % alignment;
				rfile       = 1;
				if (caddr > fend)
					caddr = fend;
			    }
			}
			break;
		    case 'L':
			last_viewed = caddr;
			caddr      -= alignment;
			if (caddr < 0)
				caddr = 0;
			rfile = 1;
			if (cursor_address >= caddr + size) {
				cursor_address  = caddr + size - 1;
				cursor_address -= cursor_address % alignment;
			}
			break;
		    case '':
			wref = 1;
			clear();
			touchwin(main_window);
			touchwin(status_window);
			refresh();
			break;
		    case 'm':
			set_mark(cursor_address);
			break;
		    case '':
			addr  = (cursor_address - caddr) / 4;
			temp  = ibuffer[addr];
			temp2 = ibuffer[addr + 1];
			if (mode == STRING)
				edit_mem_string(addr);
			else
				edit_hex(addr);
			edit_mode();
			if ((temp  != ibuffer[addr]) ||
			    (temp2 != ibuffer[addr + 1]))
				dirty = 1;
			if (mode == STRING)
				rfile = 1;
			else
				wref = 1;
			break;
		    case 'N':
			global_direction = !global_direction;
		    case 'n':
			wref = 1;
			update_cursor(OFF);
			cursor_address = generic_search(cursor_address,
							global_direction);
			cursor_address -= cursor_address % alignment;

			if ((cursor_address < caddr) ||
			    (cursor_address >= caddr + size)) {
				last_viewed = caddr;
				caddr = cursor_address;
				edit_mode();
			} else
				daddr = !daddr;
			break;
		    case 3:
		    case 'q':
		    case 'Q':
		    case '':
		    case 'x':
			if (dirty)
				save_changes();
			ch = 'e';
			running = 0;
			break;
		    case 'r':
			daddr = !daddr;
			rfile = 1;
			break;
		    case 't':
			wdismode = (wdismode + 1) % WDISMAX;
			wref = 1;
			edit_mode();
			break;
		    case '\t':
			mode = !mode;
			edit_mode();
			break;
		    case 'u':
		    case '':
			if (caddr > 0) {
				last_viewed  = caddr;
				caddr	    -= buf_size / 2;
				caddr       -= caddr % alignment;
				rfile	     = 1;
				if (caddr < 0)
					caddr = 0;
				if (cursor_address >= caddr + size) {
				    cursor_address  = caddr + size - 1;
				    cursor_address -= cursor_address %alignment;
				}
			}
			break;
		    case 'w':
			rfile = 1;
			wdis = !wdis;
			if (wdis == 0)
				chdis = 1;
			wpline = (COLS - addis * 10) / (9 * wdis + chdis * 4);
			buf_size = (LINES - 1) * wpline * 4;

			if (cursor_address >= caddr + size) {
				cursor_address  = caddr + size - 1;
				cursor_address -= cursor_address % alignment;
			}

			wmove(main_window, 0, 0);
			wclrtobot(main_window);
			break;
		    case 'W':
		    case '':
			save_changes();
			rfile = 1;
			break;
		    case '0':
			update_cursor(OFF);
			if (caddr > 0) {
				last_viewed = caddr;
				caddr	    = 0;
				rfile	    = 1;
				if (cursor_address >= caddr + size) {
				    cursor_address  = caddr + size - 1;
				    cursor_address -= cursor_address %alignment;
				}
			} else {
				cursor_address = 0;
				cref	= 1;
			}
			break;
		    case '/':
		    case '?':
			wref = 1;
			update_cursor(OFF);
			if (mode == STRING)
			    cursor_address = find_str(cursor_address, ch == '?');
			else
			    cursor_address = find_hex(cursor_address, ch == '?');

			cursor_address -= cursor_address % alignment;

			if ((cursor_address < caddr) ||
			    (cursor_address >= caddr + size)) {
				last_viewed = caddr;
				caddr = cursor_address;
				edit_mode();
			} else
				daddr = !daddr;
			break;
		    case '+':
		    case '=':
			wref = 1;
			wpline++;
			if (wpline > (COLS - addis * 10)/(9 * wdis + chdis * 4))
			    wpline--;
			buf_size = (LINES - 1) * wpline * 4;

			break;
		    case '-':
		    case '_':
			wref = 1;
			wpline--;
			if (wpline < 1)
				wpline = 1;
			buf_size = (LINES - 1) * wpline * 4;

			if (cursor_address >= caddr + buf_size) {
			    cursor_address  = caddr + buf_size - 1;
			    cursor_address -= cursor_address % alignment;
			}

			wmove(main_window, 0, 0);
			wclrtobot(main_window);
			break;
		    case '\'':
			if ((temp = get_mark(-1)) != -1)
			    if ((temp > caddr + size - 1) || (temp < caddr)) {
				last_viewed    = caddr;
				caddr	       = temp;
				caddr         -= caddr % alignment;
				cursor_address = caddr;
				rfile          = 1;
			    } else {
				update_cursor(OFF);
				cursor_address = temp - temp % alignment;
				wref           = 1;
			    }
			break;
		    case ')':
			update_cursor(OFF);
			cursor_address  = caddr + size - 1;
			cursor_address -= cursor_address % alignment;
			cref = 1;
			break;
		    case '(':
			update_cursor(OFF);
			cursor_address = caddr;
			cref = 1;
			break;
		    case '<':
			alignment <<= 1;
			if (alignment > 8)
				alignment = 1;
			edit_mode();
			break;
		    case '>':
			alignment >>= 1;
			if (alignment < 1)
				alignment = 8;
			edit_mode();
			break;
		}
	    }
	    if (rfile) {
		if (show_addr(caddr, 0)) {
			caddr = last_viewed;
			(void) show_addr(caddr, 1);
		}
		update_cursor(ON);
		wrefresh(main_window);
		rfile = 0;
		wref = 0;
		cref = 0;
	    } else if (wref) {
		if (show_addr(caddr, 0)) {
			caddr = last_viewed;
			(void) show_addr(caddr, 1);
		}
		update_cursor(ON);
		wrefresh(main_window);
		wref = 0;
		cref = 0;
	    } else if (cref) {
		update_cursor(ON);
		wrefresh(main_window);
		cref = 0;
	    }
	}
    }

    if (dirty)
	save_changes();

    update_cursor(OFF);
    wrefresh(main_window);
    wstandend(main_window);

    wmove(status_window, 0, COLS - 10);
    wclrtoeol(status_window);
    return(running);
}

update_cursor(mode)
int mode;
{
	int index;
	int row, column;

	row    = ((cursor_address - caddr) / 4) / wpline;
	column = ((cursor_address - caddr) / 4) % wpline;

	if (mode)
	    wstandout(main_window);
	else
	    wstandend(main_window);

	if (chdis) {
	    wmove(main_window, row, addis * 10 + wpline * 9 * wdis + column*4);
	    waddch_filt(buffer[cursor_address - caddr    ]);
	    waddch_filt(buffer[cursor_address - caddr + 1]);
	    waddch_filt(buffer[cursor_address - caddr + 2]);
	    waddch_filt(buffer[cursor_address - caddr + 3]);
	}

	if (wdis) {
	    wrefresh(main_window);
	    index = (cursor_address - caddr) / 4;
	    switch (wdismode) {
		case 0:			/* hex */
		    (void) sprintf(out_string, "%08x", ibuffer[index]);
		    break;
		case 1:			/* integer */
		    (void) sprintf(out_string, "%8d", ibuffer[index]);
		    out_string[8] = '\0';
		    break;
		case 2:			/* float */
		    (void) sprintf(out_string, "%-9f",
				   *((float *) &ibuffer[index]));
		    out_string[8] = '\0';
		    break;
		case 3:			/* float */
		    (void) sprintf(out_string, "%-18lf",
				   *((double *) &ibuffer[index]));
		    out_string[17] = '\0';
		    break;
	    }

	    wmove(main_window, row, addis * 10 + column * 9);
	    waddstr(main_window, out_string);
	}

	if (mode)
	    wstandend(main_window);
}


print_usage(program)
char *program;
{
	fprintf(stderr, "Usage is:\n%s ", program);
	fprintf(stderr, "[-r] [-w] [-v] filename\n");
	fprintf(stderr, "%*s -r = view mode\n", 	   strlen(program), "");
	fprintf(stderr, "%*s -w = force write mode\n", strlen(program), "");
	fprintf(stderr, "%*s -v = print version\n",    strlen(program), "");
	exit(1);
}
