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