Subject: Re: New snapshot available
To: Michael Wolfson <michael@nosflow.com>
From: Eduardo Horvath <eeh@NetBSD.org>
List: port-sparc64
Date: 11/11/2004 07:51:53
On Wed, Nov 10, 2004 at 10:12:35PM -0800, Michael Wolfson wrote:
> 
> On Nov 8, 2004, at 9:21 AM, Eduardo Horvath wrote:
> 
> >Hm.  In both cases you typed "boot disk -s"?  Strange.
> 
> Yes, and yes.
> 
> >What do you have for boot-device, boot-file and boot-args?
> 
> ok printenv boot-device
> boot-device =         disk:a disk net
> ok printenv boot-file
> boot-file =
> ok printenv boot-args
> Unknown option: boot-args
> 
> >Can you try setting fcode-debug? to true and boot with '-sVD'
> >arguments so it will stop after loading but before executing the
> >bootblock.
> 
> Rebooting with command: boot -sVD
> Trap 3e
> ok do-boot " /ofwboot"
> do-boot ?

Hm.  It appears that the trap happens before the FCode is done being
interpreted.  I wonder if it could be a tokenizer issue.  You can try
the attached version of fgen and see if the bootblock it generates 
works any better than the in-tree version.

> ok boot -sVD
> Boot device: /pci@1f,4000/scsi@3/disk@0,0:a  File and args: -sVD
> The file just loaded does not appear to be executable.
> ok do-boot " /ofwboot"
> NetBSD IEEE 1275 Bootblock
> Loading file Fast Data Access MMU Miss

Sorry, I forgot this is Forth.  Try:

 " /ofwboot" do-boot

instead.  It should work a bit better.

Eduardo


# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	fgen.h
#	fgen.l
#
echo x - fgen.h
sed 's/^X//' >fgen.h << 'END-of-fgen.h'
X/*	$NetBSD: fgen.h,v 1.4 2001/06/13 10:46:05 wiz Exp $	*/
X/*
X * fgen.h -- stuff for the fcode tokenizer.
X *
X * Copyright (c) 1998 Eduardo Horvath.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *      This product includes software developed by Eduardo Horvath.
X * 4. The name of the author may not be used to endorse or promote products
X *    derived from this software without specific prior written permission
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
X * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
X * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
X * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
X * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
X * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
X * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
X */
X
X/* Type of a Cell */
Xtypedef int64_t Cell;
X
X/* Token from the scanner. */
Xstruct tok {
X	int type;
X	char *text;
X};
X
X#define TOKEN struct tok
X#define YY_DECL TOKEN* yylex __P((void))
X
X#define FCODE	0xF00DBABE
X#define MACRO	0xFEEDBABE
X
X/* Defined fcode and string. */
Xstruct fcode {
X	char *name;
X	long num;
X	int type;
X	struct fcode *l;
X	struct fcode *r;
X};
X
X/* macro instruction as separate words */
Xstruct macro {
X	char *name;
X	char *equiv;
X	int type;
X	struct macro *l;
X	struct macro *r;
X};
X
X/*
X * FCode header -- assumes big-endian machine, 
X *	otherwise the bits need twiddling.
X */
Xstruct fcode_header {
X	char	header;
X	char	format;
X	short	checksum;
X	int	length;
X};
X
X/* Tokenizer tokens */
Xenum toktypes { 
X	TOK_OCTAL = 8,
X	TOK_DECIMAL = 10,
X	TOK_HEX = 16,
X
X	TOK_NUMBER, 
X	TOK_STRING_LIT, 
X	TOK_C_LIT,
X	TOK_PSTRING, 
X	TOK_TOKENIZE,
X	TOK_COMMENT, 
X	TOK_COLON, 
X	TOK_SEMICOLON, 
X	TOK_TOSTRING,
X	
X	/* These are special */
X	TOK_ABORT_S,
X	TOK_AGAIN,
X	TOK_ALIAS,
X	TOK_GETTOKEN,
X	TOK_ASCII,
X	TOK_BEGIN,
X	TOK_BUFFER,
X	TOK_CASE,
X	TOK_CONSTANT,
X	TOK_CONTROL,
X	TOK_CREATE,
X	TOK_DEFER,
X	TOK_DO,
X	TOK_ELSE,
X	TOK_END0,
X	TOK_ENDCASE,
X	TOK_ENDOF,
X	TOK_EXTERNAL,
X	TOK_FCODE_VERSION2,
X	TOK_FCODE_END,
X	TOK_FIELD,
X	TOK_HEADERLESS,
X	TOK_HEADERS,
X	TOK_IF,
X	TOK_LEAVE,
X	TOK_LOOP,
X	TOK_OF,
X	TOK_OFFSET16,
X	TOK_REPEAT,
X	TOK_STARTX,
X	TOK_THEN,
X	TOK_TO,
X	TOK_UNTIL,
X	TOK_VALUE,
X	TOK_VARIABLE,
X	TOK_VERSION1,
X	TOK_WHILE,
X
X	/* Tokenizer directives */
X	TOK_BEGTOK,
X	TOK_EMIT_BYTE,
X	TOK_ENDTOK,
X	TOK_FLOAD,
X
X	TOK_OTHER
X};
END-of-fgen.h
echo x - fgen.l
sed 's/^X//' >fgen.l << 'END-of-fgen.l'
X%{
X/*	$NetBSD: fgen.l,v 1.21 2003/06/23 13:05:48 agc Exp $	*/
X/* FLEX input for FORTH input file scanner */
X/*  
X * Copyright (c) 1998 Eduardo Horvath.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *      This product includes software developed by Eduardo Horvath.
X * 4. The name of the author may not be used to endorse or promote products
X *    derived from this software without specific prior written permission
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
X * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
X * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
X * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
X * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
X * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
X * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
X */
X/*
X	Specifications are as follows:
X
X	The function "yylex()" always returns a pointer to a structure:
X
X	    struct tok {
X		int type;
X		char *text;
X	    }
X	    #define TOKEN struct tok
X*/
X#include <sys/cdefs.h>
X
X#if defined(__RCSID) && !defined(lint)
X__RCSID("$NetBSD: fgen.l,v 1.21 2003/06/23 13:05:48 agc Exp $");
X#endif
X
X%}
X
X%option yylineno
X
Xdecimal	[0-9.]
Xhex	[0-9A-Fa-f]
Xhexdot	[0-9A-Fa-f.]
Xoctal	[0-7.]
Xwhite	[ \t\n\r\f]
Xtail	{white}
X
X%{
X#include <sys/types.h>
X
X#include <assert.h>
X#include <err.h>
X#include <errno.h>
X#include <fcntl.h>
X#include <stdarg.h>
X#include <stdio.h>
X#include <string.h>
X#include <unistd.h>
X
X#include "fgen.h"
XTOKEN token;
X
X/*
X * Global variables that control the parse state.
X */
X
Xstruct fcode *dictionary = NULL;
Xstruct macro *aliases = NULL;
Xint outf = 1; /* stdout */
Xint state = 0;
Xint nextfcode = 0x800; 
Xint base = TOK_HEX;
Xlong outpos;
Xchar *outbuf = NULL;
Xchar *outfile, *infile;
X#define BUFCLICK	(1024*1024)
Xsize_t outbufsiz = 0;
Xchar *myname = NULL;
Xint offsetsize = 8;
Xint defining = 0;
Xint tokenizer = 0;
Xint need_end0 = 1;
X
X#define PSTKSIZ		1024
XCell parse_stack[PSTKSIZ];
Xint parse_stack_ptr = 0;
X
Xvoid	token_err __P((int, char *, char *, char *, ...))
X	__attribute__((__format__(__printf__, 4, 5)));
XYY_DECL;
X
Xint debug = 0;
X#define ASSERT if (debug) assert
X#define STATE(y, x)	do { if (debug) printf( "%lx State %s: token `%s'\n", outpos, x, y); } while (0)
Xint mark_fload = 0;
X
X#define YY_NO_UNPUT
X%}
X
X%%
X
X0		{ token.type = TOK_OTHER; token.text = yytext; return &token; }
X
X1		{ token.type = TOK_OTHER; token.text = yytext; return &token; }
X
X2		{ token.type = TOK_OTHER; token.text = yytext; return &token; }
X
X3		{ token.type = TOK_OTHER; token.text = yytext; return &token; }
X
X-1		{ token.type = TOK_OTHER; token.text = yytext; return &token; }
X
X\.		{ token.type = TOK_OTHER; token.text = yytext; return &token; }
X
X{white}*		/* whitespace -- keep looping */ ;
X
X\\[^\n]*\n		/* end of line comment -- keep looping */ { STATE(yytext, "EOL comment"); }
X
X-?{hex}{hexdot}*	{ token.type = TOK_NUMBER; token.text = yytext;
X					return &token; }
X
X\'.\'		{ token.type = TOK_C_LIT; token.text = yytext; return &token; }
X
X\"{white}*(\\\"|[^"])*\"	{ token.type = TOK_STRING_LIT; token.text = yytext; 
X				return &token; } /* String started by `"' or `."' */
X
X\.\({white}*(\\\"|[^)])*\)	{ token.type = TOK_PSTRING; token.text = yytext; 
X				return &token; } /* String of type `.(.....)' */
X
X\.\"{white}*(\\\"|[^"])*\"	{ token.type = TOK_PSTRING; token.text = yytext; 
X				return &token; }
X
X[aA][bB][oO][rR][tT]\"{white}*(\\\"|[^"])*\" { token.type = TOK_ABORT_S; 
X				token.text = yytext;  return &token; }
X
X"("		{ token.type = TOK_COMMENT; token.text = yytext;
X				return &token; }
X
X":"		{ token.type = TOK_COLON; token.text = yytext;
X				return &token; }
X
X";"		{ token.type = TOK_SEMICOLON; token.text = yytext;
X				return &token; }
X
X\'		{ token.type = TOK_TOKENIZE; token.text = yytext;
X				return &token; }
X
X[aA][gG][aA][iI][nN]	{ token.type = TOK_AGAIN; token.text = yytext;
X				return &token; }
X
X[aA][lL][iI][aA][sS]	{ token.type = TOK_ALIAS; token.text = yytext;
X				return &token; }
X
X\[\'\]			{ token.type = TOK_GETTOKEN; token.text = yytext;
X				return &token; }
X
X[aA][sS][cC][iI][iI]	{ token.type = TOK_ASCII; token.text = yytext;
X				return &token; }
X
X[bB][eE][gG][iI][nN]	{ token.type = TOK_BEGIN; token.text = yytext;
X				return &token; }
X
X[bB][uU][fF][fF][eE][rR]:	{ token.type = TOK_BUFFER; token.text = yytext;
X				return &token; }
X
X[cC][aA][sS][eE]	{ token.type = TOK_CASE; token.text = yytext;
X				return &token; }
X
X[cC][oO][nN][sS][tT][aA][nN][tT]	{ token.type = TOK_CONSTANT; token.text = yytext;
X				return &token; }
X
X[cC][oO][nN][tT][rR][oO][lL]	{ token.type = TOK_CONTROL; token.text = yytext;
X				return &token; }
X
X[cC][rR][eE][aA][tT][eE]	{ token.type = TOK_CREATE; token.text = yytext;
X				return &token; }
X
X[dD]#		{ token.type = TOK_DECIMAL; token.text = yytext;
X				return &token; }
X
X[dD][eE][cC][iI][mM][aA][lL]	{ token.type = TOK_DECIMAL; token.text = yytext;
X				return &token; }
X
X[dD][eE][fF][eE][rR]	{ token.type = TOK_DEFER; token.text = yytext;
X				return &token; }
X
X\??[dD][oO]	{ token.type = TOK_DO; token.text = yytext;
X				return &token; }
X
X[eE][lL][sS][eE]	{ token.type = TOK_ELSE; token.text = yytext;
X				return &token; }
X
X[eE][nN][dD]0	{ token.type = TOK_END0; token.text = yytext;
X				return &token; }
X
X[eE][nN][dD][cC][aA][sS][eE]	{ token.type = TOK_ENDCASE; token.text = yytext;
X				return &token; }
X
X[eE][nN][dD][oO][fF]	{ token.type = TOK_ENDOF; token.text = yytext;
X				return &token; }
X
X[eE][xX][tT][eE][rR][nN][aA][lL]	{ token.type = TOK_EXTERNAL; token.text = yytext;
X				return &token; }
X
X[fF][cC][oO][dD][eE]-[vV][eE][rR][sS][iI][oO][nN]2	{ 
X			token.type = TOK_FCODE_VERSION2; token.text = yytext;
X				return &token; }
X
X[fF][cC][oO][dD][eE]-[eE][nN][dD]	{ token.type = TOK_FCODE_END; token.text = yytext;
X				return &token; }
X
X[fF][iI][eE][lL][dD]	{ token.type = TOK_FIELD; token.text = yytext;
X				return &token; }
X
X[hH]#		{ token.type = TOK_HEX; token.text = yytext;
X				return &token; }
X
X[hH][eE][aA][dD][eE][rR][lL][eE][sS][sS]	{ token.type = TOK_HEADERLESS; token.text = yytext;
X				return &token; }
X
X[hH][eE][aA][dD][eE][rR][sS]	{ token.type = TOK_HEADERS; token.text = yytext;
X				return &token; }
X
X[hH][eE][xX]	{ token.type = TOK_HEX; token.text = yytext;
X				return &token; }
X
X[iI][fF]		{ token.type = TOK_IF; token.text = yytext;
X				return &token; }
X
X\??[lL][eE][aA][vV][eE]	{ token.type = TOK_LEAVE; token.text = yytext;
X				return &token; }
X
X\+?[lL][oO][oO][pP]	{ token.type = TOK_LOOP; token.text = yytext;
X				return &token; }
X
X[oO]#		{ token.type = TOK_OCTAL; token.text = yytext;
X				return &token; }
X
X[oO][cC][tT][aA][lL]	{ token.type = TOK_OCTAL; token.text = yytext;
X				return &token; }
X
X[oO][fF]		{ token.type = TOK_OF; token.text = yytext;
X				return &token; }
X
X[oO][fF][fF][sS][eE][tT]16	{ token.type = TOK_OFFSET16; token.text = yytext;
X				return &token; }
X
X[rR][eE][pP][eE][aA][tT]	{ token.type = TOK_REPEAT; token.text = yytext;
X				return &token; }
X
X[sS][tT][aA][rR][tT][0124]	{ token.type = TOK_STARTX; token.text = yytext;
X				return &token; }
X 
X[tT][hH][eE][nN]	{ token.type = TOK_THEN; token.text = yytext;
X				return &token; }
X
X[tT][oO]		{ token.type = TOK_TO; token.text = yytext;
X				return &token; }
X
X[uU][nN][tT][iI][lL]	{ token.type = TOK_UNTIL; token.text = yytext;
X				return &token; }
X
X[vV][aA][lL][uU][eE]	{ token.type = TOK_VALUE; token.text = yytext;
X				return &token; }
X
X[vV][aA][rR][iI][aA][bB][lL][eE]	{ token.type = TOK_VARIABLE; token.text = yytext;
X				return &token; }
X
X[vV][eE][rR][sS][iI][oO][nN]1	{ token.type = TOK_VERSION1; token.text = yytext;
X				return &token; }
X
X[wW][hH][iI][lL][eE]	{ token.type = TOK_WHILE; token.text = yytext;
X				return &token; }
X
Xtokenizer\[	{ token.type = TOK_BEGTOK; token.text = yytext;
X				return &token; }
X
Xemit-byte	{ token.type = TOK_EMIT_BYTE; token.text = yytext;
X				return &token; }
X
X\]tokenizer	{ token.type = TOK_ENDTOK; token.text = yytext;
X				return &token; }
X
X[fF][lL][oO][aA][dD]	{ token.type = TOK_FLOAD; token.text = yytext;
X				return &token; }
X
X
X[^ \n\t\r\f]+	{ token.type = TOK_OTHER; token.text = yytext;
X				return &token; }
X
X<<EOF>>			{ return NULL; }
X%%
X
X/* Function definitions */
Xvoid push __P((Cell));
XCell pop __P((void));
Xint depth __P((void));
Xint fadd __P((struct fcode *, struct fcode *));
Xstruct fcode *flookup __P((struct fcode *, char *));
Xint aadd __P((struct macro *, struct macro *));
Xstruct macro *alookup __P((struct macro *, char *));
Xvoid initdic __P((void));
Xvoid usage __P((char *));
Xvoid tokenize __P((YY_BUFFER_STATE));
Xint emit __P((char *));
Xint spit __P((long));
Xint offspit __P((long));
Xvoid sspit __P((char *));
Xint apply_macros __P((YY_BUFFER_STATE, char *));
Xint main __P((int argc, char *argv[]));
XCell cvt __P((char *, char **, int base));
X
X/*
X * Standard FCode names and numbers.  Includes standard
X * tokenizer aliases.
X */
Xstruct fcode fcodes[] = {
X		{ "end0",			0x0000 },
X		{ "b(lit)",			0x0010 },
X		{ "b(')",			0x0011 },
X		{ "b(\")",			0x0012 },
X		{ "bbranch",			0x0013 },
X		{ "b?branch",			0x0014 },
X		{ "b(loop)",			0x0015 },
X		{ "b(+loop)",			0x0016 },
X		{ "b(do)",			0x0017 },
X		{ "b(?do)",			0x0018 },
X		{ "i",				0x0019 },
X		{ "j",				0x001a },
X		{ "b(leave)",			0x001b },
X		{ "b(of)",			0x001c },
X		{ "execute",			0x001d },
X		{ "+",				0x001e },
X		{ "-",				0x001f },
X		{ "*",				0x0020 },
X		{ "/",				0x0021 },
X		{ "mod",			0x0022 },
X		{ "and",			0x0023 },
X		{ "or",				0x0024 },
X		{ "xor",			0x0025 },
X		{ "invert",			0x0026 },
X		{ "lshift",			0x0027 },
X		{ "rshift",			0x0028 },
X		{ ">>a",			0x0029 },
X		{ "/mod",			0x002a },
X		{ "u/mod",			0x002b },
X		{ "negate",			0x002c },
X		{ "abs",			0x002d },
X		{ "min",			0x002e },
X		{ "max",			0x002f },
X		{ ">r",				0x0030 },
X		{ "r>",				0x0031 },
X		{ "r@",				0x0032 },
X		{ "exit",			0x0033 },
X		{ "0=",				0x0034 },
X		{ "0<>",			0x0035 },
X		{ "0<",				0x0036 },
X		{ "0<=",			0x0037 },
X		{ "0>",				0x0038 },
X		{ "0>=",			0x0039 },
X		{ "<",				0x003a },
X		{ ">",				0x003b },
X		{ "=",				0x003c },
X		{ "<>",				0x003d },
X		{ "u>",				0x003e },
X		{ "u<=",			0x003f },
X		{ "u<",				0x0040 },
X		{ "u>=",			0x0041 },
X		{ ">=",				0x0042 },
X		{ "<=",				0x0043 },
X		{ "between",			0x0044 },
X		{ "within",			0x0045 },
X		{ "drop",			0x0046 },
X		{ "dup",			0x0047 },
X		{ "over",			0x0048 },
X		{ "swap",			0x0049 },
X		{ "rot",			0x004a },
X		{ "-rot",			0x004b },
X		{ "tuck",			0x004c },
X		{ "nip",			0x004d },
X		{ "pick",			0x004e },
X		{ "roll",			0x004f },
X		{ "?dup",			0x0050 },
X		{ "depth",			0x0051 },
X		{ "2drop",			0x0052 },
X		{ "2dup",			0x0053 },
X		{ "2over",			0x0054 },
X		{ "2swap",			0x0055 },
X		{ "2rot",			0x0056 },
X		{ "2/",				0x0057 },
X		{ "u2/",			0x0058 },
X		{ "2*",				0x0059 },
X		{ "/c",				0x005a },
X		{ "/w",				0x005b },
X		{ "/l",				0x005c },
X		{ "/n",				0x005d },
X		{ "ca+",			0x005e },
X		{ "wa+",			0x005f },
X		{ "la+",			0x0060 },
X		{ "na+",			0x0061 },
X		{ "char+",			0x0062 },
X		{ "wa1+",			0x0063 },
X		{ "la1+",			0x0064 },
X		{ "cell+",			0x0065 },
X		{ "chars",			0x0066 },
X		{ "/w*",			0x0067 },
X		{ "/l*",			0x0068 },
X		{ "cells",			0x0069 },
X		{ "on",				0x006a },
X		{ "off",			0x006b },
X		{ "+!",				0x006c },
X		{ "@",				0x006d },
X		{ "l@",				0x006e },
X		{ "w@",				0x006f },
X		{ "<w@",			0x0070 },
X		{ "c@",				0x0071 },
X		{ "!",				0x0072 },
X		{ "l!",				0x0073 },
X		{ "w!",				0x0074 },
X		{ "c!",				0x0075 },
X		{ "2@",				0x0076 },
X		{ "2!",				0x0077 },
X		{ "move",			0x0078 },
X		{ "fill",			0x0079 },
X		{ "comp",			0x007a },
X		{ "noop",			0x007b },
X		{ "lwsplit",			0x007c },
X		{ "wjoin",			0x007d },
X		{ "lbsplit",			0x007e },
X		{ "bljoin",			0x007f },
X		{ "wbflip",			0x0080 },
X		{ "upc",			0x0081 },
X		{ "lcc",			0x0082 },
X		{ "pack",			0x0083 },
X		{ "count",			0x0084 },
X		{ "body>",			0x0085 },
X		{ ">body",			0x0086 },
X		{ "fcode-revision",		0x0087 },
X		{ "span",			0x0088 },
X		{ "unloop",			0x0089 },
X		{ "expect",			0x008a },
X		{ "alloc-mem",			0x008b },
X		{ "free-mem",			0x008c },
X		{ "key?",			0x008d },
X		{ "key",			0x008e },
X		{ "emit",			0x008f },
X		{ "type",			0x0090 },
X		{ "(cr",			0x0091 },
X		{ "cr",				0x0092 },
X		{ "#out",			0x0093 },
X		{ "#line",			0x0094 },
X		{ "hold",			0x0095 },
X		{ "<#",				0x0096 },
X		{ "u#>",			0x0097 },
X		{ "sign",			0x0098 },
X		{ "u#",				0x0099 },
X		{ "u#s",			0x009a },
X		{ "u.",				0x009b },
X		{ "u.r",			0x009c },
X		{ ".",				0x009d },
X		{ ".r",				0x009e },
X		{ ".s",				0x009f },
X		{ "base",			0x00a0 },
X		{ "convert",			0x00a1 },
X		{ "$number",			0x00a2 },
X		{ "digit",			0x00a3 },
X		{ "-1",				0x00a4 },
X		{ "true",			0x00a4 },
X		{ "0",				0x00a5 },
X		{ "1",				0x00a6 },
X		{ "2",				0x00a7 },
X		{ "3",				0x00a8 },
X		{ "bl",				0x00a9 },
X		{ "bs",				0x00aa },
X		{ "bell",			0x00ab },
X		{ "bounds",			0x00ac },
X		{ "here",			0x00ad },
X		{ "aligned",			0x00ae },
X		{ "wbsplit",			0x00af },
X		{ "bwjoin",			0x00b0 },
X		{ "b(<mark)",			0x00b1 },
X		{ "b(>resolve)",		0x00b2 },
X		{ "set-token-table",		0x00b3 },
X		{ "set-table",			0x00b4 },
X		{ "new-token",			0x00b5 },
X		{ "named-token",		0x00b6 },
X		{ "b(:)",			0x00b7 },
X		{ "b(value)",			0x00b8 },
X		{ "b(variable)",		0x00b9 },
X		{ "b(constant)",		0x00ba },
X		{ "b(create)",			0x00bb },
X		{ "b(defer)",			0x00bc },
X		{ "b(buffer:)",			0x00bd },
X		{ "b(field)",			0x00be },
X		{ "b(code)",			0x00bf },
X		{ "instance",			0x00c0 },
X		{ "b(;)",			0x00c2 },
X		{ "b(to)",			0x00c3 },
X		{ "b(case)",			0x00c4 },
X		{ "b(endcase)",			0x00c5 },
X		{ "b(endof)",			0x00c6 },
X		{ "#",				0x00c7 },
X		{ "#s",				0x00c8 },
X		{ "#>",				0x00c9 },
X		{ "external-token",		0x00ca },
X		{ "$find",			0x00cb },
X		{ "offset16",			0x00cc },
X		{ "evaluate",			0x00cd },
X		{ "c,",				0x00d0 },
X		{ "w,",				0x00d1 },
X		{ "l,",				0x00d2 },
X		{ ",",				0x00d3 },
X		{ "um*",			0x00d4 },
X		{ "um/mod",			0x00d5 },
X		{ "d+",				0x00d8 },
X		{ "d-",				0x00d9 },
X		{ "get-token",			0x00da },
X		{ "set-token",			0x00db },
X		{ "state",			0x00dc },
X		{ "compile,",			0x00dd },
X		{ "behavior",			0x00de },
X		{ "start0",			0x00f0 },
X		{ "start1",			0x00f1 },
X		{ "start2",			0x00f2 },
X		{ "start4",			0x00f3 },
X		{ "ferror",			0x00fc },
X		{ "version1",			0x00fd },
X		{ "4-byte-id",			0x00fe },
X		{ "end1",			0x00ff },
X		{ "dma-alloc",			0x0101 },
X		{ "my-address",			0x0102 },
X		{ "my-space",			0x0103 },
X		{ "memmap",			0x0104 },
X		{ "free-virtual",		0x0105 },
X		{ ">physical",			0x0106 },
X		{ "my-params",			0x010f },
X		{ "property",			0x0110 },
X		{ "encode-int",			0x0111 },
X		{ "encode+",			0x0112 },
X		{ "encode-phys",		0x0113 },
X		{ "encode-string",		0x0114 },
X		{ "encode-bytes",		0x0115 },
X		{ "reg",			0x0116 },
X		{ "intr",			0x0117 },
X		{ "driver",			0x0118 },
X		{ "model",			0x0119 },
X		{ "device-type",		0x011a },
X		{ "parse-2int",			0x011b },
X		{ "is-install",			0x011c },
X		{ "is-remove",			0x011d },
X		{ "is-selftest",		0x011e },
X		{ "new-device",			0x011f },
X		{ "diagnostic-mode?",		0x0120 },
X		{ "display-status",		0x0121 },
X		{ "memory-test-suite",		0x0122 },
X		{ "group-code",			0x0123 },
X		{ "mask",			0x0124 },
X		{ "get-msecs",			0x0125 },
X		{ "ms",				0x0126 },
X		{ "finish-device",		0x0127 },
X		{ "decode-phys",		0x0128 },
X		{ "map-low",			0x0130 },
X		{ "sbus-intr>cpu",		0x0131 },
X		{ "#lines",			0x0150 },
X		{ "#columns",			0x0151 },
X		{ "line#",			0x0152 },
X		{ "column#",			0x0153 },
X		{ "inverse?",			0x0154 },
X		{ "inverse-screen?",		0x0155 },
X		{ "frame-buffer-busy?",		0x0156 },
X		{ "draw-character",		0x0157 },
X		{ "reset-screen",		0x0158 },
X		{ "toggle-cursor",		0x0159 },
X		{ "erase-screen",		0x015a },
X		{ "blink-screen",		0x015b },
X		{ "invert-screen",		0x015c },
X		{ "insert-characters",		0x015d },
X		{ "delete-characters",		0x015e },
X		{ "insert-lines",		0x015f },
X		{ "delete-lines",		0x0160 },
X		{ "draw-logo",			0x0161 },
X		{ "frame-buffer-addr",		0x0162 },
X		{ "screen-height",		0x0163 },
X		{ "screen-width",		0x0164 },
X		{ "window-top",			0x0165 },
X		{ "window-left",		0x0166 },
X		{ "default-font",		0x016a },
X		{ "set-font",			0x016b },
X		{ "char-height",		0x016c },
X		{ "char-width",			0x016d },
X		{ ">font",			0x016e },
X		{ "fontbytes",			0x016f },
X		{ "fb8-draw-character",		0x0180 },
X		{ "fb8-reset-screen",		0x0181 },
X		{ "fb8-toggle-cursor",		0x0182 },
X		{ "fb8-erase-screen",		0x0183 },
X		{ "fb8-blink-screen",		0x0184 },
X		{ "fb8-invert-screen",		0x0185 },
X		{ "fb8-insert-characters",	0x0186 },
X		{ "fb8-delete-characters",	0x0187 },
X		{ "fb8-inisert-lines",		0x0188 },
X		{ "fb8-delete-lines",		0x0189 },
X		{ "fb8-draw-logo",		0x018a },
X		{ "fb8-install",		0x018b },
X		{ "return-buffer",		0x01a0 },
X		{ "xmit-packet",		0x01a1 },
X		{ "poll-packet",		0x01a2 },
X		{ "mac-address",		0x01a4 },
X		{ "device-name",		0x0201 },
X		{ "my-args",			0x0202 },
X		{ "my-self",			0x0203 },
X		{ "find-package",		0x0204 },
X		{ "open-package",		0x0205 },
X		{ "close-package",		0x0206 },
X		{ "find-method",		0x0207 },
X		{ "call-package",		0x0208 },
X		{ "$call-parent",		0x0209 },
X		{ "my-parent",			0x020a },
X		{ "ihandle>phandle",		0x020b },
X		{ "my-unit",			0x020d },
X		{ "$call-method",		0x020e },
X		{ "$open-package",		0x020f },
X		{ "processor-type",		0x0210 },
X		{ "firmware-version",		0x0211 },
X		{ "fcode-version",		0x0212 },
X		{ "alarm",			0x0213 },
X		{ "(is-user-word)",		0x0214 },
X		{ "suspend-fcode",		0x0215 },
X		{ "abort",			0x0216 },
X		{ "catch",			0x0217 },
X		{ "throw",			0x0218 },
X		{ "user-abort",			0x0219 },
X		{ "get-my-property",		0x021a },
X		{ "decode-int",			0x021b },
X		{ "decode-string",		0x021c },
X		{ "get-inherited-property",	0x021d },
X		{ "delete-property",		0x021e },
X		{ "get-package-property",	0x021f },
X		{ "cpeek",			0x0220 },
X		{ "wpeek",			0x0221 },
X		{ "lpeek",			0x0222 },
X		{ "cpoke",			0x0223 },
X		{ "wpoke",			0x0224 },
X		{ "lpoke",			0x0225 },
X		{ "lwflip",			0x0226 },
X		{ "lbflip",			0x0227 },
X		{ "lbflips",			0x0228 },
X		{ "adr-mask",			0x0229 },
X		{ "rb@",			0x0230 },
X		{ "rb!",			0x0231 },
X		{ "rw@",			0x0232 },
X		{ "rw!",			0x0233 },
X		{ "rl@",			0x0234 },
X		{ "rl!",			0x0235 },
X		{ "wbflips",			0x0236 },
X		{ "lwflips",			0x0237 },
X		{ "probe",			0x0238 },
X		{ "probe-virtual",		0x0239 },
X		{ "child",			0x023b },
X		{ "peer",			0x023c },
X		{ "next-property",		0x023d },
X		{ "byte-load",			0x023e },
X		{ "set-args",			0x023f },
X		{ "left-parse-string",		0x0240 },
X			/* 64-bit FCode extensions */
X		{ "bxjoin",			0x0241 },
X		{ "<l@",			0x0242 },
X		{ "lxjoin",			0x0243 },
X		{ "rx@",			0x022e },
X		{ "rx!",			0x022f },
X		{ "wxjoin",			0x0244 },
X		{ "x,",				0x0245 },
X		{ "x@",				0x0246 },
X		{ "x!",				0x0247 },
X		{ "/x",				0x0248 },
X		{ "/x*",			0x0249 },
X		{ "xa+",			0x024a },
X		{ "xa1+",			0x024b },
X		{ "xbflip",			0x024c },
X		{ "xbflips",			0x024d },
X		{ "xbsplit",			0x024e },
X		{ "xlflip",			0x024f },
X		{ "xlflips",			0x0250 },
X		{ "xlsplit",			0x0251 },
X		{ "xwflip",			0x0252 },
X		{ "xwflips",			0x0253 },
X		{ "xwsplit",			0x0254 },
X		{ NULL, 0 }
X};
X
X/*
X * Default macros -- can be overridden by colon definitions.
X */
Xstruct macro macros[] = {
X	{ "eval",	"evaluate" }, /* Build a more balanced tree */
X	{ "(.)",	"dup abs <# u#s swap sign u#>" },
X	{ "<<",		"lshift" },
X	{ ">>",		"rshift" },
X	{ "?",		"@ ." },
X	{ "1+",		"1 +" },
X	{ "1-",		"1 -" },
X	{ "2+",		"2 +" },
X	{ "2-",		"2 -" },
X	{ "accept",	"span @ -rot expect span @ swap span !" },
X	{ "allot",	"0 max 0 ?do 0 c, loop" },
X	{ "blank",	"bl fill" },
X	{ "/c*",	"chars" },
X	{ "ca1+",	"char+" },
X	{ "carret",	"b(lit) 00 00 00 h# 0d" },
X	{ ".d",		"base @ swap d# 10 base ! . base !" },
X	{ "decode-bytes", ">r over r@ + swap r@ - rot r>" },
X	{ "3drop",	"drop 2drop" },
X	{ "3dup",	"2 pick 2 pick 2 pick" },
X	{ "erase",	"0 fill" },
X	{ "false",	"0" },
X	{ ".h",		"base @ swap d# 16 base ! . base !" },
X	{ "linefeed",	"b(lit) 00 00 00 h# 0a" },
X	{ "/n*",	"cells" },
X	{ "na1+",	"cell+", },
X	{ "not",	"invert", },
X	{ "s.",		"(.) type space" },
X	{ "space",	"bl emit" },
X	{ "spaces",	"0 max 0 ?do space loop" },
X	{ "struct",	"0" },
X	{ "true",	"-1" },
X	{ "(u,)",	"<# u#s u#>" },
X	{ NULL, NULL }
X};
X
X/*
X * Utility functions.
X */
X
X/*
X * ASCII -> long int converter, eats `.'s
X */
X#define strtol(x, y, z)		cvt(x, y, z)
XCell
Xcvt(s, e, base)
Xchar *s, **e; 
Xint base;
X{
X	Cell v = 0;
X	int c, n = 0;
X
X	c = *s;
X	if (c == '-') { n = 1; s++; }
X
X	for (c = *s; (c = *s); s++) {
X
X		/* Ignore `.' */
X		if (c == '.') 
X			continue;
X		if (c >= '0' && c <= '9')
X			c -= '0';
X		else if (c >= 'a' && c <= 'f')
X			c += 10 - 'a';
X		else if (c >= 'A' && c <= 'F')
X			c += 10 - 'A';
X		if (c >= base)
X			break;
X		v *= base;
X		v += c;
X	}
X	if (e)
X		*e = s;
X	if (n)
X		return (-v);
X	return (v);
X}
X
X/*
X * Parser stack control functions.
X */
X
Xvoid
Xpush(val)
XCell val;
X{
X	if (debug > 1)
X		printf("push %lx\n", (long)val);
X	parse_stack[parse_stack_ptr++] = val;
X	if (parse_stack_ptr >= PSTKSIZ) {
X		(void)printf( "Parse stack overflow\n");
X		exit(1);
X	}
X}
X
XCell
Xpop()
X{
X	ASSERT(parse_stack_ptr);
X	if (debug > 1)
X		printf("pop %lx\n", (long)parse_stack[parse_stack_ptr-1]);
X	return parse_stack[--parse_stack_ptr];
X}
X
Xint
Xdepth()
X{
X	return (parse_stack_ptr);
X}
X
X/*
X * Insert fcode into dictionary.
X */
Xint
Xfadd(dict, new)
Xstruct fcode *dict, *new;
X{
X	int res = strcmp(dict->name, new->name);
X
X	new->type = FCODE;
X	ASSERT(dict->type == FCODE);
X	if (!res) {
X		/* 
X		 * Duplicate entry.  Give the old name the new FCode
X		 * number. 
X		 */
X		dict->num = new->num;
X		return (0);
X	}
X	if (res < 0) {
X		if (dict->l)
X			return fadd(dict->l, new);
X		else {
X			if (debug > 5)
X				(void)printf( "fadd: new FCode `%s' is %lx\n", 
X					      new->name, new->num);
X			new->l = new->r = NULL;
X			dict->l = new;
X		}
X	} else {
X		if (dict->r)
X			return fadd(dict->r, new);
X		else {
X			if (debug > 5)
X				(void)printf( "fadd: new FCode `%s' is %lx\n", 
X					      new->name, new->num);
X			new->l = new->r = NULL;
X			dict->r = new;
X		}
X	}
X	return (1);
X}
X
X/*
X * Look for a code in the dictionary.
X */
Xstruct fcode *
Xflookup(dict, str)
Xstruct fcode *dict;
Xchar *str;
X{
X	int res;
X	if (!dict) return (dict);
X
X	res = strcmp(dict->name, str);
X	ASSERT(dict->type == FCODE);
X	if (debug > 5)
X		(void)printf( "flookup: `%s' and `%s' %s match\n", 
X			      str, dict->name, res?"don't":"do");
X	if (!res) return (dict);
X	if (res < 0)
X		return (flookup(dict->l, str));
X	else 
X		return (flookup(dict->r, str));
X
X}
X
X/*
X * Insert alias into macros.
X */
Xint
Xaadd(dict, new)
X	struct macro *dict, *new;
X{
X	int res = strcmp(dict->name, new->name);
X
X	new->type = MACRO;
X	ASSERT(dict->type == MACRO);
X	if (!res) {
X		/* Duplicate name.  Replace the old macro */
X		dict->equiv = new->equiv;
X		/* We can't free the old equiv since it may be static data. */
X		return (0);
X	}
X	if (res < 0) {
X		if (dict->l)
X			return aadd(dict->l, new);
X		else {
X			new->l = new->r = NULL;
X			dict->l = new;
X			if (debug > 5)
X				(void)printf( "aadd: new alias `%s' to `%s'\n", 
X					      new->name, new->equiv);
X		}
X	} else {
X		if (dict->r)
X			return aadd(dict->r, new);
X		else {
X			new->l = new->r = NULL;
X			dict->r = new;
X			if (debug > 5)
X				(void)printf( "aadd: new alias `%s' to `%s'\n", 
X					      new->name, new->equiv);
X		}
X	}
X	return (1);
X}
X
X/*
X * Look for a macro in the aliases.
X */
Xstruct macro *
Xalookup(dict, str)
Xstruct macro *dict;
Xchar *str;
X{
X	int res;
X	if (!dict) return (dict);
X
X	ASSERT(dict->type == MACRO);
X	res = strcmp(dict->name, str);
X	if (!res) return (dict);
X	if (res < 0)
X		return (alookup(dict->l, str));
X	else 
X		return (alookup(dict->r, str));
X
X}
X
X/*
X * Bootstrap the dictionary and then install
X * all the standard FCodes.
X */
Xvoid
Xinitdic()
X{
X	struct fcode *code = fcodes;
X	struct macro *alias = macros;
X
X	ASSERT(dictionary == NULL);
X	code->l = code->r = NULL;
X	dictionary = code;
X	code->type = FCODE;
X
X	while ((++code)->name) {
X		if(!fadd(dictionary, code)) {
X			printf("init: duplicate dictionary entry %s\n", 
X			       code->name);
X		}
X	}
X
X	ASSERT(aliases == NULL);
X	aliases = alias;
X	alias->l = alias->r = NULL;
X	alias->type = MACRO;
X	while ((++alias)->name) {
X		if(!aadd(aliases, alias)) {
X			printf("init: duplicate macro entry %s\n", 
X			       alias->name);
X		}
X	}
X
X}
X
Xint
Xapply_macros(input, str) 
X	YY_BUFFER_STATE input;
X	char *str;
X{
X	struct macro *xform = alookup(aliases, str);
X	
X	if (xform) {
X		YY_BUFFER_STATE newbuf;
X
X		if (debug > 1) 
X			printf("Expanding %s to %s\n", str, xform->equiv);
X
X		newbuf = yy_scan_string(xform->equiv);
X		yy_switch_to_buffer(newbuf);
X		tokenize(newbuf);
X		yy_switch_to_buffer(input);
X		yy_delete_buffer(newbuf);
X	}
X	return (xform != NULL);
X}
X
Xvoid
Xusage(me)
X	char *me;
X{
X	(void)fprintf(stderr, "%s: [-o <outfile>] <infile>\n", me);
X	exit(1);
X}
X
Xint
Xmain(argc, argv)
X	int argc;
X	char *argv[];
X{
X	int bflag, ch;
X	FILE *inf;
X	struct fcode_header *fheader;
X	YY_BUFFER_STATE inbuf;
X	char *hdrtype = "version1";
X	int i;
X
X	outf = 1; /* stdout */
X	myname = argv[0];
X
X	bflag = 0;
X	while ((ch = getopt(argc, argv, "d:o:")) != -1)
X		switch(ch) {
X		case 'd':
X			mark_fload = 1;
X			debug = atol(optarg);
X			break;
X		case 'o':
X			outfile = optarg;
X			break;
X		case '?':
X		default:
X			warnx("Illegal argument: %c", ch);
X			usage(myname);
X		}
X	argc -= optind;
X	argv += optind;
X	
X	if (argc != 1)
X		usage(myname);
X	
X	infile = argv[0];
X
X	/*
X	 * Initialization stuff.
X	 */
X	initdic();
X	outbufsiz = BUFCLICK;
X	outbuf = malloc(outbufsiz);
X	fheader = (struct fcode_header *)outbuf;
X	outpos = 0;
X	emit(hdrtype);
X	outpos = sizeof(*fheader);
X
X	/* 
X	 * Do it.
X	 */
X	if ((inf = fopen(infile, "r")) == NULL)
X		(void)err(1, "can not open %s for reading", infile);
X
X	inbuf = yy_create_buffer( inf, YY_BUF_SIZE );
X	yy_switch_to_buffer(inbuf);
X	tokenize(inbuf);
X	yy_delete_buffer(inbuf);
X	fclose(inf);
X	if (need_end0) emit("end0");
X
X	/* Now calculate length and checksum and stick them in the header */
X	fheader->format = 0x08;
X	fheader->length = htonl(outpos);
X	fheader->checksum = 0;
X	for (i = sizeof(*fheader); i<outpos; i++)
X		fheader->checksum += (unsigned char)outbuf[i];
X	fheader->checksum = htons(fheader->checksum);
X
X	if ((outf = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1)
X		err(1, "can out open %s for writing", outfile);
X
X	if (write(outf, outbuf, outpos) != outpos) {
X		close(outf);
X		unlink(outfile);
X		err(1, "write error");
X	}
X	close(outf);
X	return (0);
X};
X
X/*
X * Tokenize one file.  This is a separate function so it can
X * be called recursively to parse mutiple levels of include files.
X */
X
Xvoid
Xtokenize(input_buf) 
X	YY_BUFFER_STATE input_buf;
X{
X	FILE *inf;
X	YY_BUFFER_STATE inbuf;
X	TOKEN *token;
X	char *last_token = "";
X	struct fcode *fcode;
X	int pos, off;
X
X	while ((token = yylex()) != NULL) {
X		switch (token->type) {
X		case TOK_NUMBER:
X			STATE(token->text, "TOK_NUMBER");
X		{ 
X			char *end;
X			Cell value;
X			
X			if (tokenizer) {
X				push(strtol(token->text, &end, 16));
X				break;
X			}
X			value = strtol(token->text, &end, base);
X			if (*end != 0)
X				token_err(yylineno, infile, yytext,
X				    "illegal number conversion");
X
X			/* 
X			 * If this is a 64-bit value we need to store two literals
X			 * and issue a `lxjoin' to combine them.  But that's a future
X			 * project.
X			 */
X			emit("b(lit)");
X			spit((value>>24)&0x0ff);
X			spit((value>>16)&0x0ff);
X			spit((value>>8)&0x0ff);
X			spit(value&0x0ff);
X			if ((value>>32) != value && (value>>32) != 0 && 
X				(value>>32) != -1) {
X				emit("b(lit)");
X				spit((value>>56)&0x0ff);
X				spit((value>>48)&0x0ff);
X				spit((value>>40)&0x0ff);
X				spit((value>>32)&0x0ff);
X				emit("lxjoin");
X			}
X		}
X		break;
X		case TOK_C_LIT:
X			STATE(token->text, "TOK_C_LIT");
X			emit("b(lit)");
X			spit(0);
X			spit(0);
X			spit(0);
X			spit(token->text[1]);
X		break;
X		case TOK_STRING_LIT: 
X			STATE(token->text, "TOK_STRING_LIT:");
X		{
X			int len;
X			char *p = token->text;
X			
X			++p;			/* Skip the quote */
X			len = strlen(++p);	/* Skip the 1st space */
X
X#define ERR_TOOLONG	\
X	token_err(yylineno, infile, yytext, "string length %d too long", len)
X
X			if (len > 255)
X				ERR_TOOLONG;
X
X			if (p[len-1] == ')' ||
X			    p[len-1] == '"') {
X				p[len-1] = 0;
X			}
X			emit("b(\")");
X			sspit(p);
X		}
X		break;
X		case TOK_PSTRING: 
X			STATE(token->text, "TOK_PSTRING:");
X		{
X			int len;
X			char *p = token->text;
X
X			if (*p++ == '.') p++; /* Skip over delimiter */
X			p++; /* Skip over space/tab */
X
X			len = strlen(p);
X			if (len > 255)
X				ERR_TOOLONG;
X
X			if (p[len-1] == ')' ||
X			    p[len-1] == '"') {
X				p[len-1] = 0;
X			}
X			emit("b(\")");
X			sspit(p);
X			emit("type");
X		}
X		break;
X		case TOK_ABORT_S:
X			STATE(token->text, "TOK_PSTRING:");
X		{
X			int len;
X			Cell value = -2;
X			char *p = token->text;
X
X			while (*p++ != ' '); /* Skip to the string */
X
X			len = strlen(p);
X			if (len > 255)
X				ERR_TOOLONG;
X
X			if (p[len-1] == '"') {
X				p[len-1] = 0;
X			}
X			emit("b?branch");
X			push(outpos);
X			offspit(0);
X			emit("b(\")");
X			sspit(p);
X			emit("type");
X			emit("cr");
X			emit("b(lit)");
X			spit((value>>24)&0x0ff);
X			spit((value>>16)&0x0ff);
X			spit((value>>8)&0x0ff);
X			spit(value&0x0ff);
X			emit("throw");
X			emit("b(>resolve)");
X			pos = outpos;
X			outpos = pop();
X			off = pos - outpos;
X			offspit(off);
X			outpos = pos;
X		}
X		break;
X
X		case TOK_TOKENIZE:
X			STATE(token->text, "TOK_TOKENIZE");
X			/* The next pass should tokenize the FCODE number */
X			emit("b(')");
X			break;
X		case TOK_COMMENT: 
X			STATE(token->text, "TOK_COMMENT:");
X			do {
X				off = input();
X			} while ((off != ')') && (off != '\n') && 
X				(off != EOF));
X			break;
X		case TOK_COLON: 
X			STATE(token->text, "TOK_COLON:");
X
X			token = yylex();
X			if (token == NULL)
X				token_err(yylineno, infile, yytext,
X				    "EOF in colon definition");
X			
X			/* Add new code to dictionary */
X			fcode = malloc(sizeof(*fcode));
X			fcode->num = nextfcode++;
X			fcode->name = strdup(token->text);
X			if (!fadd(dictionary, fcode)) {
X				/* Duplicate definition.  Free the memory. */
X				if (debug)
X					(void)printf("%s: duplicate FCode\n",
X						token->text);
X				free(fcode->name);
X				free(fcode);
X			}
X			if (debug)
X				(void)printf("Adding %s to dictionary\n", token->text);		
X			if (state == 0)
X				emit("new-token");
X			else {
X				if (state == TOK_EXTERNAL)
X					emit("external-token");
X				else
X				/* Here we have a choice of new-token or named-token */
X					emit("named-token");
X				sspit(token->text);
X			}
X			spit(fcode->num);
X			emit("b(:)");
X			last_token = fcode->name;
X			defining = 1;
X 			break;
X		case TOK_SEMICOLON: 
X			STATE(token->text, "TOK_SEMICOLON:");
X			emit("b(;)");
X			defining = 0;
X			if (depth()) {
X				token_err(yylineno, infile, NULL,
X				    "Warning: stack depth %d at end of %s\n",
X				    depth(), last_token);
X			}
X			last_token = "";
X			break;
X
X			/* These are special */
X		case TOK_AGAIN:
X			STATE(token->text, "TOK_AGAIN");
X			emit("bbranch");
X			pos = pop();
X			pos = pos - outpos;
X			offspit(pos);
X			break;
X		case TOK_ALIAS:
X			STATE(token->text, "TOK_ALIAS");
X		{
X			struct macro *alias;
X
X			token = yylex();
X			if (token == NULL) {
X				(void)printf( "EOF in alias definition\n");
X				return;
X			}
X			if (token->type != TOK_OTHER) {
X				(void)printf( "ENDCOMMENT aliasing weird token type %d\n",
X					      token->type);
X			}
X			alias = malloc(sizeof(*alias));
X			alias->name = strdup(token->text);
X			token = yylex();
X			if (token == NULL) {
X				(void)printf( "EOF in alias definition\n");
X				return;
X			}			
X			alias->equiv = strdup(token->text);
X			if (!aadd(aliases, alias)) {
X				free(alias->name);
X				free(alias);
X			}
X		}
X		break;
X		case TOK_GETTOKEN:
X			STATE(token->text, "TOK_GETTOKEN");
X			/* This is caused by ['] */
X			emit("b(')");
X			token = yylex();
X			if (token == NULL) {
X				(void)printf( "EOF in [']\n");
X				return;
X			}
X			if ((fcode = flookup(dictionary, token->text)) == NULL) {
X				(void)printf( "[']: %s not found\n", token->text);
X				exit(1);
X			}
X			spit(fcode->num);
X			break;
X		case TOK_ASCII:
X			STATE(token->text, "TOK_ASCII");
X			token = yylex();
X			if (token == NULL) {
X				(void)printf( "EOF after \"ascii\"\n");
X				exit(1);
X			}
X			emit("b(lit)");
X			spit(0);
X			spit(0);
X			spit(0);
X			spit(token->text[0]);
X			break;
X		case TOK_BEGIN:
X			STATE(token->text, "TOK_BEGIN");
X			emit("b(<mark)");
X			push(outpos);
X			break;
X		case TOK_BUFFER:
X			STATE(token->text, "TOK_BUFFER");
X
X			token = yylex();
X			if (token == NULL) {
X				(void)printf( "EOF in colon definition\n");
X				return;
X			}
X			
X			/* Add new code to dictionary */
X			fcode = malloc(sizeof(*fcode));
X			fcode->num = nextfcode++;
X			fcode->name = strdup(token->text);
X			fadd(dictionary, fcode);
X			
X			if (state == 0)
X				emit("new-token");
X			else {
X				if (state == TOK_EXTERNAL)
X					emit("external-token");
X				else
X				/* Here we have a choice of new-token or named-token */
X					emit("named-token");
X				sspit(token->text);
X			}
X			spit(fcode->num);
X			emit("b(buffer:)");
X			break;
X		case TOK_CASE:
X			STATE(token->text, "TOK_CASE");
X			emit("b(case)");
X			push(0);
X			break;
X		case TOK_CONSTANT:
X			STATE(token->text, "TOK_CONSTANT");
X
X			token = yylex();
X			if (token == NULL) {
X				(void)printf( "EOF in constant definition\n");
X				return;
X			}
X			
X			/* Add new code to dictionary */
X			fcode = malloc(sizeof(*fcode));
X			fcode->num = nextfcode++;
X			fcode->name = strdup(token->text);
X			fadd(dictionary, fcode);
X			
X			if (state == 0)
X				emit("new-token");
X			else {
X				if (state == TOK_EXTERNAL)
X					emit("external-token");
X				else
X				/* Here we have a choice of new-token or named-token */
X					emit("named-token");
X				sspit(token->text);
X			}
X			spit(fcode->num);
X			emit("b(constant)");
X			break;
X		case TOK_CONTROL:
X			STATE(token->text, "TOK_CONTROL");
X			token = yylex();
X			if (token == NULL) {
X				(void)printf( "EOF after \"ascii\"\n");
X				exit(1);
X			}
X			emit("b(lit)");
X			spit(0);
X			spit(0);
X			spit(0);
X			spit(token->text[0]&0x1f);
X			break;
X		case TOK_CREATE:
X			STATE(token->text, "TOK_CREATE");
X			/* Don't know what this does or if it's right */
X			token = yylex();
X			if (token == NULL) {
X				(void)printf( "EOF in create definition\n");
X				return;
X			}
X			
X			/* Add new code to dictionary */
X			fcode = malloc(sizeof(*fcode));
X			fcode->num = nextfcode++;
X			fcode->name = strdup(token->text);
X			fadd(dictionary, fcode);
X			
X			if (state == 0)
X				emit("new-token");
X			else {
X				if (state == TOK_EXTERNAL)
X					emit("external-token");
X				else
X				/* Here we have a choice of new-token or named-token */
X					emit("named-token");
X				sspit(token->text);
X			}
X			spit(fcode->num);
X			emit("b(create)");
X			break;
X		case TOK_DECIMAL:
X			STATE(token->text, "TOK_DECIMAL");
X			if (token->text[1] != '#') {
X				if (defining) {
X					emit("b(lit)");
X					spit(0);
X					spit(0);
X					spit(0);
X					spit(10);
X					emit("base");
X					emit("!");
X				} else
X					base = TOK_DECIMAL;
X			} else {
X				char *end;
X				Cell value;
X
X				token = yylex();
X				if (token == NULL) {
X					(void)printf( "EOF after d#\n");
X					return;
X				}
X				if (token->type == TOK_OTHER) {
X					if (strcmp("-1", token->text) == 0) {
X						emit(token->text);
X						break;
X					}
X				}
X				value = strtol(token->text, &end, 10);
X				if (*end != 0)
X					token_err(yylineno, infile, NULL,
X					    "Illegal number conversion: %s", token->text);
X
X				/* 
X				 * If this is a 64-bit value we need to store two literals
X				 * and issue a `lxjoin' to combine them.  But that's a future
X				 * project.
X				 */
X				emit("b(lit)");
X				spit((value>>24)&0x0ff);
X				spit((value>>16)&0x0ff);
X				spit((value>>8)&0x0ff);
X				spit(value&0x0ff);
X				if ((value>>32) != value && (value>>32) != 0) {
X					emit("b(lit)");
X					spit((value>>56)&0x0ff);
X					spit((value>>48)&0x0ff);
X					spit((value>>40)&0x0ff);
X					spit((value>>32)&0x0ff);
X					emit("lxjoin");
X				}
X			}
X			break;
X		case TOK_DEFER:
X			STATE(token->text, "TOK_DEFER");
X			/* Don't know what this does or if it's right */
X			token = yylex();
X			if (token == NULL) {
X				(void)printf( "EOF in colon definition\n");
X				return;
X			}
X			
X			/* Add new code to dictionary */
X			fcode = malloc(sizeof(*fcode));
X			fcode->num = nextfcode++;
X			fcode->name = strdup(token->text);
X			fadd(dictionary, fcode);
X			
X			if (state == 0)
X				emit("new-token");
X			else {
X				if (state == TOK_EXTERNAL)
X					emit("external-token");
X				else
X				/* Here we have a choice of new-token or named-token */
X					emit("named-token");
X				sspit(token->text);
X			}
X			spit(fcode->num);
X			emit("b(defer)");
X			break;
X		case TOK_DO:
X			STATE(token->text, "TOK_DO");
X			/*
X			 * From the 1275 spec.  B is branch location, T is branch target.
X			 *
X			 *	b(do)  offset1 ... b(loop)  offset2 ...
X			 *	b(do)  offset1 ... b(+loop) offset2 ...
X			 *	b(?do) offset1 ... b(loop)  offset2 ...
X			 *	b(?do) offset1 ... b(+loop) offset2 ...
X			 *            ^                            ^
X			 *           B1       ^            ^       T1
X			 *                    T2           B2
X			 *
X			 * How we do this is we generate the b(do) or b(?do), spit out a
X			 * zero offset while remembering b1 and t2.  Then we call tokenize()
X			 * to generate the body.  When tokenize() finds a b(loop) or b(+loop),
X			 * it generates the FCode and returns, with outpos at b2.  We then
X			 * calculate the offsets, put them in the right slots and finishup.
X			 */
X			
X			if (token->text[0] == '?')
X				emit("b(?do)");
X			else
X				emit("b(do)");
X			push(outpos);
X			offspit(0);	/* Place holder for later */
X			push(outpos);
X			break;
X		case TOK_END0:
X			STATE(token->text, "TOK_ELSE");
X			emit("end0");
X			/* Remember we already generated end0 */
X			need_end0 = 0;
X			break;
X		case TOK_ELSE:
X			STATE(token->text, "TOK_ELSE");
X			/* Get where we need to patch */
X			off = pop();
X			emit("bbranch");
X			/* Save where we are now. */
X			push(outpos);
X			offspit(0);	/* Place holder for later */
X			emit("b(>resolve)");
X			/* Rewind and patch the if branch */
X			pos = outpos;
X			outpos = off;
X			off = pos - off;
X			offspit(off);	/* Place holder for later */
X			/* revert to the end */
X			outpos = pos;
X			break;
X		case TOK_ENDCASE: 
X			STATE(token->text, "TOK_ENDCASE:");
X			emit("b(endcase)");
X			pos = outpos; /* Remember where we need to branch to */
X
X			/* Thread our way backwards and install proper offsets */
X			off = pop();
X			while (off) {
X				int disp;
X				int next;
X
X				/* Move to this offset */
X				outpos = off;
X				/* Load next offset to process */
X				disp = (signed char)(outbuf[outpos]);
X				if (offsetsize == 16) {
X					disp = (disp << 8) | 
X						(unsigned char)outbuf[outpos+1];
X				}
X				next = outpos + disp;
X				if (debug > 3)
X					printf("Next endof: %x at %x\n", 
X						disp, next);
X
X				/* process this offset */
X				off = pos - outpos;
X				offspit(off);
X				if ((off = disp))
X					off = next;
X			}
X			outpos = pos;
X			break;
X		case TOK_ENDOF:
X			STATE(token->text, "TOK_ENDOF");
X			off = pop();
X			emit("b(endof)");
X			/* 
X			 * Save back pointer in the offset field so we can traverse
X			 * the linked list and patch it in the endcase.
X			 */
X			pos = pop();	/* get position of prev link. */
X			push(outpos);	/* save position of this link. */
X			if (pos)
X				/* save potision of prev link. */
X				offspit(pos - outpos);
X			else
X				/* This is the first statement */
X				offspit(0);
X			pos = outpos;
X			/* Now point the offset from b(of) here. */
X			outpos = off;
X			off = pos - off;
X			offspit(off);
X			/* Restore position */
X			outpos = pos;
X			break;
X		case TOK_EXTERNAL:
X			STATE(token->text, "TOK_EXTERNAL");
X			state = TOK_EXTERNAL;
X			break;
X		case TOK_FCODE_VERSION2:
X			/* This is actually a tokenizer directive. */
X			STATE(token->text, "TOK_FCODE_VERSION2");
X			offsetsize = 16;
X			pos = outpos;
X			outpos = 0;
X			emit("start1");
X			outpos = pos;
X			break;
X		case TOK_FCODE_END:
X			/* 
X			 * Another tokenizer directive.
X			 *
X			 * This should generate end0 and finish filling in
X			 * the FCode header.  But that's all done in main().
X			 */
X			return;
X		case TOK_FIELD:
X			STATE(token->text, "TOK_FIELD");
X	
X			token = yylex();
X			if (token == NULL) {
X				(void)printf( "EOF in field definition\n");
X				return;
X			}
X			
X			/* Add new code to dictionary */
X			fcode = malloc(sizeof(*fcode));
X			fcode->num = nextfcode++;
X			fcode->name = strdup(token->text);
X			fadd(dictionary, fcode);
X			
X			if (state == 0)
X				emit("new-token");
X			else {
X				if (state == TOK_EXTERNAL)
X					emit("external-token");
X				else
X				/* Here we have a choice of new-token or named-token */
X					emit("named-token");
X				sspit(token->text);
X			}
X			spit(fcode->num);
X			emit("b(field)");
X			break;
X		
X		case TOK_HEX:
X			STATE(token->text, "TOK_HEX");
X			if (token->text[1] != '#') {
X				if (defining) {
X					emit("b(lit)");
X					spit(0);
X					spit(0);
X					spit(0);
X					spit(16);
X					emit("base");
X					emit("!");
X				} else
X					base = TOK_HEX;
X			} else {
X				char *end;
X				Cell value;
X
X				token = yylex();
X				if (token == NULL) {
X					(void)printf( "EOF after h#\n");
X					return;
X				}
X				value = strtol(token->text, &end, 16);
X				if (*end != 0) {
X					(void)printf("Illegal number conversion:%s:%d: %s\n",
X					    infile, yylineno, yytext);
X					exit(1);
X				}
X				/* 
X				 * If this is a 64-bit value we need to store two literals
X				 * and issue a `lxjoin' to combine them.  But that's a future
X				 * project.
X				 */
X				emit("b(lit)");
X				spit((value>>24)&0x0ff);
X				spit((value>>16)&0x0ff);
X				spit((value>>8)&0x0ff);
X				spit(value&0x0ff);
X				if ((value>>32) != value && (value>>32) != 0) {
X					emit("b(lit)");
X					spit((value>>56)&0x0ff);
X					spit((value>>48)&0x0ff);
X					spit((value>>40)&0x0ff);
X					spit((value>>32)&0x0ff);
X					emit("lxjoin");
X				}
X			}
X			break;
X		case TOK_HEADERLESS:
X			STATE(token->text, "TOK_HEADERLESS");
X			state = 0;
X			break;
X		case TOK_HEADERS:
X			STATE(token->text, "TOK_HEADERS");
X			state = TOK_HEADERS;
X			break;
X		case TOK_IF:
X			STATE(token->text, "TOK_IF");
X			/*
X			 * Similar to do but simpler since we only deal w/one branch.
X			 */
X			emit("b?branch");
X			push(outpos);
X			offspit(0);	/* Place holder for later */
X			break;
X		case TOK_LEAVE:
X			STATE(token->text, "TOK_LEAVE");
X			emit("b(leave)");
X			break;
X		case TOK_LOOP:
X			STATE(token->text, "TOK_LOOP");
X
X			if (token->text[0] == '+')
X				emit("b(+loop)");
X			else
X				emit("b(loop)");
X			/* First do backwards branch of loop */
X			pos = pop();
X			off = pos - outpos;
X			offspit(off);
X			/* Now do forward branch of do */
X			pos = outpos;
X			outpos = pop();
X			off = pos - outpos;
X			spit(off);
X			/* Restore output position */
X			outpos = pos;
X			break;
X		case TOK_OCTAL:
X			STATE(token->text, "TOK_OCTAL");
X			if (token->text[1] != '#') {
X				if (defining) {
X					spit(16);
X					emit("base");
X					emit("!");
X				} else
X					base = TOK_OCTAL;
X			} else {
X				char *end;
X				Cell value;
X
X				token = yylex();
X				if (token == NULL) {
X					(void)printf( "EOF after o#\n");
X					return;
X				}
X				value = strtol(token->text, &end, 8);
X				if (*end != 0) {
X					(void)printf("Illegal number conversion:%s:%d: %s\n",
X					    infile, yylineno, yytext);
X					exit(1);
X				}
X				/* 
X				 * If this is a 64-bit value we need to store two literals
X				 * and issue a `lxjoin' to combine them.  But that's a future
X				 * project.
X				 */
X				emit("b(lit)");
X				spit((value>>24)&0x0ff);
X				spit((value>>16)&0x0ff);
X				spit((value>>8)&0x0ff);
X				spit(value&0x0ff);
X				if ((value>>32) != value && (value>>32) != 0) {
X					emit("b(lit)");
X					spit((value>>56)&0x0ff);
X					spit((value>>48)&0x0ff);
X					spit((value>>40)&0x0ff);
X					spit((value>>32)&0x0ff);
X					emit("lxjoin");
X				}
X			}
X			break;
X		case TOK_OF:
X			STATE(token->text, "TOK_OF");
X			/*
X			 * Let's hope I get the semantics right.
X			 *
X			 * The `of' behaves almost the same as an
X			 * `if'.  The difference is that `endof'
X			 * takes a branch offset to the associated
X			 * `endcase'.  Here we will generate a temporary
X			 * offset of the `of' associated with the `endof'.
X			 * Then in `endcase' we should be pointing just
X			 * after the offset of the last `endof' so we 
X			 * calculate the offset and thread our way backwards
X			 * searching for the previous `b(case)' or `b(endof)'.
X			 */
X			emit("b(of)");
X			push(outpos);
X			offspit(0);	/* Place holder for later */
X			break;
X		case TOK_OFFSET16:
X			STATE(token->text, "TOK_OFFSET16");
X			offsetsize = 16;
X			emit("offset16");
X			break;
X		case TOK_REPEAT:
X			STATE(token->text, "TOK_REPEAT");
X			emit("bbranch");
X			pos = pop();
X			off = pop();
X			/* First the offset for the branch back to the begin */
X			off -= outpos;
X			offspit(off);
X			emit("b(>resolve)");
X			/* Now point the offset of the while here. */
X			off = outpos;
X			outpos = pos;
X			pos = off - pos;
X			offspit(pos);
X			/* Return to the end of the output */
X			outpos = off;
X			break;
X		case TOK_STARTX:
X			/* Put a "startX" at addr 0. */
X			STATE(token->text, "TOK_FCODE_VERSION2");
X			offsetsize = 16;
X			pos = outpos;
X			outpos = 0;
X			emit(token->text);
X			outpos = pos;
X			break;
X		case TOK_THEN:
X			STATE(token->text, "TOK_THEN");
X			emit("b(>resolve)");
X			pos = outpos;
X			outpos = pop();
X			off = pos - outpos;
X			offspit(off);
X			outpos = pos;
X			break;
X		case TOK_TO:
X			STATE(token->text, "TOK_TO");
X			/* The next pass should tokenize the FCODE number */
X			emit("b(to)");
X			break;
X		case TOK_UNTIL:
X			STATE(token->text, "TOK_UNTIL");
X		{
X			int pos;
X
X			emit("b?branch");
X			pos = pop();
X			pos -= outpos;
X			offspit(pos);
X		}
X		break;			
X		case TOK_VALUE:
X			STATE(token->text, "TOK_VALUE");
X
X			token = yylex();
X			if (token == NULL) {
X				(void)printf( "EOF in value definition\n");
X				return;
X			}
X			
X			/* Add new code to dictionary */
X			fcode = malloc(sizeof(*fcode));
X			fcode->num = nextfcode++;
X			fcode->name = strdup(token->text);
X			fadd(dictionary, fcode);
X			
X			if (state == 0)
X				emit("new-token");
X			else {
X				if (state == TOK_EXTERNAL)
X					emit("external-token");
X				else
X				/* Here we have a choice of new-token or named-token */
X					emit("named-token");
X				sspit(token->text);
X			}
X			spit(fcode->num);
X			emit("b(value)");
X			break;
X		case TOK_VARIABLE:
X			STATE(token->text, "TOK_VARIABLE");
X
X			token = yylex();
X			if (token == NULL) {
X				(void)printf( "EOF in variable definition\n");
X				return;
X			}
X			
X			/* Add new code to dictionary */
X			fcode = malloc(sizeof(*fcode));
X			fcode->num = nextfcode++;
X			fcode->name = strdup(token->text);
X			fadd(dictionary, fcode);
X			
X			if (state == 0)
X				emit("new-token");
X			else {
X				if (state == TOK_EXTERNAL)
X					emit("external-token");
X				else
X				/* Here we have a choice of new-token or named-token */
X					emit("named-token");
X				sspit(token->text);
X			}
X			spit(fcode->num);
X			emit("b(variable)");
X			break;
X		case TOK_VERSION1:
X			/* This is actually a tokenizer directive. */
X			STATE(token->text, "TOK_FCODE_VERSION2");
X			offsetsize = 8;
X			pos = outpos;
X			outpos = 0;
X			emit("version1");
X			outpos = pos;
X			break;
X		case TOK_WHILE:
X			STATE(token->text, "TOK_WHILE");
X			emit("b?branch");
X			push(outpos);
X			offspit(0);
X			break;
X
X			/* Tokenizer directives */
X		case TOK_BEGTOK:
X			STATE(token->text, "TOK_BEGTOK");
X			tokenizer = 1;
X			break;
X		case TOK_EMIT_BYTE:
X			STATE(token->text, "TOK_EMIT_BYTE");
X			spit(pop());
X			break;
X		case TOK_ENDTOK:
X			STATE(token->text, "TOK_ENDTOK");
X			tokenizer = 0;
X			break;
X		case TOK_FLOAD:
X			{
X				char *oldinfile = infile;
X
X				STATE(token->text, "TOK_FLOAD");
X				/* Parse a different file for a while */
X				token = yylex();
X				if ((inf = fopen(token->text, "r")) == NULL) {
X					(void)printf("%s: Could not "
X						"open %s: %s\n",
X						myname, token->text,
X						strerror(errno));
X					break;
X				}
X				infile = strdup(token->text);
X				if (mark_fload) {
X					/* 
X					 * Insert commands to print out the
X					 * filename into the instruction
X					 * stream
X					 */
X					emit("b(\")");
X					sspit("fload-ing ");
X					emit("type");
X					emit("b(\")");
X					sspit(infile);
X					emit("type");
X					emit("cr");
X					emit(".s");
X				}
X				inbuf = yy_create_buffer(inf, YY_BUF_SIZE);
X				yy_switch_to_buffer(inbuf);
X
X				printf("======= fload file %s\n", infile);
X				tokenize(inbuf);
X				printf("======= done file %s\n", infile);
X				yy_switch_to_buffer(input_buf);
X				yy_delete_buffer(inbuf);
X				fclose(inf);
X				if (mark_fload) {
X					/* 
X					 * Insert commands to print out the
X					 * filename into the instruction
X					 * stream
X					 */
X					emit("b(\")");
X					sspit("fload-ed ");
X					emit("type");
X					emit("b(\")");
X					sspit(infile);
X					emit("type");
X					emit("cr");
X					emit(".s");
X					emit("cr");
X				}
X				free(infile);
X				infile = oldinfile;
X			}
X			break;
X		case TOK_OTHER:
X			STATE(token->text, "TOK_OTHER");
X			if (apply_macros(input_buf, token->text))
X				break;
X			if (emit(token->text)) {
X#if 0
X				/*
X				 * Call an external command 
X				 *
X				 * XXXXX assumes it will always find the command
X				 */
X				sspit(token->text);
X				emit("$find");
X				emit("drop");
X				emit("execute");
X#else
X				printf("%s:%d: undefined token %s\n",
X					infile, yylineno, yytext);
X				exit(1);
X				token_err(yylineno, infile, yytext,
X					"%s: undefined token `%s'\n",
X					myname, token->text);
X				fflush(stderr);
X				exit(1);
X#endif
X			}
X			break;
X		default:
X			/* Nothing */ ;
X		}
X	}
X	return;
X}
X
X/*
X * print a tokenizer error message
X */
Xvoid
Xtoken_err(int lineno, char *infile, char *text, char *fmt, ...)
X{
X	va_list ap;
X
X	va_start(ap, fmt);
X	if (infile)
X		(void)fprintf(stderr, "%s:%d: ", infile, lineno);
X	if (fmt)
X		(void)vfprintf(stderr, fmt, ap);
X	fputc('\n', stderr);
X	if (text)
X		fprintf(stderr, "\t%s", text);
X	va_end(ap);
X	exit(1);
X}
X
X/*
X * Lookup fcode string in dictionary and spit it out.
X *
X * Fcode must be in dictionary.  No alias conversion done.
X */
Xint
Xemit(str)
X	char *str;
X{
X	struct fcode *code;
X	if ((code = flookup( dictionary, str)))
X		spit(code->num);
X	if (debug > 1) {
X		if (code)
X			(void)printf( "emitting `%s'\n", code->name);
X		else
X			(void)printf( "emit: not found `%s'\n", str);
X	}
X	return (code == NULL);
X}
X
X/*
X * Spit out an integral value as a series of FCodes.
X *
X * It will spit out one zero byte or as many bytes as are
X * non-zero.
X */
Xint
Xspit(n)
X	long n;
X{
X	int count = 1;
X
X	if (n >> 8)
X		count += spit(n >> 8);
X	if (outpos >= outbufsiz) {
X		while (outpos >= outbufsiz) outbufsiz += BUFCLICK;
X		if (!(outbuf = realloc(outbuf, outbufsiz))) {
X			(void)printf( "realloc of %ld bytes failed -- out of memory\n",
X				      (long)outbufsiz);
X			exit(1);
X		}
X	}
X	if (debug > 3) printf("%lx: spitting %2.2x\n", outpos, (unsigned char)n);
X	outbuf[outpos++] = n;
X	return (count);
X}
X
X/*
X * Spit out an FCode string.
X */
Xvoid
Xsspit(s)
X	char *s;
X{
X	int len = strlen(s);
X
X	if (len > 255) {
X		(void)printf( "string length %d too long\n", len);
X		return;
X	}
X	if (debug > 2)
X		(void)printf( "sspit: len %d str `%s'\n", len, s);
X	spit(len);
X	while (len--)
X		spit(*s++);
X}
X
X/*
X * Spit out an offset.  Offsets can be 8 or 16 bits.
X * Bail if the value overflows.  This is a little complicated since
X * offsets can be negative numbers.
X */
Xint
Xoffspit(n)
X	long n;
X{
X
X	if (offsetsize == 16) {
X		volatile int16_t off16 = n;
X
X		if (n != off16)
X			token_err(yylineno, infile, NULL,
X				"Offset16 offset overflow: %lx != %x\n",
X				n, off16);
X		spit((n>>8) & 0xff);
X		return spit(n & 0xff);
X	} else {
X		volatile int8_t off8 = n;
X
X		if (n != off8)
X			token_err(yylineno, infile, NULL,
X				"Offset8 offset overflow: %lx != %x\n",
X				n, off8);
X		return spit(n & 0x0ffL);
X	}
X}
X
Xint 
Xyywrap()
X{
X	/* Always generate EOF */
X	return (1);
X}
END-of-fgen.l
exit