Author: stepan
Date: 2006-08-18 14:47:12 +0200 (Fri, 18 Aug 2006)
New Revision: 76
Added:
fcode-utils/detok/addfcodes.c
fcode-utils/detok/addfcodes.h
fcode-utils/detok/pcihdr.c
fcode-utils/detok/printformats.c
fcode-utils/toke/clflags.c
fcode-utils/toke/clflags.h
fcode-utils/toke/conditl.c
fcode-utils/toke/conditl.h
fcode-utils/toke/devnode.c
fcode-utils/toke/devnode.h
fcode-utils/toke/errhandler.c
fcode-utils/toke/errhandler.h
fcode-utils/toke/flowcontrol.c
fcode-utils/toke/flowcontrol.h
fcode-utils/toke/macros.h
fcode-utils/toke/nextfcode.c
fcode-utils/toke/nextfcode.h
fcode-utils/toke/parselocals.c
fcode-utils/toke/parselocals.h
fcode-utils/toke/scanner.h
fcode-utils/toke/strsubvocab.c
fcode-utils/toke/strsubvocab.h
fcode-utils/toke/ticvocab.c
fcode-utils/toke/ticvocab.h
fcode-utils/toke/tokzesc.c
fcode-utils/toke/tokzesc.h
fcode-utils/toke/tracesyms.c
fcode-utils/toke/tracesyms.h
fcode-utils/toke/usersymbols.c
fcode-utils/toke/usersymbols.h
fcode-utils/toke/vocabfuncts.h
Removed:
fcode-utils/detok/Rules.make
fcode-utils/toke/Rules.make
Modified:
fcode-utils/detok/Makefile
fcode-utils/detok/decode.c
fcode-utils/detok/detok.c
fcode-utils/detok/detok.h
fcode-utils/detok/dictionary.c
fcode-utils/detok/stream.c
fcode-utils/detok/stream.h
fcode-utils/romheaders/Makefile
fcode-utils/romheaders/romheaders.c
fcode-utils/toke/Makefile
fcode-utils/toke/dictionary.c
fcode-utils/toke/dictionary.h
fcode-utils/toke/emit.c
fcode-utils/toke/emit.h
fcode-utils/toke/macros.c
fcode-utils/toke/scanner.c
fcode-utils/toke/stack.c
fcode-utils/toke/stack.h
fcode-utils/toke/stream.c
fcode-utils/toke/stream.h
fcode-utils/toke/toke.c
fcode-utils/toke/toke.h
Log:
initial merge of David Paktor's fine work.
I redid all of the Makefiles and fixed some minor
issues with the code.
Modified: fcode-utils/detok/Makefile
===================================================================
--- fcode-utils/detok/Makefile 2006-08-18 09:45:11 UTC (rev 75)
+++ fcode-utils/detok/Makefile 2006-08-18 12:47:12 UTC (rev 76)
@@ -1,11 +1,12 @@
#
-# OpenBIOS - free your system!
-# ( detokenizer )
-#
-# This program is part of a free implementation of the IEEE 1275-1994
+# OpenBIOS - free your system!
+# ( Utilities )
+#
+# This program is part of a free implementation of the IEEE 1275-1994
# Standard for Boot (Initialization Configuration) Firmware.
#
-# Copyright (C) 2001-2005 Stefan Reinauer, <stepan(a)openbios.org>
+# Copyright (C) 2001-2006 Stefan Reinauer <stepan(a)openbios.org>
+# Copyright (C) 2006 coresystems GmbH <info(a)coresystems.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -21,48 +22,37 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
#
-ARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/x86_64/amd64/ -e "s/Power Macintosh/ppc/")
-TOPDIR := $(shell /bin/pwd)
-BUILDDIR ?= $(TOPDIR)/obj-$(ARCH)
+PROGRAM = detok
-VPATH := $(BUILDDIR)
+CC = gcc
+STRIP = strip
+INCLUDES = -I../shared
+#CFLAGS = -O2 -g -Wall
+CFLAGS = -Os -Wall -Wno-pointer-sign
+LDFLAGS =
+OBJS = addfcodes.o decode.o detok.o dictionary.o pcihdr.o printformats.o \
+ stream.o ../shared/classcodes.o
-include $(TOPDIR)/Rules.make
+all: .dependencies $(PROGRAM)
+$(PROGRAM): $(OBJS)
+ $(CC) -o $(PROGRAM) $(OBJS) $(LDFLAGS)
+ $(STRIP) -s $(PROGRAM)
-CC = gcc
-CFLAGS = -O2 -Wall -ansi
+clean:
+ rm -f $(OBJS) *~
-# For debugging the indentation code of detok, define DEBUG_INDENT
-#CFLAGS := $(CFLAGS) -DDEBUG_INDENT
+distclean: clean
+ rm -f $(PROGRAM) .dependencies
+
+.dependencies: *.c
+ @$(CC) $(CFLAGS) $(INCLUDES) -MM *.c > .dependencies
-all: main detok
- @echo -e "\nOpenBIOS detokenizer detok build finished\n"
+.PHONY: all clean distclean
-main:
- @echo -e "\nWelcome to the OpenBIOS detokenizer.."
- @test -r $(BUILDDIR) || ( mkdir -p $(BUILDDIR); \
- echo -e "\nCreating build directory $(BUILDDIR)" )
-
-detok: detok.o dictionary.o decode.o stream.o
- @echo -en "\nLinking fcode detokenizer detok..."
- @cd $(BUILDDIR) && ( $(CC) $(CFLAGS) $^ -o $@; strip detok )
- @echo -e "\tok"
-
-clean:
- @test ! -d $(BUILDDIR) && \
- echo "Architecture $(ARCH) is already clean." || \
- ( \
- echo "Cleaning up architecture $(ARCH)"; \
- rm -rf $(BUILDDIR) \
- rm forth.dict.core \
- )
+-include .dependencies
-distclean: clean
- rm -f detok
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCLUDES) $< -o $@
-detok.o: detok.h stream.h detok.c
-stream.o: detok.h stream.c
-decode.o: detok.h stream.h decode.c Makefile
-dictionary.o: detok.h dictionary.c
Deleted: fcode-utils/detok/Rules.make
===================================================================
--- fcode-utils/detok/Rules.make 2006-08-18 09:45:11 UTC (rev 75)
+++ fcode-utils/detok/Rules.make 2006-08-18 12:47:12 UTC (rev 76)
@@ -1,17 +0,0 @@
-# tag: Makefile rules
-
-VPATH := $(VPATH):.
-
-.S.o:
- echo -n " assembling $<... "
- $(CC) -c -nostdlib $(INCLUDES) $(CFLAGS) $< -o $(BUILDDIR)/$@ && \
- echo -e " \t\tok" || \
- echo -e " \t\tfailed"
-
-.c.o:
- @echo -n " compiling $<... "
- @$(CC) -c $(CFLAGS) $(INCLUDES) $< -o $(BUILDDIR)/$@ && \
- echo -e " \t\tok" || \
- echo -e " \t\failed"
-
-
Added: fcode-utils/detok/addfcodes.c
===================================================================
--- fcode-utils/detok/addfcodes.c (rev 0)
+++ fcode-utils/detok/addfcodes.c 2006-08-18 12:47:12 UTC (rev 76)
@@ -0,0 +1,343 @@
+/*
+ * OpenBIOS - free your system!
+ * ( FCode tokenizer )
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 2001-2005 Stefan Reinauer, <stepan(a)openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+/* **************************************************************************
+ *
+ * Function(s) for entering Vendor-Specific FCodes to detokenizer.
+ *
+ * (C) Copyright 2006 IBM Corporation. All Rights Reserved.
+ * Module Author: David L. Paktor dlpaktor(a)us.ibm.com
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Functions Exported:
+ * add_fcodes_from_list Add Vendor-Specific FCodes from
+ * the file whose name is supplied.
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Revision History:
+ * Tue, 25 Apr 2006 by David L. Paktor
+ * Identified this need when working with in-house code,
+ * which uses some custom functions. This solution
+ * is (hoped to be) general enough to cover all cases.
+ *
+ **************************************************************************** */
+
+
+/* **************************************************************************
+ *
+ * Global Variables Imported
+ * indata Buffer into which the file will be read
+ * stream_max Size of the file buffer.
+ *
+ **************************************************************************** */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "detok.h"
+#include "stream.h"
+#include "addfcodes.h"
+
+/* **************************************************************************
+ *
+ * Internal Static Variables
+ * current_vfc_line Line to be scanned in Vendor-FCodes buffer
+ * vfc_remainder Remainder of Vendor-FCodes buffer to be scanned
+ * vfc_line_no Number of current line in Vendor-FCodes buffer
+ * vfc_buf_end Pointer to end of Vendor-FCodes buffer
+ *
+ **************************************************************************** */
+
+static char *current_vfc_line;
+static char *vfc_remainder;
+static int vfc_line_no = 0;
+static char *vfc_buf_end;
+
+/* **************************************************************************
+ *
+ * Function name: skip_whitespace
+ * Synopsis: Advance the given string-pointer past blanks and tabs.
+ * (String is presumed to end before new-line)
+ *
+ * Inputs:
+ * Parameters:
+ * string_line_ptr Address of pointer to string
+ *
+ * Outputs:
+ * Returned Value: None
+ * *string_line_ptr Advanced past blanks and tabs
+ *
+ **************************************************************************** */
+
+static void skip_whitespace( char **string_line_ptr)
+{
+ char *cur_char_ptr = *string_line_ptr;
+ for ( ; *cur_char_ptr != 0 ; cur_char_ptr++ )
+ {
+ if ( (*cur_char_ptr != '\t') && (*cur_char_ptr != ' ') )
+ {
+ *string_line_ptr = cur_char_ptr;
+ break;
+ }
+ }
+}
+
+/* **************************************************************************
+ *
+ * Function name: get_next_vfc_line
+ * Synopsis: Advance to the next vfc_line to be processed.
+ * Skip blanks and comments. Indicate when end reached.
+ *
+ * Inputs:
+ * Parameters: None
+ * Local Static Variables:
+ * vfc_remainder
+ * vfc_buf_end
+ *
+ * Outputs:
+ * Returned Value: FALSE if reached end of buffer
+ * Local Static Variables:
+ * current_vfc_line Advanced to next line to be scanned
+ * vfc_line_no Kept in sync with line number in file
+ *
+ * Process Explanation:
+ * Comments begin with a pound-sign ('#') or a backslash ('\')
+ * Comment-lines or blank or empty lines will be skipped.
+ *
+ **************************************************************************** */
+
+static bool get_next_vfc_line( void )
+{
+ bool retval = FALSE; /* TRUE = not at end yet */
+ while ( vfc_remainder < vfc_buf_end )
+ {
+ current_vfc_line = vfc_remainder;
+ vfc_remainder = strchr( current_vfc_line, '\n');
+ *vfc_remainder = 0;
+ vfc_remainder++;
+ vfc_line_no++;
+ skip_whitespace( ¤t_vfc_line);
+ if ( *current_vfc_line == 0 ) continue; /* Blank line */
+ if ( *current_vfc_line == '#' ) continue; /* Comment */
+ if ( *current_vfc_line == '\\' ) continue; /* Comment */
+ retval = TRUE;
+ break; /* Found something */
+ }
+ return( retval);
+}
+
+/* **************************************************************************
+ *
+ * Function name: vfc_splash
+ * Synopsis: Print a "splash" message to show that we
+ * are processing Vendor-Specific FCodes,
+ * but only once.
+ *
+ * Inputs:
+ * Parameters:
+ * vf_file_name Vendor-Specific FCodes file name
+ * Local Static Variables:
+ * did_not_splash Control printing; once only.
+ *
+ * Outputs:
+ * Returned Value: None
+ * Local Static Variables:
+ * did_not_splash FALSE after first call.
+ * Printout:
+ * "Splash" message...
+ *
+ **************************************************************************** */
+static bool did_not_splash = TRUE;
+static void vfc_splash( char *vf_file_name)
+{
+ if ( did_not_splash )
+ {
+ /* Temporary substring buffer */
+ /* Guarantee that the malloc will be big enough. */
+ char *strbfr = malloc( strlen( vf_file_name) +65 ) ;
+ sprintf( strbfr,
+ "Reading additional FCodes from file: %s\n",
+ vf_file_name);
+ printremark( strbfr);
+ free( strbfr);
+ did_not_splash = FALSE;
+ }
+}
+
+/* **************************************************************************
+ *
+ * Function name: add_fcodes_from_list
+ * Synopsis: Add Vendor-Specific FCodes from the named file
+ * to the permanent resident dictionary.
+ *
+ * Inputs:
+ * Parameters:
+ * vf_file_name Vendor-Specific FCodes file name
+ * Global Variables:
+ * verbose "Verbose" flag.
+ * indata Start of file buffer
+ * stream_max Size of the file buffer.
+ *
+ * Outputs:
+ * Returned Value: TRUE if FCodes have actually been added
+ * Global Variables:
+ * check_tok_seq Cleared to FALSE, then restored to TRUE
+ * Local Static Variables:
+ * vfc_remainder Initted to start of file buffer
+ * vfc_buf_end Initted to end of file buffer
+ * Memory Allocated
+ * Permanent copy of FCode Name
+ * When Freed?
+ * Never. Rmeains until program termination.
+ * Printout:
+ * If verbose, "Splash" line and count of added entries.
+ *
+ * Error Detection:
+ * Fail to open or read Vendor-FCodes file -- Exit program
+ * Improperly formatted input line -- print message and ignore
+ * FCode value out of valid range -- print message and ignore
+ * FCode value already in use -- print message and ignore
+ *
+ * Process Explanation:
+ * Valid lines are formatted with the FCode number first
+ * and the name after, one entry per line. Extra text
+ * after the name will be ignored, so an extra "comment"
+ * is permitted. The FCode number must be in hex, with
+ * an optional leading 0x or 0X For example: 0X407
+ * The valid range is 0x010 to 0x7ff. Numbers above 0x800
+ * infringe upon the are reserved for FCodes generated
+ * by the tokenization process.
+ * Numbers already in use will be ignored. A Message will be
+ * printed even if the name matches the one on the line.
+ *
+ **************************************************************************** */
+
+bool add_fcodes_from_list( char *vf_file_name)
+{
+ bool retval = FALSE;
+ int added_fc_count = 0;
+ check_tok_seq = FALSE;
+
+ if ( verbose ) vfc_splash( vf_file_name);
+
+ if ( init_stream( vf_file_name) != 0 )
+ {
+ char *strbfr = malloc( strlen( vf_file_name) +65 );
+ sprintf( strbfr,
+ "Could not open Additional FCodes file: %s\n",
+ vf_file_name);
+ printremark( strbfr);
+ free( strbfr);
+ exit(1);
+ }
+ vfc_remainder = indata;
+ vfc_buf_end = indata + stream_max -1;
+
+ while ( get_next_vfc_line() )
+ {
+ char vs_fc_name[36];
+ int vs_fc_number;
+ int scan_result;
+ char *lookup_result;
+ char *fc_name_cpy;
+
+ scan_result = sscanf( current_vfc_line, "0x%x %32s",
+ &vs_fc_number, vs_fc_name);
+
+ if ( scan_result != 2 ) /* Allow a capital 0X */
+ {
+ scan_result = sscanf( current_vfc_line, "0X%x %32s",
+ &vs_fc_number, vs_fc_name);
+ }
+ if ( scan_result != 2 ) /* Try it without the 0x */
+ {
+ scan_result = sscanf( current_vfc_line, "%x %32s",
+ &vs_fc_number, vs_fc_name);
+ }
+
+ if ( scan_result != 2 ) /* That's it... */
+ {
+ char *strbfr = malloc( strlen( current_vfc_line) +65 );
+ vfc_splash( vf_file_name);
+ sprintf( strbfr,
+ "Line #%d, invalid format. Ignoring: %s\n",
+ vfc_line_no, current_vfc_line);
+ printremark( strbfr);
+ free( strbfr);
+ continue;
+ }
+
+ if ( ( vs_fc_number < 0x10 ) || ( vs_fc_number > 0x7ff ) )
+ {
+ char *strbfr = malloc( 85 );
+ vfc_splash( vf_file_name);
+ sprintf( strbfr,
+ "Line #%d, FCode number out of range: 0x%x Ignoring.\n",
+ vfc_line_no, vs_fc_number);
+ printremark( strbfr);
+ free( strbfr);
+ continue;
+ }
+
+ lookup_result = lookup_token( (u16)vs_fc_number);
+ if ( strcmp( lookup_result, "ferror") != 0 )
+ {
+ char *strbfr = malloc( strlen( lookup_result) + 85 );
+ vfc_splash( vf_file_name);
+ sprintf( strbfr,
+ "Line #%d. FCode number 0x%x is already "
+ "defined as %s Ignoring.\n",
+ vfc_line_no, vs_fc_number, lookup_result);
+ printremark( strbfr);
+ free( strbfr);
+ continue;
+ }
+
+ /* We've passed all the tests! */
+ fc_name_cpy = strdup( vs_fc_name);
+ add_token( (u16)vs_fc_number, fc_name_cpy);
+ added_fc_count++;
+ retval = TRUE;
+ }
+
+ if ( verbose )
+ {
+ char *strbfr = malloc( 85 );
+ sprintf( strbfr,
+ "Added %d FCode numbers\n", added_fc_count);
+ printremark( strbfr);
+ free( strbfr);
+ }
+
+ close_stream();
+ check_tok_seq = TRUE;
+ return( retval);
+}
Added: fcode-utils/detok/addfcodes.h
===================================================================
--- fcode-utils/detok/addfcodes.h (rev 0)
+++ fcode-utils/detok/addfcodes.h 2006-08-18 12:47:12 UTC (rev 76)
@@ -0,0 +1,48 @@
+#ifndef _DETOK_VSFCODES_H
+#define _DETOK_VSFCODES_H
+
+/*
+ * OpenBIOS - free your system!
+ * ( FCode tokenizer )
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 2001-2005 Stefan Reinauer, <stepan(a)openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+/* **************************************************************************
+ *
+ * Header for function for entering Vendor-Specific FCodes
+ * to detokenizer.
+ *
+ * (C) Copyright 2006 IBM Corporation. All Rights Reserved.
+ * Module Author: David L. Paktor dlpaktor(a)us.ibm.com
+ *
+ **************************************************************************** */
+
+#include "types.h"
+
+/* ************************************************************************** *
+ *
+ * Function Prototypes / Functions Exported:
+ *
+ **************************************************************************** */
+
+bool add_fcodes_from_list( char *vf_file_name);
+
+#endif /* _DETOK_VSFCODES_H */
Modified: fcode-utils/detok/decode.c
===================================================================
--- fcode-utils/detok/decode.c 2006-08-18 09:45:11 UTC (rev 75)
+++ fcode-utils/detok/decode.c 2006-08-18 12:47:12 UTC (rev 76)
@@ -24,96 +24,322 @@
*
*/
+/* **************************************************************************
+ * Modifications made in 2005 by IBM Corporation
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Modifications Author: David L. Paktor dlpaktor(a)us.ibm.com
+ **************************************************************************** */
+
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <ctype.h>
+#include <setjmp.h>
#include "detok.h"
#include "stream.h"
-/* Dictionary function prototypes */
-char *lookup_token(u16 number);
-int add_token(u16 number, char *name);
+static int indent; /* Current level of indentation */
-extern u16 fcode;
+/* **************************************************************************
+ *
+ * Still to be done:
+ * Handling of indent-level is not correct. Branches should
+ * balance with their resolvers; constructs like do..loop
+ * case/of/endof/endcase are a few major examples.
+ * This will be tricky; the rules need to be carefully thought
+ * out, and the implementation might be more complex than
+ * at first meets the eye...
+ *
+ **************************************************************************** */
+static bool ended_okay = TRUE; /* FALSE if finished prematurely */
+
bool offs16=TRUE;
-int indent, verbose=0, decode_all=0, linenumbers=0, linenum;
-u32 fclen;
+unsigned int linenum;
+bool end_found=FALSE;
+unsigned int token_streampos; /* Streampos() of currently-gotten token */
+u16 last_defined_token = 0;
-static u8 *unnamed=(u8 *)"(unnamed-fcode)";
+jmp_buf eof_exception;
-void pretty_string(u8 *string)
+static int fclen;
+static const char *unnamed = "(unnamed-fcode)" ;
+
+static void decode_indent(void)
{
- u8 c;
- unsigned int i;
- bool qopen=TRUE;
+ int i;
+ if (indent<0) {
+#ifdef DEBUG_INDENT
+ printf("detok: error in indentation code.\n");
+#endif
+ indent=0;
+ }
+ for (i=0; i<indent; i++)
+ printf (" ");
+}
+/* Print forth string ( [len] char[0] ... char[len] ) */
+static void pretty_print_string(void)
+{
+ u8 len;
+ u8 *strptr;
+ int indx;
+ bool in_parens = FALSE ; /* Are we already inside parentheses? */
+
+ strptr = get_string( &len );
+
+ printf("( len=%s%x", len >= 10 ? "0x":"", len);
+ if ( len >= 10 ) printf(" [%d bytes]", len);
+ printf(" )\n");
+ if (show_linenumbers) printf(" ");
+ decode_indent();
printf("\" ");
- for (i=1; i<1+(unsigned int)string[0]; i++) {
- c=string[i];
+ for ( indx = 0; indx < len; indx++ )
+ {
+ u8 c = *strptr++;
if (isprint(c)) {
- if (!qopen) {
+ if ( in_parens )
+ {
printf(" )");
- qopen=TRUE;
+ in_parens = FALSE;
}
printf("%c",c);
+ /* Quote-mark must escape itself */
+ if ( c == '"' ) printf("%c",c);
} else {
- if (qopen) {
+ if ( !in_parens )
+ {
printf("\"(");
- qopen=FALSE;
+ in_parens = TRUE;
}
printf(" %02x",c);
}
}
- if (!qopen)
+ if ( in_parens )
printf(" )");
printf("\"");
}
-static void decode_indent(void)
+static void decode_lines(void)
{
- int i;
-#ifdef DEBUG_INDENT
- if (indent<0) {
- printf("detok: error in indentation code.\n");
- indent=0;
+ if (show_linenumbers) {
+ printf("%6d: ",show_offsets ? token_streampos : linenum++);
}
-#endif
- for (i=0; i<indent; i++)
- printf (" ");
}
-static void decode_lines(void)
+/* **************************************************************************
+ *
+ * Function name: output_token_name
+ * Synopsis: Print the name of the token just retrieved
+ * along with any interesting related information...
+ *
+ * Inputs:
+ * Global/Static Variables:
+ * fcode The token # just retrieved
+ * last_defined_token Used to screen invalid tokens.
+ * token_streampos Location of token just retrieved
+ * Global/Static Constants:
+ * unnamed Namefield of headerless token
+ *
+ * Outputs:
+ * Printout:
+ * Print the function name (if known) and the FCode number,
+ * if interesting.
+ * The fcode number is interesting if either
+ * a) the token has no name
+ * or
+ * b) verbose mode is in effect.
+ * If the token is named, show its FCode number in
+ * the syntax of a FORTH Comment, otherwise, its
+ * FCode number -- in [brackets] -- acts as its name.
+ *
+ * Error Detection:
+ * If the token # is larger than the last defined token, it is
+ * probably an artifact of an error that was allowed in the
+ * tokenization; if it were treated normally, it would lead
+ * to a cascade of failures. Print a message, skip the first
+ * byte, and return.
+ *
+ * Revision History:
+ * Refactored. The line number or offset (if selected) and the
+ * indent are printed in the output_token() routine, which
+ * calls this one.
+ * Add Error Detection
+ *
+ *
+ **************************************************************************** */
+
+static void output_token_name(void)
{
- if (linenumbers) {
- printf("%6d: ",linenumbers==1?linenum:get_streampos());
- linenum++;
+ char *tname;
+
+ /* Run error detection only if last_defined_token was assigned */
+ if ( (fcode > last_defined_token) && (last_defined_token > 0) )
+ {
+ char temp_buf[80];
+ int buf_pos;
+ u8 top_byte = fcode >> 8;
+ printf ("Invalid token: [0x%03x]\n", fcode);
+ sprintf(temp_buf, "Backing up over first byte, which is ");
+ buf_pos = strlen(temp_buf);
+ if ( top_byte < 10 )
+ {
+ sprintf(&temp_buf[buf_pos], " %02x", top_byte);
+ }else{
+ sprintf( &temp_buf[buf_pos], "0x%02x ( =dec %d)",
+ top_byte, top_byte);
}
+ printremark(temp_buf);
+ set_streampos(token_streampos+1);
+ return;
}
-static void output_token(void)
-{
- u8 *tname=lookup_token(fcode);
+ tname = lookup_token(fcode);
printf ("%s ", tname);
- /* The fcode number is interesting if
- * a) detok is in verbose mode
- * b) the token has no name.
+ /* The fcode number is interesting
+ * if either
+ * a) the token has no name
+ * or
+ * b) detok is in verbose mode.
*/
- if (verbose || tname == unnamed)
+ if ( tname == unnamed )
+ {
printf("[0x%03x] ", fcode);
+ } else {
+ if ( verbose )
+ {
+ /* If the token is named,
+ * show its fcode number in
+ * the syntax of a FORTH Comment
+ */
+ printf("( 0x%03x ) ", fcode);
+ }
+ }
}
+/* **************************************************************************
+ *
+ * Function name: output_token
+ * Synopsis: Print the full line for the token just retrieved:
+ * line number, indentation and name.
+ *
+ * Revision History:
+ * Updated Mon, 11 Jul 2005 by David L. Paktor
+ * Separate out output_token_name() for specific uses.
+ * Incorporate calls to decode_lines() and decode_indent()
+ * to allow better control of indentation.
+ *
+ **************************************************************************** */
+
+static void output_token(void)
+{
+ decode_lines();
+ decode_indent();
+ output_token_name();
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: decode_offset
+ * Synopsis: Gather and display an FCode-offset associated with
+ * a branch or suchlike function.
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global/Static Variables:
+ * show_offsets Whether to show offsets in full detail
+ * offs16 Whether 16- (or 8-) -bit offsets
+ * stream_max Maximum valid destimation
+ * Local Static Variables:
+ *
+ * Outputs:
+ * Returned Value: The offset, converted to signed 16-bit #
+ * Global/Static Variables:
+ * stream-position Reset if invalid destination; otherwise,
+ * advanced in the normal manner.
+ * Printout:
+ * The offset and destination, if display of offsets was specified
+ * or if the destination is invalid
+ *
+ * Error Detection:
+ * Crude and rudimentary:
+ * If the target-destination is outside the theoretical limits,
+ * it's obviously wrong.
+ * Notification remark is printed and the stream-position reset
+ * to the location of the offset, to allow it to be processed
+ * in the manner of normal tokens.
+ * If the offset is zero, that's obviously wrong, but don't reset
+ * the stream-position: zero gets processed as end0 and that
+ * is also wrong...
+ *
+ * Still to be done:
+ * More sophisticated error-checking for invalid offsets. Look
+ * at the type of branch, and what should be expected in the
+ * vicinity of the destination. (This might be best served
+ * by a separate routine).
+ * This might also help with handling the indent-level correctly...
+ * Also, if indentation were to be handled in this routine,
+ * there would be no need to return the value of the offset.
+ *
+ **************************************************************************** */
+
static s16 decode_offset(void)
{
s16 offs;
+ int dest;
+ bool invalid_dest;
+ int streampos = get_streampos();
+ output_token();
offs=get_offset();
- output_token();
- printf("0x%x\n",offs);
+
+ /* The target-destination is the source-byte offset
+ * at which the FCode-offset is found, plus
+ * the FCode-offset.
+ */
+ dest = streampos + offs;
+
+ /* A destination of zero is invalid because there must be a
+ * token -- such as b(<mark) or b(do) -- preceding
+ * the target of a backward branch.
+ * A destination at the end of the stream is unlikely but
+ * theoretically possible, so we'll treat it as valid.
+ * An offset of zero is also, of course, invalid.
+ */
+ invalid_dest = BOOLVAL ( (dest <= 0)
+ || (dest > stream_max)
+ || (offs == 0) );
+
+ /* Show the offset in hex and again as a signed decimal number. */
+ if ( offs16 )
+ {
+ printf("0x%04x (", (u16)(offs & 0xffff) );
+ }else{
+ printf("0x%02x (", (u8)(offs & 0x00ff) );
+ }
+ if ( (offs < 0) || (offs > 9) ) printf(" =dec %d", offs);
+ /* If we're showing source-byte offsets, show targets of offsets */
+ if ( show_offsets || invalid_dest )
+ {
+ printf(" dest = %d ",dest);
+ }
+ printf(")\n");
+
+ if ( invalid_dest )
+ {
+ if (offs == 0)
+ {
+ printremark("Error: Unresolved offset.");
+ }else{
+ printremark("Error: Invalid offset. Ignoring...");
+ set_streampos( streampos);
+ }
+ }
return offs;
}
@@ -127,59 +353,39 @@
{
u16 token;
output_token();
- token=get_token();
+ token = next_token();
printf("0x%03x\n",token);
- add_token(token, unnamed);
+ add_token(token, (char *)unnamed);
}
static void named_token(void)
{
u16 token;
+ u8 len;
u8* string;
output_token();
/* get forth string ( [len] [char0] ... [charn] ) */
- string=get_string();
- token=get_token();
-
- printf("%s 0x%03x\n", string+1, token);
-
- add_token(token,string+1);
+ string=get_name(&len);
+ token = next_token();
+ printf("%s 0x%03x\n", string, token);
+ add_token(token,string);
}
-static void external_token(void)
+static void bquote(void)
{
- u16 token;
- u8* string;
-
output_token();
/* get forth string ( [len] [char0] ... [charn] ) */
- string=get_string();
- token=get_token();
-
- printf("%s 0x%03x\n", string+1, token);
-
- add_token(token,string+1);
-}
-
-static void bquote(void)
-{
- u8 *string;
-
- /* get forth string ( [len] [char0] ... [charn] ) */
- string=get_string();
- output_token();
- pretty_string(string);
+ pretty_print_string();
printf("\n");
- free(string);
}
static void blit(void)
{
u32 lit;
+ output_token();
lit=get_num32();
- output_token();
printf("0x%x\n",lit);
}
@@ -204,56 +410,81 @@
u16 token;
output_token();
- token=get_token();
- decode_default();
+ token = next_token();
+ output_token_name();
+ printf ("\n");
}
+/* **************************************************************************
+ *
+ * Function name: decode_start
+ * Synopsis: Display the (known valid) FCode block Header
+ *
+ * Outputs:
+ * Global/Static Variables:
+ * fclen Length of the FCode block as shown in its Header
+ *
+ **************************************************************************** */
+
static void decode_start(void)
{
u8 fcformat;
u16 fcchecksum, checksum=0;
- long pos;
- u32 i;
- decode_default();
+ output_token();
+ printf(" ( %d-bit offsets)\n", offs16 ? 16 : 8 );
+ token_streampos = get_streampos();
decode_lines();
fcformat=get_num8();
printf(" format: 0x%02x\n", fcformat);
- decode_lines();
- fcchecksum=get_num16();
- /* missing: check for checksum correctness. */
-
- fclen=get_num32(); /* skip len */
- pos=get_streampos();
- for (i=0; i<fclen-pos; i++)
- checksum+=get_num8();
+ /* Check for checksum correctness. */
- set_streampos(pos-4);
+ token_streampos = get_streampos();
+ decode_lines();
+ fcchecksum=get_num16(); /* Read the stored checksum */
+ checksum = calc_checksum(); /* Calculate the actual checksum */
- printf(" checksum: 0x%04x (%sOk)\n", fcchecksum,
- fcchecksum==checksum?"":"not ");
+ if ( fcchecksum==checksum )
+ {
+ printf(" checksum: 0x%04x (Ok)\n", fcchecksum);
+ } else {
+ printf(" checksum should be: 0x%04x, but is 0x%04x\n",
+ checksum,fcchecksum);
+ }
+ token_streampos = get_streampos();
decode_lines();
fclen=get_num32();
- printf(" len: 0x%x (%d bytes)\n", fclen, fclen);
+ printf(" len: 0x%04x ( %d bytes)\n", fclen, fclen);
}
-void decode_token(u16 token)
+/* **************************************************************************
+ *
+ * Function name: decode_token
+ * Synopsis: Display detokenization for one token.
+ * Handle complicated cases and dispatch simple ones.
+ *
+ * Revision History:
+ * Detect FCode-Starters in the middle of an FCode block.
+ * Some tuning of adjustment of indent, particularly wrt branches...
+ *
+ **************************************************************************** */
+
+static void decode_token(u16 token)
{
+ bool handy_flag = TRUE;
switch (token) {
case 0x0b5:
new_token();
break;
- case 0x0b6:
+ case 0x0b6: /* Named Token */
+ case 0x0ca: /* External Token */
named_token();
break;
- case 0x0ca:
- external_token();
- break;
case 0x012:
bquote();
break;
@@ -276,14 +507,14 @@
case 0x0c2: /* b(;) */
case 0x0b2: /* b(>resolve) */
case 0x0c5: /* b(endcase) */
+ indent--;
decode_default();
- indent--;
break;
case 0x015: /* b(loop) */
case 0x016: /* b(+loop) */
case 0x0c6: /* b(endof) */
+ indent--;
decode_offset();
- indent--;
break;
case 0x017: /* b(do) */
case 0x018: /* b/?do) */
@@ -295,38 +526,274 @@
case 0x0c3: /* b(to) */
decode_two();
break;
+ case 0x0fd: /* version1 */
+ handy_flag = FALSE;
case 0x0f0: /* start0 */
case 0x0f1: /* start1 */
case 0x0f2: /* start2 */
case 0x0f3: /* start4 */
+ offs16 = handy_flag;
+ printremark("Unexpected FCode-Block Starter.");
decode_start();
+ printremark(" Ignoring length field.");
break;
+ case 0: /* end0 */
+ case 0xff: /* end1 */
+ end_found=TRUE;
+ decode_default();
+ break;
+ default:
+ decode_default();
+ }
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: decode_fcode_header
+ * Synopsis: Detokenize the FCode Header.
+ * Check for file corruption
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global/Static Variables:
+ * stream_max Length of input stream
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global/Static Variables:
+ * offs16 FALSE if Starter was version1, else TRUE
+ * fclen On error, gets set to reach end of input stream
+ * Otherwise, gets set by decode_start()
+ * Printout:
+ *
+ * Error Detection:
+ * First byte not a valid FCode Start: Print message, restore
+ * input pointer to initial value, set fclen to [(end of
+ * input stream) - (input pointer)], return FALSE.
+ *
+ * Process Explanation:
+ * This routine error-checks and dispatches to the routine that
+ * does the actual printing.
+ * Refrain from showing offset until correctness of starter-byte
+ * has been confirmed.
+ *
+ **************************************************************************** */
+
+static void decode_fcode_header(void)
+{
+ long err_pos;
+ u16 token;
+
+ err_pos = get_streampos();
+ indent = 0;
+ token = next_token();
+ offs16=TRUE;
+ switch (token)
+ {
case 0x0fd: /* version1 */
- decode_start();
offs16=FALSE;
+ case 0x0f0: /* start0 */
+ case 0x0f1: /* start1 */
+ case 0x0f2: /* start2 */
+ case 0x0f3: /* start4 */
+ decode_start();
break;
default:
- decode_default();
+ {
+ char temp_bufr[128] =
+ "Invalid FCode Start Byte. Ignoring FCode header." ;
+ set_streampos( err_pos );
+ fclen = max - pc;
+ printf("\n");
+ if (show_linenumbers)
+ {
+ sprintf( &(temp_bufr[strlen(temp_bufr)]),
+ " Remaining len = 0x%04x ( %d bytes)", fclen, fclen);
+ }
+ printremark( temp_bufr );
}
}
+}
-int detokenize(void)
+/* **************************************************************************
+ *
+ * Function name: decode_fcode_block
+ * Synopsis: Detokenize one FCode block.
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global/Static Variables:
+ * fclen Length of the FCode block as shown in its Header
+ * end_found Whether the END0 code was seen
+ * decode_all TRUE = continue even after END0
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global/Static Variables:
+ * end_found Whether the END0 code was seen
+ * Printout:
+ * A summary message at the end of FCode detokenization
+ *
+ * Error Detection:
+ * If the end of the FCode block, as calculated by its FCode length,
+ * was reached without encountering END0, print a message.
+ * Detect END0 that occurs before end of FCode block,
+ * even if decode_all is in effect.
+ *
+ * Process Explanation:
+ * This routine dispatches to the routines that do the actual
+ * printing of the detokenization.
+ * The end_found flag is not a direct input, but more of an
+ * intermediate input, so to speak... Clear it at the start.
+ * Detection of FCode-Starters in the middle of an FCode block
+ * is handled by decode_token() routine.
+ *
+ **************************************************************************** */
+
+static void decode_fcode_block(void)
{
u16 token;
+ unsigned int fc_block_start;
+ unsigned int fc_block_end;
- if (linenumbers)
- linenum=1;
+ end_found = FALSE;
+ fc_block_start = get_streampos();
- do {
- decode_lines();
- decode_indent();
- token=get_token();
+ decode_fcode_header();
+
+ fc_block_end = fc_block_start + fclen;
+
+ while ( ( !end_found || decode_all )
+ && ( get_streampos() < fc_block_end ) )
+ {
+ token = next_token();
decode_token(token);
- } while ((token||decode_all) && ((get_streampos()-1)<=fclen));
+ }
+ if ( !end_found )
+ {
+ printremark("FCode-ender not found");
+ }
+ {
+ char temp_bufr[80];
+ /* Don't use fclen here, in case it got corrupted
+ * by an "Unexpected FCode-Block Starter"
+ */
+ if ( get_streampos() == fc_block_end )
+ {
+ sprintf( temp_bufr,
+ "Detokenization finished normally after %d bytes.",
+ fc_block_end - fc_block_start );
+ }else{
+ sprintf( temp_bufr,
+ "Detokenization finished prematurely after %d of %d bytes.",
+ get_streampos() - fc_block_start,
+ fc_block_end - fc_block_start );
+ ended_okay = FALSE;
+ }
+ printremark( temp_bufr );
+ }
+}
- decode_lines();
- printf ("\\ detokenizing finished after %d of %d bytes.\n",
- get_streampos(), fclen );
+/* **************************************************************************
+ *
+ * Function name: another_fcode_block
+ * Synopsis: Indicate whether there is a follow-on FCode block
+ * within the current PCI image.
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global/Static Variables:
+ * token_streampos Streampos() of token just gotten
+ * Next token in Input Stream
+ *
+ * Outputs:
+ * Returned Value: TRUE if next token shows the start
+ * of a valid FCode-block
+ * Printout:
+ * Message if there is a follow-on FCode block
+ *
+ * Error Detection:
+ * If next token is neither a valid FCode-block starter nor the
+ * start of a zero-fill field, print a message.
+ *
+ * Process Explanation:
+ * Extract the next token from the Input Stream but do not
+ * consume it. Then examine the token.
+ *
+ **************************************************************************** */
- return 0;
+static bool another_fcode_block(void)
+{
+ bool retval = FALSE;
+ u16 token;
+
+ token = next_token();
+ set_streampos( token_streampos );
+
+ switch (token)
+ {
+ case 0x0fd: /* version1 */
+ case 0x0f0: /* start0 */
+ case 0x0f1: /* start1 */
+ case 0x0f2: /* start2 */
+ case 0x0f3: /* start4 */
+ retval = TRUE;
+ printremark("Subsequent FCode Block detected. Detokenizing.");
+ break;
+ case 0: /* Start of a zero-fill field */
+ /* retval already = FALSE . Nothing else to be done. */
+ break;
+ default:
+ {
+ char temp_bufr[80];
+ sprintf( temp_bufr,
+ "Unexpected token, 0x%02x, after end of FCode block.",
+ token);
+ printremark( temp_bufr);
+ }
+ }
+ return ( retval );
}
+
+/* **************************************************************************
+ *
+ * Function name: detokenize
+ * Synopsis: Detokenize one input file
+ *
+ *
+ *
+ **************************************************************************** */
+
+void detokenize(void)
+{
+ fclen = stream_max;
+
+ if ( setjmp(eof_exception) == 0 )
+ {
+ while ( more_to_go() )
+ {
+ if ( ended_okay )
+ {
+ init_fcode_block();
+ }
+ ended_okay = TRUE;
+
+ adjust_for_pci_header();
+
+ /* Allow for multiple FCode Blocks within the PCI image.
+ * The first one had better be a valid block, but the
+ * next may or may not be...
+ */
+ do
+ {
+ decode_fcode_block();
+ } while ( another_fcode_block() );
+
+ adjust_for_pci_filler();
+
+ }
+ }
+
+
+}
Modified: fcode-utils/detok/detok.c
===================================================================
--- fcode-utils/detok/detok.c 2006-08-18 09:45:11 UTC (rev 75)
+++ fcode-utils/detok/detok.c 2006-08-18 12:47:12 UTC (rev 76)
@@ -24,58 +24,76 @@
*
*/
+/* **************************************************************************
+ * Modifications made in 2005 by IBM Corporation
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Modifications Author: David L. Paktor dlpaktor(a)us.ibm.com
+ **************************************************************************** */
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+
#ifdef __GLIBC__
#define _GNU_SOURCE
#include <getopt.h>
-#else
-/* Some systems seem to have an incomplete unistd.h.
- * We need to define getopt() and optind for them.
- */
-extern int optind;
-int getopt(int argc, char * const argv[], const char *optstring);
#endif
#include "detok.h"
#include "stream.h"
+#include "addfcodes.h"
#define DETOK_VERSION "0.6.1"
-/* prototypes for dictionary handling */
-void init_dictionary(void);
-void decode_token(u16 token);
-/* prototype for detokenizer function */
-int detokenize(void);
+#define IBM_COPYR "(C) Copyright 2005 IBM Corporation. All Rights Reserved."
-extern unsigned int decode_all, verbose, linenumbers;
+bool verbose = FALSE ;
+bool decode_all = FALSE ;
+bool show_linenumbers = FALSE ;
+bool show_offsets = FALSE ;
-void print_copyright(void)
+/* Param is FALSE when beginning to detokenize,
+ * TRUE preceding error-exit */
+static void print_copyright(bool is_error)
{
- printf( "Welcome to the OpenBIOS detokenizer v%s\ndetok Copyright"
+ typedef void (*vfunct)(); /* Pointer to function returning void */
+ vfunct pfunct ;
+ char buffr[512];
+
+ sprintf( buffr,
+ "Welcome to the OpenBIOS detokenizer v%s\ndetok Copyright"
"(c) 2001-2005 by Stefan Reinauer.\nWritten by Stefan "
"Reinauer, <stepan(a)openbios.org>\n" "This program is "
"free software; you may redistribute it under the terms of\n"
"the GNU General Public License. This program has absolutely"
" no warranty.\n\n" ,DETOK_VERSION);
+
+ pfunct = ( is_error ? (vfunct)printf : printremark );
+
+ (*pfunct) ( buffr );
+
+ (*pfunct) ( IBM_COPYR "\n" );
}
-void usage(char *name)
+static void usage(char *name)
{
printf( "usage: %s [OPTION]... [FCODE-FILE]...\n\n"
" -v, --verbose print fcode numbers\n"
" -a, --all don't stop at end0\n"
" -n, --linenumbers print line numbers\n"
" -o, --offsets print byte offsets\n"
+ " -f, --fcodes add FCodes from list-file\n"
" -h, --help print this help text\n\n", name);
}
int main(int argc, char **argv)
{
int c;
- const char *optstring="vhano?";
+ const char *optstring="vhanof:?";
+ int linenumbers = 0;
+ bool add_vfcodes = FALSE;
+ char *vfc_filnam = NULL;
while (1) {
#ifdef __GLIBC__
@@ -86,6 +104,7 @@
{ "all", 0, 0, 'a' },
{ "linenumbers", 0, 0, 'n' },
{ "offsets", 0, 0, 'o' },
+ { "fcodes", 1, 0, 'f' },
{ 0, 0, 0, 0 }
};
@@ -99,24 +118,31 @@
switch (c) {
case 'v':
- verbose=1;
+ verbose=TRUE;
break;
case 'a':
- decode_all=1;
+ decode_all=TRUE;
break;
case 'n':
linenumbers|=1;
+ show_linenumbers = TRUE;
break;
case 'o':
linenumbers|=2;
+ show_linenumbers = TRUE;
+ show_offsets = TRUE;
break;
+ case 'f':
+ add_vfcodes = TRUE;
+ vfc_filnam = optarg;
+ break;
case 'h':
case '?':
- print_copyright();
+ print_copyright(TRUE);
usage(argv[0]);
return 0;
default:
- print_copyright();
+ print_copyright(TRUE);
printf ("%s: unknown option.\n",argv[0]);
usage(argv[0]);
return 1;
@@ -124,13 +150,14 @@
}
if (verbose)
- print_copyright();
+ print_copyright(FALSE);
if (linenumbers>2)
- printf("Line numbers will be disabled in favour of offsets.\n");
+ printremark(
+ "Line numbers will be disabled in favour of offsets.\n");
if (optind >= argc) {
- print_copyright();
+ print_copyright(TRUE);
printf ("%s: filename missing.\n",argv[0]);
usage(argv[0]);
return 1;
@@ -138,6 +165,14 @@
init_dictionary();
+ if ( add_vfcodes )
+ {
+ if ( add_fcodes_from_list( vfc_filnam) )
+ {
+ freeze_dictionary();
+ }
+ }
+
while (optind < argc) {
if (init_stream(argv[optind])) {
Modified: fcode-utils/detok/detok.h
===================================================================
--- fcode-utils/detok/detok.h 2006-08-18 09:45:11 UTC (rev 75)
+++ fcode-utils/detok/detok.h 2006-08-18 12:47:12 UTC (rev 76)
@@ -1,3 +1,6 @@
+#ifndef _UTILS_DETOK_DETOK_H
+#define _UTILS_DETOK_DETOK_H
+
/*
* OpenBIOS - free your system!
* ( detokenizer )
@@ -24,10 +27,49 @@
*
*/
-#define u8 unsigned char
-#define u16 unsigned short
-#define u32 unsigned int
-#define s16 short
-#define bool int
-#define TRUE (-1)
-#define FALSE (0)
+/* **************************************************************************
+ * Modifications made in 2005 by IBM Corporation
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Modifications Author: David L. Paktor dlpaktor(a)us.ibm.com
+ **************************************************************************** */
+
+#include "types.h"
+
+/* Prototypes for functions exported from
+ * detok.c decode.c printformats.c pcihdr.c and dictionary.c
+ */
+
+void add_token(u16 number, char *name);
+void init_dictionary(void);
+void reset_dictionary(void);
+void freeze_dictionary(void);
+char *lookup_token(u16 number);
+
+void detokenize(void);
+
+void printremark(char *str);
+
+int handle_pci_header ( u8 *data_ptr );
+void handle_pci_filler(u8 *filler_ptr);
+
+
+/* External declarations for variables defined in or used by
+ * detok.c decode.c printformats.c pcihdr.c and dictionary.c
+ */
+extern bool verbose;
+extern bool decode_all;
+extern bool show_linenumbers;
+extern bool show_offsets;
+
+extern bool check_tok_seq;
+
+extern u16 fcode;
+extern bool offs16;
+extern bool end_found;
+extern unsigned int linenum;
+
+extern u8 *pci_image_end;
+extern unsigned int token_streampos;
+extern u16 last_defined_token;
+
+#endif /* _UTILS_DETOK_DETOK_H */
Modified: fcode-utils/detok/dictionary.c
===================================================================
--- fcode-utils/detok/dictionary.c 2006-08-18 09:45:11 UTC (rev 75)
+++ fcode-utils/detok/dictionary.c 2006-08-18 12:47:12 UTC (rev 76)
@@ -24,20 +24,29 @@
*
*/
+/* **************************************************************************
+ * Modifications made in 2005 by IBM Corporation
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Modifications Author: David L. Paktor dlpaktor(a)us.ibm.com
+ **************************************************************************** */
+
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "detok.h"
+bool check_tok_seq = TRUE;
+
typedef struct token {
- u8 *name;
+ char *name;
u16 fcode;
struct token *next;
} token_t;
+#define TOKEN_ENTRY(num, name) { name, (u16)num, (token_t *)NULL }
+static token_t *dictionary; /* Initialize dynamically to accommodate AIX */
static char *fcerror="ferror";
-token_t *dictionary=NULL;
char *lookup_token(u16 number)
{
@@ -53,7 +62,51 @@
return fcerror;
}
-int add_token(u16 number, char *name)
+/* **************************************************************************
+ *
+ * Function name: add_token
+ * Synopsis: Add an entry to the FCode-Tokens vocabulary.
+ *
+ * Inputs:
+ * Parameters:
+ * number Numeric value of the FCode token
+ * name Name of the function to display
+ * Global/Static Variables:
+ * dictionary Pointer to the "tail" of the
+ * FCode-Tokens vocabulary.
+ * check_tok_seq TRUE = "Check Token Sequence"
+ * A retro-fit to accommodate
+ * adding Vendor FCodes
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global/Static Variables:
+ * dictionary Updated to point to the new entry.
+ * last_defined_token Updated to the given FCode token
+ * Memory Allocated
+ * For the new entry.
+ * When Freed?
+ * Never. Retained for duration of the program.
+ *
+ * Error Detection:
+ * Failure to allocate memory is a fatal error.
+ * If the given FCode token is not exactly one larger than the
+ * previous last_defined_token , then there's something
+ * odd going on; print a remark to alert the user. The
+ * value of last_defined_token will be used elsewhere
+ * for additional error-checking.
+ *
+ * Process Explanation:
+ * The name field pointer is presumed to already point to a stable
+ * memory-space.
+ * Memory will be allocated for the entry itself; its fields will
+ * be entered and the pointer-to-the-tail-of-the-vocabulary
+ * will be updated to point to the new entry.
+ * Error-check and update last_defined_token
+ *
+ **************************************************************************** */
+
+void add_token(u16 number, char *name)
{
token_t *curr;
@@ -68,393 +121,451 @@
curr->name=name;
dictionary=curr;
- return 0;
+
+ if ( check_tok_seq )
+ {
+ /* Error-check, but not for first time. */
+ if ( (number == last_defined_token + 1)
+ || (last_defined_token == 0) )
+ {
+ last_defined_token = number;
+ }else{
+ if ( number <= last_defined_token )
+ {
+ printremark("Warning: New token # might overlap "
+ "previously assigned token #(s).");
+ }else{
+ printremark("Warning: New token # out of sequence with "
+ "previously assigned token #(s).");
+ /* It's increasing; update it. */
+ last_defined_token = number;
+ }
}
+ }
+}
+
+token_t detok_table[] = {
+
+ TOKEN_ENTRY( 0x000, "end0" ),
+ TOKEN_ENTRY( 0x010, "b(lit)" ),
+ TOKEN_ENTRY( 0x011, "b(')" ),
+ TOKEN_ENTRY( 0x012, "b(\")" ),
+ TOKEN_ENTRY( 0x013, "bbranch" ),
+ TOKEN_ENTRY( 0x014, "b?branch" ),
+ TOKEN_ENTRY( 0x015, "b(loop)" ),
+ TOKEN_ENTRY( 0x016, "b(+loop)" ),
+ TOKEN_ENTRY( 0x017, "b(do)" ),
+ TOKEN_ENTRY( 0x018, "b(?do)" ),
+ TOKEN_ENTRY( 0x019, "i" ),
+ TOKEN_ENTRY( 0x01a, "j" ),
+ TOKEN_ENTRY( 0x01b, "b(leave)" ),
+ TOKEN_ENTRY( 0x01c, "b(of)" ),
+ TOKEN_ENTRY( 0x01d, "execute" ),
+ TOKEN_ENTRY( 0x01e, "+" ),
+ TOKEN_ENTRY( 0x01f, "-" ),
+ TOKEN_ENTRY( 0x020, "*" ),
+ TOKEN_ENTRY( 0x021, "/" ),
+ TOKEN_ENTRY( 0x022, "mod" ),
+ TOKEN_ENTRY( 0x023, "and" ),
+ TOKEN_ENTRY( 0x024, "or" ),
+ TOKEN_ENTRY( 0x025, "xor" ),
+ TOKEN_ENTRY( 0x026, "invert" ),
+ TOKEN_ENTRY( 0x027, "lshift" ),
+ TOKEN_ENTRY( 0x028, "rshift" ),
+ TOKEN_ENTRY( 0x029, ">>a" ),
+ TOKEN_ENTRY( 0x02a, "/mod" ),
+ TOKEN_ENTRY( 0x02b, "u/mod" ),
+ TOKEN_ENTRY( 0x02c, "negate" ),
+ TOKEN_ENTRY( 0x02d, "abs" ),
+ TOKEN_ENTRY( 0x02e, "min" ),
+ TOKEN_ENTRY( 0x02f, "max" ),
+ TOKEN_ENTRY( 0x030, ">r" ),
+ TOKEN_ENTRY( 0x031, "r>" ),
+ TOKEN_ENTRY( 0x032, "r@" ),
+ TOKEN_ENTRY( 0x033, "exit" ),
+ TOKEN_ENTRY( 0x034, "0=" ),
+ TOKEN_ENTRY( 0x035, "0<>" ),
+ TOKEN_ENTRY( 0x036, "0<" ),
+ TOKEN_ENTRY( 0x037, "0<=" ),
+ TOKEN_ENTRY( 0x038, "0>" ),
+ TOKEN_ENTRY( 0x039, "0>=" ),
+ TOKEN_ENTRY( 0x03a, "<" ),
+ TOKEN_ENTRY( 0x03b, ">" ),
+ TOKEN_ENTRY( 0x03c, "=" ),
+ TOKEN_ENTRY( 0x03d, "<>" ),
+ TOKEN_ENTRY( 0x03e, "u>" ),
+ TOKEN_ENTRY( 0x03f, "u<=" ),
+ TOKEN_ENTRY( 0x040, "u<" ),
+ TOKEN_ENTRY( 0x041, "u>=" ),
+ TOKEN_ENTRY( 0x042, ">=" ),
+ TOKEN_ENTRY( 0x043, "<=" ),
+ TOKEN_ENTRY( 0x044, "between" ),
+ TOKEN_ENTRY( 0x045, "within" ),
+ TOKEN_ENTRY( 0x046, "drop" ),
+ TOKEN_ENTRY( 0x047, "dup" ),
+ TOKEN_ENTRY( 0x048, "over" ),
+ TOKEN_ENTRY( 0x049, "swap" ),
+ TOKEN_ENTRY( 0x04A, "rot" ),
+ TOKEN_ENTRY( 0x04b, "-rot" ),
+ TOKEN_ENTRY( 0x04c, "tuck" ),
+ TOKEN_ENTRY( 0x04d, "nip" ),
+ TOKEN_ENTRY( 0x04e, "pick" ),
+ TOKEN_ENTRY( 0x04f, "roll" ),
+ TOKEN_ENTRY( 0x050, "?dup" ),
+ TOKEN_ENTRY( 0x051, "depth" ),
+ TOKEN_ENTRY( 0x052, "2drop" ),
+ TOKEN_ENTRY( 0x053, "2dup" ),
+ TOKEN_ENTRY( 0x054, "2over" ),
+ TOKEN_ENTRY( 0x055, "2swap" ),
+ TOKEN_ENTRY( 0x056, "2rot" ),
+ TOKEN_ENTRY( 0x057, "2/" ),
+ TOKEN_ENTRY( 0x058, "u2/" ),
+ TOKEN_ENTRY( 0x059, "2*" ),
+ TOKEN_ENTRY( 0x05a, "/c" ),
+ TOKEN_ENTRY( 0x05b, "/w" ),
+ TOKEN_ENTRY( 0x05c, "/l" ),
+ TOKEN_ENTRY( 0x05d, "/n" ),
+ TOKEN_ENTRY( 0x05e, "ca+" ),
+ TOKEN_ENTRY( 0x05f, "wa+" ),
+ TOKEN_ENTRY( 0x060, "la+" ),
+ TOKEN_ENTRY( 0x061, "na+" ),
+ TOKEN_ENTRY( 0x062, "char+" ),
+ TOKEN_ENTRY( 0x063, "wa1+" ),
+ TOKEN_ENTRY( 0x064, "la1+" ),
+ TOKEN_ENTRY( 0x065, "cell+" ),
+ TOKEN_ENTRY( 0x066, "chars" ),
+ TOKEN_ENTRY( 0x067, "/w*" ),
+ TOKEN_ENTRY( 0x068, "/l*" ),
+ TOKEN_ENTRY( 0x069, "cells" ),
+ TOKEN_ENTRY( 0x06a, "on" ),
+ TOKEN_ENTRY( 0x06b, "off" ),
+ TOKEN_ENTRY( 0x06c, "+!" ),
+ TOKEN_ENTRY( 0x06d, "@" ),
+ TOKEN_ENTRY( 0x06e, "l@" ),
+ TOKEN_ENTRY( 0x06f, "w@" ),
+ TOKEN_ENTRY( 0x070, "<w@" ),
+ TOKEN_ENTRY( 0x071, "c@" ),
+ TOKEN_ENTRY( 0x072, "!" ),
+ TOKEN_ENTRY( 0x073, "l!" ),
+ TOKEN_ENTRY( 0x074, "w!" ),
+ TOKEN_ENTRY( 0x075, "c!" ),
+ TOKEN_ENTRY( 0x076, "2@" ),
+ TOKEN_ENTRY( 0x077, "2!" ),
+ TOKEN_ENTRY( 0x078, "move" ),
+ TOKEN_ENTRY( 0x079, "fill" ),
+ TOKEN_ENTRY( 0x07a, "comp" ),
+ TOKEN_ENTRY( 0x07b, "noop" ),
+ TOKEN_ENTRY( 0x07c, "lwsplit" ),
+ TOKEN_ENTRY( 0x07d, "wljoin" ),
+ TOKEN_ENTRY( 0x07e, "lbsplit" ),
+ TOKEN_ENTRY( 0x07f, "bljoin" ),
+ TOKEN_ENTRY( 0x080, "wbflip" ),
+ TOKEN_ENTRY( 0x081, "upc" ),
+ TOKEN_ENTRY( 0x082, "lcc" ),
+ TOKEN_ENTRY( 0x083, "pack" ),
+ TOKEN_ENTRY( 0x084, "count" ),
+ TOKEN_ENTRY( 0x085, "body>" ),
+ TOKEN_ENTRY( 0x086, ">body" ),
+ TOKEN_ENTRY( 0x087, "fcode-revision" ),
+ TOKEN_ENTRY( 0x088, "span" ),
+ TOKEN_ENTRY( 0x089, "unloop" ),
+ TOKEN_ENTRY( 0x08a, "expect" ),
+ TOKEN_ENTRY( 0x08b, "alloc-mem" ),
+ TOKEN_ENTRY( 0x08c, "free-mem" ),
+ TOKEN_ENTRY( 0x08d, "key?" ),
+ TOKEN_ENTRY( 0x08e, "key" ),
+ TOKEN_ENTRY( 0x08f, "emit" ),
+ TOKEN_ENTRY( 0x090, "type" ),
+ TOKEN_ENTRY( 0x091, "(cr" ),
+ TOKEN_ENTRY( 0x092, "cr" ),
+ TOKEN_ENTRY( 0x093, "#out" ),
+ TOKEN_ENTRY( 0x094, "#line" ),
+ TOKEN_ENTRY( 0x095, "hold" ),
+ TOKEN_ENTRY( 0x096, "<#" ),
+ TOKEN_ENTRY( 0x097, "u#>" ),
+ TOKEN_ENTRY( 0x098, "sign" ),
+ TOKEN_ENTRY( 0x099, "u#" ),
+ TOKEN_ENTRY( 0x09a, "u#s" ),
+ TOKEN_ENTRY( 0x09b, "u." ),
+ TOKEN_ENTRY( 0x09c, "u.r" ),
+ TOKEN_ENTRY( 0x09d, "." ),
+ TOKEN_ENTRY( 0x09e, ".r" ),
+ TOKEN_ENTRY( 0x09f, ".s" ),
+ TOKEN_ENTRY( 0x0a0, "base" ),
+ TOKEN_ENTRY( 0x0a1, "convert" ),
+ TOKEN_ENTRY( 0x0a2, "$number" ),
+ TOKEN_ENTRY( 0x0a3, "digit" ),
+ TOKEN_ENTRY( 0x0a4, "-1" ),
+ TOKEN_ENTRY( 0x0a5, "0" ),
+ TOKEN_ENTRY( 0x0a6, "1" ),
+ TOKEN_ENTRY( 0x0a7, "2" ),
+ TOKEN_ENTRY( 0x0a8, "3" ),
+ TOKEN_ENTRY( 0x0a9, "bl" ),
+ TOKEN_ENTRY( 0x0aa, "bs" ),
+ TOKEN_ENTRY( 0x0ab, "bell" ),
+ TOKEN_ENTRY( 0x0ac, "bounds" ),
+ TOKEN_ENTRY( 0x0ad, "here" ),
+ TOKEN_ENTRY( 0x0ae, "aligned" ),
+ TOKEN_ENTRY( 0x0af, "wbsplit" ),
+ TOKEN_ENTRY( 0x0b0, "bwjoin" ),
+ TOKEN_ENTRY( 0x0b1, "b(<mark)" ),
+ TOKEN_ENTRY( 0x0b2, "b(>resolve)" ),
+ TOKEN_ENTRY( 0x0b3, "set-token-table" ),
+ TOKEN_ENTRY( 0x0b4, "set-table" ),
+ TOKEN_ENTRY( 0x0b5, "new-token" ),
+ TOKEN_ENTRY( 0x0b6, "named-token" ),
+ TOKEN_ENTRY( 0x0b7, "b(:)" ),
+ TOKEN_ENTRY( 0x0b8, "b(value)" ),
+ TOKEN_ENTRY( 0x0b9, "b(variable)" ),
+ TOKEN_ENTRY( 0x0ba, "b(constant)" ),
+ TOKEN_ENTRY( 0x0bb, "b(create)" ),
+ TOKEN_ENTRY( 0x0bc, "b(defer)" ),
+ TOKEN_ENTRY( 0x0bd, "b(buffer:)" ),
+ TOKEN_ENTRY( 0x0be, "b(field)" ),
+ TOKEN_ENTRY( 0x0bf, "b(code)" ),
+ TOKEN_ENTRY( 0x0c0, "instance" ),
+ TOKEN_ENTRY( 0x0c2, "b(;)" ),
+ TOKEN_ENTRY( 0x0c3, "b(to)" ),
+ TOKEN_ENTRY( 0x0c4, "b(case)" ),
+ TOKEN_ENTRY( 0x0c5, "b(endcase)" ),
+ TOKEN_ENTRY( 0x0c6, "b(endof)" ),
+ TOKEN_ENTRY( 0x0c7, "#" ),
+ TOKEN_ENTRY( 0x0c8, "#s" ),
+ TOKEN_ENTRY( 0x0c9, "#>" ),
+ TOKEN_ENTRY( 0x0ca, "external-token" ),
+ TOKEN_ENTRY( 0x0cb, "$find" ),
+ TOKEN_ENTRY( 0x0cc, "offset16" ),
+ TOKEN_ENTRY( 0x0cd, "evaluate" ),
+ TOKEN_ENTRY( 0x0d0, "c," ),
+ TOKEN_ENTRY( 0x0d1, "w," ),
+ TOKEN_ENTRY( 0x0d2, "l," ),
+ TOKEN_ENTRY( 0x0d3, "," ),
+ TOKEN_ENTRY( 0x0d4, "um*" ),
+ TOKEN_ENTRY( 0x0d5, "um/mod" ),
+ TOKEN_ENTRY( 0x0d8, "d+" ),
+ TOKEN_ENTRY( 0x0d9, "d-" ),
+ TOKEN_ENTRY( 0x0da, "get-token" ),
+ TOKEN_ENTRY( 0x0db, "set-token" ),
+ TOKEN_ENTRY( 0x0dc, "state" ),
+ TOKEN_ENTRY( 0x0dd, "compile" ),
+ TOKEN_ENTRY( 0x0de, "behavior" ),
+ TOKEN_ENTRY( 0x0f0, "start0" ),
+ TOKEN_ENTRY( 0x0f1, "start1" ),
+ TOKEN_ENTRY( 0x0f2, "start2" ),
+ TOKEN_ENTRY( 0x0f3, "start4" ),
+ TOKEN_ENTRY( 0x0fc, "ferror" ),
+ TOKEN_ENTRY( 0x0fd, "version1" ),
+ TOKEN_ENTRY( 0x0fe, "4-byte-id" ),
+ TOKEN_ENTRY( 0x0ff, "end1" ),
+ TOKEN_ENTRY( 0x101, "dma-alloc" ),
+ TOKEN_ENTRY( 0x102, "my-address" ),
+ TOKEN_ENTRY( 0x103, "my-space" ),
+ TOKEN_ENTRY( 0x104, "memmap" ),
+ TOKEN_ENTRY( 0x105, "free-virtual" ),
+ TOKEN_ENTRY( 0x106, ">physical" ),
+ TOKEN_ENTRY( 0x10f, "my-params" ),
+ TOKEN_ENTRY( 0x110, "property" ),
+ TOKEN_ENTRY( 0x111, "encode-int" ),
+ TOKEN_ENTRY( 0x112, "encode+" ),
+ TOKEN_ENTRY( 0x113, "encode-phys" ),
+ TOKEN_ENTRY( 0x114, "encode-string" ),
+ TOKEN_ENTRY( 0x115, "encode-bytes" ),
+ TOKEN_ENTRY( 0x116, "reg" ),
+ TOKEN_ENTRY( 0x117, "intr" ),
+ TOKEN_ENTRY( 0x118, "driver" ),
+ TOKEN_ENTRY( 0x119, "model" ),
+ TOKEN_ENTRY( 0x11a, "device-type" ),
+ TOKEN_ENTRY( 0x11b, "parse-2int" ),
+ TOKEN_ENTRY( 0x11c, "is-install" ),
+ TOKEN_ENTRY( 0x11d, "is-remove" ),
+ TOKEN_ENTRY( 0x11e, "is-selftest" ),
+ TOKEN_ENTRY( 0x11f, "new-device" ),
+ TOKEN_ENTRY( 0x120, "diagnostic-mode?" ),
+ TOKEN_ENTRY( 0x121, "display-status" ),
+ TOKEN_ENTRY( 0x122, "memory-test-issue" ),
+ TOKEN_ENTRY( 0x123, "group-code" ),
+ TOKEN_ENTRY( 0x124, "mask" ),
+ TOKEN_ENTRY( 0x125, "get-msecs" ),
+ TOKEN_ENTRY( 0x126, "ms" ),
+ TOKEN_ENTRY( 0x127, "finish-device" ),
+ TOKEN_ENTRY( 0x128, "decode-phys" ),
+ TOKEN_ENTRY( 0x12b, "interpose" ),
+ TOKEN_ENTRY( 0x130, "map-low" ),
+ TOKEN_ENTRY( 0x131, "sbus-intr>cpu" ),
+ TOKEN_ENTRY( 0x150, "#lines" ),
+ TOKEN_ENTRY( 0x151, "#columns" ),
+ TOKEN_ENTRY( 0x152, "line#" ),
+ TOKEN_ENTRY( 0x153, "column#" ),
+ TOKEN_ENTRY( 0x154, "inverse?" ),
+ TOKEN_ENTRY( 0x155, "inverse-screen?" ),
+ TOKEN_ENTRY( 0x156, "frame-buffer-busy?" ),
+ TOKEN_ENTRY( 0x157, "draw-character" ),
+ TOKEN_ENTRY( 0x158, "reset-screen" ),
+ TOKEN_ENTRY( 0x159, "toggle-cursor" ),
+ TOKEN_ENTRY( 0x15a, "erase-screen" ),
+ TOKEN_ENTRY( 0x15b, "blink-screen" ),
+ TOKEN_ENTRY( 0x15c, "invert-screen" ),
+ TOKEN_ENTRY( 0x15d, "insert-characters" ),
+ TOKEN_ENTRY( 0x15e, "delete-characters" ),
+ TOKEN_ENTRY( 0x15f, "insert-lines" ),
+ TOKEN_ENTRY( 0x160, "delete-lines" ),
+ TOKEN_ENTRY( 0x161, "draw-logo" ),
+ TOKEN_ENTRY( 0x162, "frame-buffer-adr" ),
+ TOKEN_ENTRY( 0x163, "screen-height" ),
+ TOKEN_ENTRY( 0x164, "screen-width" ),
+ TOKEN_ENTRY( 0x165, "window-top" ),
+ TOKEN_ENTRY( 0x166, "window-left" ),
+ TOKEN_ENTRY( 0x16a, "default-font" ),
+ TOKEN_ENTRY( 0x16b, "set-font" ),
+ TOKEN_ENTRY( 0x16c, "char-height" ),
+ TOKEN_ENTRY( 0x16d, "char-width" ),
+ TOKEN_ENTRY( 0x16e, ">font" ),
+ TOKEN_ENTRY( 0x16f, "fontbytes" ),
+ TOKEN_ENTRY( 0x170, "fb1-draw-character" ),
+ TOKEN_ENTRY( 0x171, "fb1-reset-screen" ),
+ TOKEN_ENTRY( 0x172, "fb1-toggle-cursor" ),
+ TOKEN_ENTRY( 0x173, "fb1-erase-screen" ),
+ TOKEN_ENTRY( 0x174, "fb1-blink-screen" ),
+ TOKEN_ENTRY( 0x175, "fb1-invert-screen" ),
+ TOKEN_ENTRY( 0x176, "fb1-insert-characters" ),
+ TOKEN_ENTRY( 0x177, "fb1-delete-characters" ),
+ TOKEN_ENTRY( 0x178, "fb1-insert-lines" ),
+ TOKEN_ENTRY( 0x179, "fb1-delete-lines" ),
+ TOKEN_ENTRY( 0x17a, "fb1-draw-logo" ),
+ TOKEN_ENTRY( 0x17b, "fb1-install" ),
+ TOKEN_ENTRY( 0x17c, "fb1-slide-up" ),
+ TOKEN_ENTRY( 0x180, "fb8-draw-character" ),
+ TOKEN_ENTRY( 0x181, "fb8-reset-screen" ),
+ TOKEN_ENTRY( 0x182, "fb8-toggle-cursor" ),
+ TOKEN_ENTRY( 0x183, "fb8-erase-screen" ),
+ TOKEN_ENTRY( 0x184, "fb8-blink-screen" ),
+ TOKEN_ENTRY( 0x185, "fb8-invert-screen" ),
+ TOKEN_ENTRY( 0x186, "fb8-insert-characters" ),
+ TOKEN_ENTRY( 0x187, "fb8-delete-characters" ),
+ TOKEN_ENTRY( 0x188, "fb8-insert-lines" ),
+ TOKEN_ENTRY( 0x189, "fb8-delete-lines" ),
+ TOKEN_ENTRY( 0x18a, "fb8-draw-logo" ),
+ TOKEN_ENTRY( 0x18b, "fb8-install" ),
+ TOKEN_ENTRY( 0x1a0, "return-buffer" ),
+ TOKEN_ENTRY( 0x1a1, "xmit-packet" ),
+ TOKEN_ENTRY( 0x1a2, "poll-packet" ),
+ TOKEN_ENTRY( 0x1a4, "mac-address" ),
+ TOKEN_ENTRY( 0x201, "device-name" ),
+ TOKEN_ENTRY( 0x202, "my-args" ),
+ TOKEN_ENTRY( 0x203, "my-self" ),
+ TOKEN_ENTRY( 0x204, "find-package" ),
+ TOKEN_ENTRY( 0x205, "open-package" ),
+ TOKEN_ENTRY( 0x206, "close-package" ),
+ TOKEN_ENTRY( 0x207, "find-method" ),
+ TOKEN_ENTRY( 0x208, "call-package" ),
+ TOKEN_ENTRY( 0x209, "$call-parent" ),
+ TOKEN_ENTRY( 0x20a, "my-parent" ),
+ TOKEN_ENTRY( 0x20b, "ihandle>phandle" ),
+ TOKEN_ENTRY( 0x20d, "my-unit" ),
+ TOKEN_ENTRY( 0x20e, "$call-method" ),
+ TOKEN_ENTRY( 0x20f, "$open-package" ),
+ TOKEN_ENTRY( 0x210, "processor-type" ),
+ TOKEN_ENTRY( 0x211, "firmware-version" ),
+ TOKEN_ENTRY( 0x212, "fcode-version" ),
+ TOKEN_ENTRY( 0x213, "alarm" ),
+ TOKEN_ENTRY( 0x214, "(is-user-word)" ),
+ TOKEN_ENTRY( 0x215, "suspend-fcode" ),
+ TOKEN_ENTRY( 0x216, "abort" ),
+ TOKEN_ENTRY( 0x217, "catch" ),
+ TOKEN_ENTRY( 0x218, "throw" ),
+ TOKEN_ENTRY( 0x219, "user-abort" ),
+ TOKEN_ENTRY( 0x21a, "get-my-property" ),
+ TOKEN_ENTRY( 0x21b, "decode-int" ),
+ TOKEN_ENTRY( 0x21c, "decode-string" ),
+ TOKEN_ENTRY( 0x21d, "get-inherited-property" ),
+ TOKEN_ENTRY( 0x21e, "delete-property" ),
+ TOKEN_ENTRY( 0x21f, "get-package-property" ),
+ TOKEN_ENTRY( 0x220, "cpeek" ),
+ TOKEN_ENTRY( 0x221, "wpeek" ),
+ TOKEN_ENTRY( 0x222, "lpeek" ),
+ TOKEN_ENTRY( 0x223, "cpoke" ),
+ TOKEN_ENTRY( 0x224, "wpoke" ),
+ TOKEN_ENTRY( 0x225, "lpoke" ),
+ TOKEN_ENTRY( 0x226, "lwflip" ),
+ TOKEN_ENTRY( 0x227, "lbflip" ),
+ TOKEN_ENTRY( 0x228, "lbflips" ),
+ TOKEN_ENTRY( 0x229, "adr-mask" ),
+ TOKEN_ENTRY( 0x230, "rb@" ),
+ TOKEN_ENTRY( 0x231, "rb!" ),
+ TOKEN_ENTRY( 0x232, "rw@" ),
+ TOKEN_ENTRY( 0x233, "rw!" ),
+ TOKEN_ENTRY( 0x234, "rl@" ),
+ TOKEN_ENTRY( 0x235, "rl!" ),
+ TOKEN_ENTRY( 0x236, "wbflips" ),
+ TOKEN_ENTRY( 0x237, "lwflips" ),
+ TOKEN_ENTRY( 0x238, "probe" ),
+ TOKEN_ENTRY( 0x239, "probe-virtual" ),
+ TOKEN_ENTRY( 0x23b, "child" ),
+ TOKEN_ENTRY( 0x23c, "peer" ),
+ TOKEN_ENTRY( 0x23d, "next-property" ),
+ TOKEN_ENTRY( 0x23e, "byte-load" ),
+ TOKEN_ENTRY( 0x23f, "set-args" ),
+ TOKEN_ENTRY( 0x240, "left-parse-string" ),
+
+ /* FCodes from 64bit extension addendum */
+ TOKEN_ENTRY( 0x22e, "rx@" ),
+ TOKEN_ENTRY( 0x22f, "rx!" ),
+ TOKEN_ENTRY( 0x241, "bxjoin" ),
+ TOKEN_ENTRY( 0x242, "<l@" ),
+ TOKEN_ENTRY( 0x243, "lxjoin" ),
+ TOKEN_ENTRY( 0x244, "wxjoin" ),
+ TOKEN_ENTRY( 0x245, "x," ),
+ TOKEN_ENTRY( 0x246, "x@" ),
+ TOKEN_ENTRY( 0x247, "x!" ),
+ TOKEN_ENTRY( 0x248, "/x" ),
+ TOKEN_ENTRY( 0x249, "/x*" ),
+ TOKEN_ENTRY( 0x24a, "xa+" ),
+ TOKEN_ENTRY( 0x24b, "xa1+" ),
+ TOKEN_ENTRY( 0x24c, "xbflip" ),
+ TOKEN_ENTRY( 0x24d, "xbflips" ),
+ TOKEN_ENTRY( 0x24e, "xbsplit" ),
+ TOKEN_ENTRY( 0x24f, "xlflip" ),
+ TOKEN_ENTRY( 0x250, "xlflips" ),
+ TOKEN_ENTRY( 0x251, "xlsplit" ),
+ TOKEN_ENTRY( 0x252, "xwflip" ),
+ TOKEN_ENTRY( 0x253, "xwflips" ),
+ TOKEN_ENTRY( 0x254, "xwsplit" ),
+};
+
+static const int dictionary_indx_max = (sizeof(detok_table)/sizeof(token_t)) ;
+
+static token_t *dictionary_reset_position;
+
void init_dictionary(void)
{
- add_token( 0x000, "end0" );
- add_token( 0x010, "b(lit)" );
- add_token( 0x011, "b(')" );
- add_token( 0x012, "b(\")" );
- add_token( 0x013, "bbranch" );
- add_token( 0x014, "b?branch" );
- add_token( 0x015, "b(loop)" );
- add_token( 0x016, "b(+loop)" );
- add_token( 0x017, "b(do)" );
- add_token( 0x018, "b(?do)" );
- add_token( 0x019, "i" );
- add_token( 0x01a, "j" );
- add_token( 0x01b, "b(leave)" );
- add_token( 0x01c, "b(of)" );
- add_token( 0x01d, "execute" );
- add_token( 0x01e, "+" );
- add_token( 0x01f, "-" );
- add_token( 0x020, "*" );
- add_token( 0x021, "/" );
- add_token( 0x022, "mod" );
- add_token( 0x023, "and" );
- add_token( 0x024, "or" );
- add_token( 0x025, "xor" );
- add_token( 0x026, "invert" );
- add_token( 0x027, "lshift" );
- add_token( 0x028, "rshift" );
- add_token( 0x029, ">>a" );
- add_token( 0x02a, "/mod" );
- add_token( 0x02b, "u/mod" );
- add_token( 0x02c, "negate" );
- add_token( 0x02d, "abs" );
- add_token( 0x02e, "min" );
- add_token( 0x02f, "max" );
- add_token( 0x030, ">r" );
- add_token( 0x031, "r>" );
- add_token( 0x032, "r@" );
- add_token( 0x033, "exit" );
- add_token( 0x034, "0=" );
- add_token( 0x035, "0<>" );
- add_token( 0x036, "0<" );
- add_token( 0x037, "0<=" );
- add_token( 0x038, "0>" );
- add_token( 0x039, "0>=" );
- add_token( 0x03a, "<" );
- add_token( 0x03b, ">" );
- add_token( 0x03c, "=" );
- add_token( 0x03d, "<>" );
- add_token( 0x03e, "u>" );
- add_token( 0x03f, "u<=" );
- add_token( 0x040, "u<" );
- add_token( 0x041, "u>=" );
- add_token( 0x042, ">=" );
- add_token( 0x043, "<=" );
- add_token( 0x044, "between" );
- add_token( 0x045, "within" );
- add_token( 0x046, "drop" );
- add_token( 0x047, "dup" );
- add_token( 0x048, "over" );
- add_token( 0x049, "swap" );
- add_token( 0x04A, "rot" );
- add_token( 0x04b, "-rot" );
- add_token( 0x04c, "tuck" );
- add_token( 0x04d, "nip" );
- add_token( 0x04e, "pick" );
- add_token( 0x04f, "roll" );
- add_token( 0x050, "?dup" );
- add_token( 0x051, "depth" );
- add_token( 0x052, "2drop" );
- add_token( 0x053, "2dup" );
- add_token( 0x054, "2over" );
- add_token( 0x055, "2swap" );
- add_token( 0x056, "2rot" );
- add_token( 0x057, "2/" );
- add_token( 0x058, "u2/" );
- add_token( 0x059, "2*" );
- add_token( 0x05a, "/c" );
- add_token( 0x05b, "/w" );
- add_token( 0x05c, "/l" );
- add_token( 0x05d, "/n" );
- add_token( 0x05e, "ca+" );
- add_token( 0x05f, "wa+" );
- add_token( 0x060, "la+" );
- add_token( 0x061, "na+" );
- add_token( 0x062, "char+" );
- add_token( 0x063, "wa1+" );
- add_token( 0x064, "la1+" );
- add_token( 0x065, "cell+" );
- add_token( 0x066, "chars" );
- add_token( 0x067, "/w*" );
- add_token( 0x068, "/l*" );
- add_token( 0x069, "cells" );
- add_token( 0x06a, "on" );
- add_token( 0x06b, "off" );
- add_token( 0x06c, "+!" );
- add_token( 0x06d, "@" );
- add_token( 0x06e, "l@" );
- add_token( 0x06f, "w@" );
- add_token( 0x070, "<w@" );
- add_token( 0x071, "c@" );
- add_token( 0x072, "!" );
- add_token( 0x073, "l!" );
- add_token( 0x074, "w!" );
- add_token( 0x075, "c!" );
- add_token( 0x076, "2@" );
- add_token( 0x077, "2!" );
- add_token( 0x078, "move" );
- add_token( 0x079, "fill" );
- add_token( 0x07a, "comp" );
- add_token( 0x07b, "noop" );
- add_token( 0x07c, "lwsplit" );
- add_token( 0x07d, "wljoin" );
- add_token( 0x07e, "lbsplit" );
- add_token( 0x07f, "bljoin" );
- add_token( 0x080, "wbflip" );
- add_token( 0x081, "upc" );
- add_token( 0x082, "lcc" );
- add_token( 0x083, "pack" );
- add_token( 0x084, "count" );
- add_token( 0x085, "body>" );
- add_token( 0x086, ">body" );
- add_token( 0x087, "fcode-revision" );
- add_token( 0x088, "span" );
- add_token( 0x089, "unloop" );
- add_token( 0x08a, "expect" );
- add_token( 0x08b, "alloc-mem" );
- add_token( 0x08c, "free-mem" );
- add_token( 0x08d, "key?" );
- add_token( 0x08e, "key" );
- add_token( 0x08f, "emit" );
- add_token( 0x090, "type" );
- add_token( 0x091, "(cr" );
- add_token( 0x092, "cr" );
- add_token( 0x093, "#out" );
- add_token( 0x094, "#line" );
- add_token( 0x095, "hold" );
- add_token( 0x096, "<#" );
- add_token( 0x097, "u#>" );
- add_token( 0x098, "sign" );
- add_token( 0x099, "u#" );
- add_token( 0x09a, "u#s" );
- add_token( 0x09b, "u." );
- add_token( 0x09c, "u.r" );
- add_token( 0x09d, "." );
- add_token( 0x09e, ".r" );
- add_token( 0x09f, ".s" );
- add_token( 0x0a0, "base" );
- add_token( 0x0a1, "convert" );
- add_token( 0x0a2, "$number" );
- add_token( 0x0a3, "digit" );
- add_token( 0x0a4, "-1" );
- add_token( 0x0a5, "0" );
- add_token( 0x0a6, "1" );
- add_token( 0x0a7, "2" );
- add_token( 0x0a8, "3" );
- add_token( 0x0a9, "bl" );
- add_token( 0x0aa, "bs" );
- add_token( 0x0ab, "bell" );
- add_token( 0x0ac, "bounds" );
- add_token( 0x0ad, "here" );
- add_token( 0x0ae, "aligned" );
- add_token( 0x0af, "wbsplit" );
- add_token( 0x0b0, "bwjoin" );
- add_token( 0x0b1, "b(<mark)" );
- add_token( 0x0b2, "b(>resolve)" );
- add_token( 0x0b3, "set-token-table" );
- add_token( 0x0b4, "set-table" );
- add_token( 0x0b5, "new-token" );
- add_token( 0x0b6, "named-token" );
- add_token( 0x0b7, "b(:)" );
- add_token( 0x0b8, "b(value)" );
- add_token( 0x0b9, "b(variable)" );
- add_token( 0x0ba, "b(constant)" );
- add_token( 0x0bb, "b(create)" );
- add_token( 0x0bc, "b(defer)" );
- add_token( 0x0bd, "b(buffer:)" );
- add_token( 0x0be, "b(field)" );
- add_token( 0x0bf, "b(code)" );
- add_token( 0x0c0, "instance" );
- add_token( 0x0c2, "b(;)" );
- add_token( 0x0c3, "b(to)" );
- add_token( 0x0c4, "b(case)" );
- add_token( 0x0c5, "b(endcase)" );
- add_token( 0x0c6, "b(endof)" );
- add_token( 0x0c7, "#" );
- add_token( 0x0c8, "#s" );
- add_token( 0x0c9, "#>" );
- add_token( 0x0ca, "external-token" );
- add_token( 0x0cb, "$find" );
- add_token( 0x0cc, "offset16" );
- add_token( 0x0cd, "evaluate" );
- add_token( 0x0d0, "c," );
- add_token( 0x0d1, "w," );
- add_token( 0x0d2, "l," );
- add_token( 0x0d3, "," );
- add_token( 0x0d4, "um*" );
- add_token( 0x0d5, "um/mod" );
- add_token( 0x0d8, "d+" );
- add_token( 0x0d9, "d-" );
- add_token( 0x0da, "get-token" );
- add_token( 0x0db, "set-token" );
- add_token( 0x0dc, "state" );
- add_token( 0x0dd, "compile" );
- add_token( 0x0de, "behavior" );
- add_token( 0x0f0, "start0" );
- add_token( 0x0f1, "start1" );
- add_token( 0x0f2, "start2" );
- add_token( 0x0f3, "start4" );
- add_token( 0x0fc, "ferror" );
- add_token( 0x0fd, "version1" );
- add_token( 0x0fe, "4-byte-id" );
- add_token( 0x0ff, "end1" );
- add_token( 0x101, "dma-alloc" );
- add_token( 0x102, "my-address" );
- add_token( 0x103, "my-space" );
- add_token( 0x104, "memmap" );
- add_token( 0x105, "free-virtual" );
- add_token( 0x106, ">physical" );
- add_token( 0x10f, "my-params" );
- add_token( 0x110, "property" );
- add_token( 0x111, "encode-int" );
- add_token( 0x112, "encode+" );
- add_token( 0x113, "encode-phys" );
- add_token( 0x114, "encode-string" );
- add_token( 0x115, "encode-bytes" );
- add_token( 0x116, "reg" );
- add_token( 0x117, "intr" );
- add_token( 0x118, "driver" );
- add_token( 0x119, "model" );
- add_token( 0x11a, "device-type" );
- add_token( 0x11b, "parse-2int" );
- add_token( 0x11c, "is-install" );
- add_token( 0x11d, "is-remove" );
- add_token( 0x11e, "is-selftest" );
- add_token( 0x11f, "new-device" );
- add_token( 0x120, "diagnostic-mode?" );
- add_token( 0x121, "display-status" );
- add_token( 0x122, "memory-test-issue" );
- add_token( 0x123, "group-code" );
- add_token( 0x124, "mask" );
- add_token( 0x125, "get-msecs" );
- add_token( 0x126, "ms" );
- add_token( 0x127, "finish-device" );
- add_token( 0x128, "decode-phys" );
- add_token( 0x12b, "interpose" );
- add_token( 0x130, "map-low" );
- add_token( 0x131, "sbus-intr>cpu" );
- add_token( 0x150, "#lines" );
- add_token( 0x151, "#columns" );
- add_token( 0x152, "line#" );
- add_token( 0x153, "column#" );
- add_token( 0x154, "inverse?" );
- add_token( 0x155, "inverse-screen?" );
- add_token( 0x156, "frame-buffer-busy?" );
- add_token( 0x157, "draw-character" );
- add_token( 0x158, "reset-screen" );
- add_token( 0x159, "toggle-cursor" );
- add_token( 0x15a, "erase-screen" );
- add_token( 0x15b, "blink-screen" );
- add_token( 0x15c, "invert-screen" );
- add_token( 0x15d, "insert-characters" );
- add_token( 0x15e, "delete-characters" );
- add_token( 0x15f, "insert-lines" );
- add_token( 0x160, "delete-lines" );
- add_token( 0x161, "draw-logo" );
- add_token( 0x162, "frame-buffer-adr" );
- add_token( 0x163, "screen-height" );
- add_token( 0x164, "screen-width" );
- add_token( 0x165, "window-top" );
- add_token( 0x166, "window-left" );
- add_token( 0x16a, "default-font" );
- add_token( 0x16b, "set-font" );
- add_token( 0x16c, "char-height" );
- add_token( 0x16d, "char-width" );
- add_token( 0x16e, ">font" );
- add_token( 0x16f, "fontbytes" );
- add_token( 0x170, "fb1-draw-character" );
- add_token( 0x171, "fb1-reset-screen" );
- add_token( 0x172, "fb1-toggle-cursor" );
- add_token( 0x173, "fb1-erase-screen" );
- add_token( 0x174, "fb1-blink-screen" );
- add_token( 0x175, "fb1-invert-screen" );
- add_token( 0x176, "fb1-insert-characters" );
- add_token( 0x177, "fb1-delete-characters" );
- add_token( 0x178, "fb1-insert-lines" );
- add_token( 0x179, "fb1-delete-lines" );
- add_token( 0x17a, "fb1-draw-logo" );
- add_token( 0x17b, "fb1-install" );
- add_token( 0x17c, "fb1-slide-up" );
- add_token( 0x180, "fb8-draw-character" );
- add_token( 0x181, "fb8-reset-screen" );
- add_token( 0x182, "fb8-toggle-cursor" );
- add_token( 0x183, "fb8-erase-screen" );
- add_token( 0x184, "fb8-blink-screen" );
- add_token( 0x185, "fb8-invert-screen" );
- add_token( 0x186, "fb8-insert-characters" );
- add_token( 0x187, "fb8-delete-characters" );
- add_token( 0x188, "fb8-insert-lines" );
- add_token( 0x189, "fb8-delete-lines" );
- add_token( 0x18a, "fb8-draw-logo" );
- add_token( 0x18b, "fb8-install" );
- add_token( 0x1a0, "return-buffer" );
- add_token( 0x1a1, "xmit-packet" );
- add_token( 0x1a2, "poll-packet" );
- add_token( 0x1a4, "mac-address" );
- add_token( 0x201, "device-name" );
- add_token( 0x202, "my-args" );
- add_token( 0x203, "my-self" );
- add_token( 0x204, "find-package" );
- add_token( 0x205, "open-package" );
- add_token( 0x206, "close-package" );
- add_token( 0x207, "find-method" );
- add_token( 0x208, "call-package" );
- add_token( 0x209, "$call-parent" );
- add_token( 0x20a, "my-package" );
- add_token( 0x20b, "ihandle>phandle" );
- add_token( 0x20d, "my-unit" );
- add_token( 0x20e, "$call-method" );
- add_token( 0x20f, "$open-package" );
- add_token( 0x210, "processor-type" );
- add_token( 0x211, "firmware-version" );
- add_token( 0x212, "fcode-version" );
- add_token( 0x213, "alarm" );
- add_token( 0x214, "(is-user-word)" );
- add_token( 0x215, "suspend-fcode" );
- add_token( 0x216, "abort" );
- add_token( 0x217, "catch" );
- add_token( 0x218, "throw" );
- add_token( 0x219, "user-abort" );
- add_token( 0x21a, "get-my-property" );
- add_token( 0x21b, "decode-int" );
- add_token( 0x21c, "decode-string" );
- add_token( 0x21d, "get-inherited-property" );
- add_token( 0x21e, "delete-property" );
- add_token( 0x21f, "get-package-property" );
- add_token( 0x220, "cpeek" );
- add_token( 0x221, "wpeek" );
- add_token( 0x222, "lpeek" );
- add_token( 0x223, "cpoke" );
- add_token( 0x224, "wpoke" );
- add_token( 0x225, "lpoke" );
- add_token( 0x226, "lwflip" );
- add_token( 0x227, "lbflip" );
- add_token( 0x228, "lbflips" );
- add_token( 0x229, "adr-mask" );
- add_token( 0x230, "rb@" );
- add_token( 0x231, "rb!" );
- add_token( 0x232, "rw@" );
- add_token( 0x233, "rw!" );
- add_token( 0x234, "rl@" );
- add_token( 0x235, "rl!" );
- add_token( 0x236, "wbflips" );
- add_token( 0x237, "lwflips" );
- add_token( 0x238, "probe" );
- add_token( 0x239, "probe-virtual" );
- add_token( 0x23b, "child" );
- add_token( 0x23c, "peer" );
- add_token( 0x23d, "next-property" );
- add_token( 0x23e, "byte-load" );
- add_token( 0x23f, "set-args" );
- add_token( 0x240, "left-parse-string" );
+ int indx;
- /* FCodes from 64bit extension addendum */
- add_token( 0x22e, "rx@" );
- add_token( 0x22f, "rx!" );
- add_token( 0x241, "bxjoin" );
- add_token( 0x242, "<l@" );
- add_token( 0x243, "lxjoin" );
- add_token( 0x244, "wxjoin" );
- add_token( 0x245, "x," );
- add_token( 0x246, "x@" );
- add_token( 0x247, "x!" );
- add_token( 0x248, "/x" );
- add_token( 0x249, "/x*" );
- add_token( 0x24a, "xa+" );
- add_token( 0x24b, "xa1+" );
- add_token( 0x24c, "xbflip" );
- add_token( 0x24d, "xbflips" );
- add_token( 0x24e, "xbsplit" );
- add_token( 0x24f, "xlflip" );
- add_token( 0x250, "xlflips" );
- add_token( 0x251, "xlsplit" );
- add_token( 0x252, "xwflip" );
- add_token( 0x253, "xwflips" );
- add_token( 0x254, "xwsplit" );
+ dictionary = &detok_table[dictionary_indx_max-1];
+ dictionary_reset_position = dictionary;
+
+ for (indx = 1; indx < dictionary_indx_max ; indx++ )
+ {
+ detok_table[indx].next = &detok_table[indx-1];
+ }
}
+
+void reset_dictionary(void)
+{
+ token_t *next_t;
+
+ next_t = dictionary;
+ while ( next_t != dictionary_reset_position )
+ {
+ next_t = dictionary->next ;
+ free( dictionary->name );
+ free( dictionary );
+ dictionary = next_t ;
+ }
+}
+
+/* If FCodes have been added by User, we need to update reset-position */
+void freeze_dictionary(void)
+{
+ dictionary_reset_position = dictionary;
+}
Added: fcode-utils/detok/pcihdr.c
===================================================================
--- fcode-utils/detok/pcihdr.c (rev 0)
+++ fcode-utils/detok/pcihdr.c 2006-08-18 12:47:12 UTC (rev 76)
@@ -0,0 +1,478 @@
+/*
+ * OpenBIOS - free your system!
+ * ( FCode tokenizer )
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 2001-2005 Stefan Reinauer, <stepan(a)openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+/* **************************************************************************
+ *
+ * Support function for de-tokenizer.
+ *
+ * Identify and process PCI header at beginning of FCode binary file.
+ * "Processing" consists of recognizing the PCI Header and Data Structure,
+ * optionally printing a description thereof, and (mainly) allowing
+ * the given pointer to be bumped to the start of the actual FCode.
+ *
+ *
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Module Author: David L. Paktor dlpaktor(a)us.ibm.com
+ *
+ * Revision History:
+ *
+ * Updated Mon, 23 May 2005 by David L. Paktor
+ * Identify "Not Last" header.
+ * Updated Thu, 24 Feb 2005 by David L. Paktor
+ * Per notes after Code Review.
+ * Updated Fri, 04 Feb 2005 by David L. Paktor
+ * Updated Wed, 08 Jun 2005 by David L. Paktor
+ * Added support for multiple-PCI-image files.
+ *
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Functions Eported:
+ * handle_pci_header
+ * Handle all activities connected with presence of
+ * PCI Header/Data at beginning of FCode file, and
+ * facilitate "skipping" over to actual FCode data.
+ *
+ * handle_pci_filler
+ * Skip past "filler" between blocks in multi-PCI-image files.
+ *
+ *
+ **************************************************************************** */
+
+
+/* **************************************************************************
+ *
+ * Still to be done:
+ * Print (as remarks) full descriptions of headers' fields
+ * Error check for wrong "Format"
+ * Skip past non-FCode blocks, thru multiple data-blocks
+ * Recognize PCI header in unexpected place or out-of-place
+ *
+ **************************************************************************** */
+
+#include "pcihdr.h"
+#include <stdio.h>
+
+#include "detok.h"
+
+
+/* **************************************************************************
+ *
+ * Global Variables Exported
+ * pci_image_end Pointer to just after end of current PCI image
+ *
+ **************************************************************************** */
+
+u8 *pci_image_end = NULL;
+
+/* **************************************************************************
+ *
+ * Internal Static Variables
+ * pci_image_len Length (in bytes) of current PCI image
+ *
+ **************************************************************************** */
+
+static int pci_image_len = 0;
+
+
+/* **************************************************************************
+ *
+ * Function name: is_pci_header ( rom_header_t *pci_rom_hdr )
+ * Synopsis: Indicate whether given pointer is pointing to
+ * something that might be a valid PCI header
+ *
+ * Inputs:
+ * Parameters:
+ * pci_rom_hdr pointer to start of data-stream to examine.
+ * Treat as pointer to rom_header_t
+ *
+ * Outputs:
+ * Returned Value: An integer.
+ * 0 Definitely *NOT* a PCI header
+ * Positive Number Appears to be a valid PCI header;
+ * value is offset to PCI Data Structure.
+ * Negative Number Appears to be a PCI header, but
+ * with errors. (Not Implemented Yet.
+ * See under "Still to be done".)
+ *
+ * Error Detection:
+ * (See under "Still to be done".)
+ *
+ * Process Explanation:
+ * Examine "signature" location for known value 0x55aa
+ * If a match, return value of "dptr" (Data-pointer offset) field.
+ *
+ * Revision History:
+ * Created Tue, 01 Feb 2005 by David L. Paktor
+ *
+ * Still to be done:
+ * Error-check; look for inconsistencies:
+ * Return a Negative Number if data-stream appears to be a PCI
+ * header, but has erroneous or inconsistent sub-field contents.
+ * Value and meaning of the Negative Number yet to be defined.
+ *
+ **************************************************************************** */
+
+static int is_pci_header ( rom_header_t *pci_rom_hdr )
+{
+ const u16 pci_header_signature = 0x55aa;
+ int retval ;
+
+ retval = 0;
+
+ if ( BIG_ENDIAN_WORD_FETCH(pci_rom_hdr->signature) == pci_header_signature )
+ {
+ retval = LITTLE_ENDIAN_WORD_FETCH(pci_rom_hdr->data_ptr);
+ }
+ return(retval);
+}
+
+/* **************************************************************************
+ *
+ * Function name: is_pci_data_struct ( pci_data_t *pci_data_ptr )
+ * Synopsis: Indicate whether given pointer is pointing to
+ * a valid PCI Data Structure
+ *
+ * Inputs:
+ * Parameters:
+ * pci_data_ptr pointer to start of data-stream to examine.
+ * Treat as pointer to pci_data_t
+ *
+ * Outputs:
+ * Returned Value: An integer.
+ * 0 Definitely *NOT* a PCI Data Structure
+ * Positive Number Appears to be valid PCI Data Structure;
+ * value is length of PCI Data Structure,
+ * (presumably, offset to start of FCode).
+ * Negative Number Appears to be a PCI Data Structure,
+ * but with errors. (Not Implemented Yet.
+ * See under "Still to be done".)
+ *
+ * Global/Static Variables:
+ * Does not alter the poiner passed-in;
+ * does not alter any Global/Static Variables
+ * Printout: NONE
+ *
+ * Error Detection: (Condition) (Action)
+ * (See under "Still to be done".)
+ *
+ * Process Explanation:
+ * Examine "signature" location for known value "PCIR"
+ * If a match, return value of "dlen" (Data Structure Length) field.
+ *
+ * Revision History:
+ * Created Tue, 01 Feb 2005 by David L. Paktor
+ *
+ * Still to be done:
+ * Error-check; look for wrong "Code Type" or other inconsistencies:
+ * Return a Negative Number if data-stream appears to be a
+ * valid PCI Data Structure, but has erroneous or inconsistent
+ * sub-field contents.
+ * Value and meaning of the Negative Number yet to be defined.
+ * Skip past non-FCode data-blocks, even multiple blocks
+ *
+ **************************************************************************** */
+
+static int is_pci_data_struct ( pci_data_t *pci_data_ptr )
+{
+ int retval ;
+
+ retval = 0;
+
+ if (BIG_ENDIAN_LONG_FETCH(pci_data_ptr->signature) == PCI_DATA_HDR)
+ {
+ retval = LITTLE_ENDIAN_WORD_FETCH(pci_data_ptr->dlen);
+ }
+ return(retval);
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: announce_pci_hdr ( rom_header_t *pci_rom_hdr )
+ * Synopsis: Print indication that the PCI header was found,
+ * and other details, formatted as FORTH remarks.
+ *
+ * Inputs:
+ * Parameters:
+ * pci_rom_hdr Pointer to start of PCI header.
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Printout: Announcement. Size of data_ptr field.
+ *
+ **************************************************************************** */
+
+static void announce_pci_hdr ( rom_header_t *pci_rom_hdr )
+{
+ char temp_buf[80];
+ u32 temp;
+
+ printremark ( "PCI Header identified");
+ temp=(u32)LITTLE_ENDIAN_WORD_FETCH(pci_rom_hdr->data_ptr);
+ sprintf(temp_buf, " Offset to Data Structure = 0x%04x (%d)\n",
+ temp, temp);
+ printremark ( temp_buf );
+}
+
+/* **************************************************************************
+ *
+ * Function name: announce_pci_data_struct ( pci_data_t *pci_data_ptr )
+ * Synopsis: Print indication that the PCI Data Structure
+ * was found, and some additional details.
+ * Format as FORTH remarks.
+ *
+ * Inputs:
+ * Parameters:
+ * pci_data_ptr Pointer to start of PCI Data Structure.
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global/Static Variables:
+ * pci_image_len Updated to byte-length of current PCI image
+ * Printout: (See Synopsis)
+ *
+ * Process Explanation:
+ * Extract some details, format and print them,
+ * using the syntax of FORTH remarks.
+ *
+ * Revision History:
+ * Created Tue, 01 Feb 2005 by David L. Paktor
+ * Updated Wed, 25 May 2005 by David L. Paktor
+ * Added printout of several fields...
+ *
+ **************************************************************************** */
+
+static void announce_pci_data_struct ( pci_data_t *pci_data_ptr )
+{
+ char temp_buf[80];
+ u32 temp;
+
+ printremark ( "PCI Data Structure identified");
+
+ temp=(u32)LITTLE_ENDIAN_WORD_FETCH(pci_data_ptr->dlen);
+ sprintf(temp_buf, " Data Structure Length = 0x%04x (%d)\n", temp, temp);
+ printremark ( temp_buf );
+
+ sprintf(temp_buf, " Vendor ID: 0x%04x\n",
+ LITTLE_ENDIAN_WORD_FETCH(pci_data_ptr->vendor));
+ printremark ( temp_buf );
+
+ sprintf(temp_buf, " Device ID: 0x%04x\n",
+ LITTLE_ENDIAN_WORD_FETCH(pci_data_ptr->device));
+ printremark ( temp_buf );
+
+ temp=(u32)CLASS_CODE_FETCH(pci_data_ptr->class_code);
+ sprintf(temp_buf, " Class Code: 0x%06x (%s)",
+ temp, pci_device_class_name(temp));
+ printremark ( temp_buf );
+
+ temp=(u32)LITTLE_ENDIAN_WORD_FETCH(pci_data_ptr->vpd);
+ if ( temp != 0 )
+ {
+ sprintf(temp_buf, " Vital Prod Data: 0x%02x\n", temp);
+ printremark ( temp_buf );
+ }
+
+ temp=(u32)LITTLE_ENDIAN_WORD_FETCH(pci_data_ptr->irevision);
+ if ( temp != 0 )
+ {
+ sprintf(temp_buf, " Image Revision: 0x%02x\n", temp);
+ printremark ( temp_buf );
+ }
+
+ sprintf(temp_buf, " Code Type: 0x%02x (%s)\n", pci_data_ptr->code_type,
+ pci_code_type_name(pci_data_ptr->code_type) );
+ printremark ( temp_buf );
+
+ temp=(u32)LITTLE_ENDIAN_WORD_FETCH(pci_data_ptr->ilen);
+ pci_image_len = temp*512;
+ sprintf(temp_buf, " Image Length: 0x%04x blocks (%d bytes)\n",
+ temp, pci_image_len);
+ printremark ( temp_buf );
+
+ sprintf(temp_buf, " %sast PCI Image.\n",
+ pci_data_ptr->last_image_flag&&0x80 != 0 ? "L" : "Not l");
+ printremark ( temp_buf );
+
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: handle_pci_header
+ * Synopsis: Handle PCI Header/Data at beginning of FCode file;
+ * facilitate "skipping" over to actual FCode data.
+ *
+ * Inputs:
+ * Parameters:
+ * data_ptr Pointer to start of data-stream to examine.
+ * Global/Static Variables:
+ * pci_image_len Length (in bytes) of current PCI image
+ *
+ * Outputs:
+ * Returned Value:
+ * Positive Number. Offset to start of FCode.
+ * Zero If no PCI header; may be treated as
+ * a valid offset.
+ * Negative Number PCI header or PCI Data Structure test
+ * returned error indication.
+ * (Not Implemented Yet. See
+ * under "Still to be done".)
+ * Global/Static Variables:
+ * pci_image_end Pointer to just after the end of
+ * the current PCI image
+ * Printout: As FORTH remarks, print indications that the
+ * PCI header was found, and maybe later more data.
+ *
+ * Error Detection: (Condition) (Action)
+ * (See under "Still to be done".)
+ *
+ * Process Explanation:
+ * Use the various support routines defined below.
+ *
+ *
+ * Revision History:
+ *
+ * Updated Wed, 09 Feb 2005 by David L. Paktor
+ * Extracted assignments from within if( ) statements.
+ *
+ * Created Tue, 01 Feb 2005 by David L. Paktor
+ *
+ * Still to be done:
+ * Handle error cases. At present, neither is_pci_header()
+ * nor is_pci_data_struct() returns a negative number,
+ * but when they are modified to do so, we must handle it.
+ *
+ **************************************************************************** */
+
+int handle_pci_header ( u8 *data_ptr )
+{
+ int hdrlen;
+ int data_struc_len;
+ /* int retval; */ /* Not needed until we handle error cases... */
+
+ data_struc_len = 0;
+
+ hdrlen = is_pci_header( (rom_header_t *)data_ptr );
+ /* retval = hdrlen; */ /* Not needed yet... */
+ if ( hdrlen < 0 )
+ {
+ /* Handle error case... */
+ /* Leave null for now... */
+ /* It might need to do a premature EXIT here... */
+ } else {
+ /* if hdrlen == 0 then we don't need to check a Data Structure */
+ if ( hdrlen > 0 )
+ {
+ announce_pci_hdr ( (rom_header_t *)data_ptr );
+ data_struc_len = is_pci_data_struct(
+ (pci_data_t *) &data_ptr[hdrlen] );
+ /*
+ * A Data Structure Length of Zero would be an error
+ * that could be detected by is_pci_data_struct()
+ */
+ if ( data_struc_len <= 0 )
+ {
+ /* Handle error case... */
+ /* Leave null for now... */
+ /* It might need to do a premature EXIT here... */
+ /* retval = -1; */ /* Not needed yet... */
+ } else {
+ announce_pci_data_struct ( (pci_data_t *) &data_ptr[hdrlen] );
+ pci_image_end = data_ptr + pci_image_len;
+ /* retval = hdrlen+data_struc_len; */ /* Not needed yet... */
+ }
+ }
+ }
+ return (hdrlen+data_struc_len);
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: handle_pci_filler
+ * Synopsis: Examine and report on the "filler" padding after the
+ * end of an FCode-block but still within a PCI-image
+ *
+ * Inputs:
+ * Parameters:
+ * filler_ptr Pointer to start of PCI-filler in data-stream
+ * Global/Static Variables:
+ * pci_image_end Pointer to just after the end of
+ * the current PCI image
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Printout:
+ * Descriptive message.
+ *
+ * Error Detection:
+ * Non-zero filler field. Different message.
+ *
+ * Process Explanation:
+ * The calling routine has checked that there was, indeed, a PCI
+ * header present, so we know that pci_image_end is valid.
+ * If the entire filler is zero-bytes, print a simple message and
+ * we're out'a here!
+ * If there are non-zero bytes, identify loc'n of first non-zero.
+ *
+ * Still to be done:
+ * Come up with something more elegant for non-zero filler.
+ *
+ **************************************************************************** */
+
+void handle_pci_filler(u8 *filler_ptr)
+{
+ u8 *scan_ptr;
+ int filler_len;
+ char temp_buf[80];
+ bool all_zero = TRUE;
+ u8 filler_byte = *filler_ptr;
+
+ filler_len = pci_image_end - filler_ptr;
+
+ for ( scan_ptr = filler_ptr;
+ scan_ptr < pci_image_end;
+ filler_byte = *(++scan_ptr) )
+ {
+ if ( filler_byte != 0 )
+ {
+ all_zero = FALSE;
+ break;
+ }
+ }
+
+ if ( all_zero )
+ {
+ sprintf(temp_buf, "PCI Image padded with %d bytes of zero", filler_len);
+ }else{
+ sprintf(temp_buf, "PCI Image padding-field of %d bytes "
+ "had first non-zero byte at offset %ld",
+ filler_len, scan_ptr - filler_ptr );
+ }
+ printremark ( temp_buf );
+}
Added: fcode-utils/detok/printformats.c
===================================================================
--- fcode-utils/detok/printformats.c (rev 0)
+++ fcode-utils/detok/printformats.c 2006-08-18 12:47:12 UTC (rev 76)
@@ -0,0 +1,140 @@
+/*
+ * OpenBIOS - free your system!
+ * ( FCode tokenizer )
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 2001-2005 Stefan Reinauer, <stepan(a)openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+/* **************************************************************************
+ *
+ * Print, in various controlled formats, for the detokenizer.
+ *
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Module Author: David L. Paktor dlpaktor(a)us.ibm.com
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Ultimately, our goal is to produce output that can be run back
+ * through the tokenizer and produce the same binary. So, any
+ * extra text will have to be in a form that the tokenizer will
+ * treat as comments.
+ *
+ **************************************************************************** */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "detok.h"
+
+
+/* **************************************************************************
+ *
+ * Function name: printremark ( string )
+ * Synopsis: Print the given string as a series of "Remark" lines,
+ * (i.e., preceded by backslash-space)
+ *
+ * Inputs:
+ * Parameters:
+ * str Pointer to the start of the string,
+ * however long it may be. The string
+ * may have any number of embedded new-lines.
+ *
+ * Outputs:
+ * Returned Value: *** NONE***
+ * Printout: Each line of the string will be preceded by
+ * a backslash and two spaces. Backslash-space
+ * is the standard delimiter for a "remark", i.e.
+ * the entire line is ignored as a comment. The
+ * second space is "just" for aesthetics.
+ *
+ * Process Explanation:
+ * Parse the input string for new-lines. Print each separately.
+ * Do not alter the input string.
+ *
+ *
+ * Still to be done:
+ * Define a routine, call it PrintComment , to print the given
+ * string surrounded by open-paren-space ... space-close-paren
+ * Define a single central routine, call it safe_malloc ,
+ * to do the test for null and print "No Memory" and exit.
+ * Define a single central routine, call it PrintError , to:
+ * Print the given error message
+ * Show the input file and line number
+ * Collect error-flags for failure-exit at end of operation.
+ *
+ **************************************************************************** */
+
+void printremark ( char *str)
+{
+ char *strtmp ; /* Temporary pointer to current substring */
+ int substrlen ; /* Length of current substring */
+ char *substrend ; /* Pointer to end of current substring */
+ char *strend ; /* Pointer to end of given string */
+
+ char *strbfr ; /* Temporary substring buffer */
+
+ /* Guarantee that the malloc will be big enough. */
+ strbfr = (char *)malloc(strlen((char *)str)+1);
+ if ( !strbfr )
+ {
+ printf ("No memory.\n");
+ exit(-1);
+ }
+
+
+ strtmp = str;
+ strend = &str[strlen(str)];
+
+ /* ******************************************************************
+ *
+ * Isolate the current substring; allow that the given
+ * string might not be terminated with a new-line.
+ *
+ * The strend pointer provides a convenient means to
+ * test for when we've reached the end.
+ *
+ ******************************************************************** */
+
+ while ( strtmp < strend )
+ {
+ substrend = strchr(strtmp , '\n');
+ substrlen = ( substrend ? (substrend-strtmp) : strlen(strtmp) );
+
+ strncpy (strbfr, strtmp, substrlen);
+ /* **********************************************************
+ *
+ * strncpy() does not append a terminating null character,
+ * so we have to.
+ *
+ ************************************************************ */
+ strbfr[substrlen] = (char)0;
+
+ printf("\\ %s\n",strbfr);
+
+ strtmp = &strtmp[ substrlen + ( substrend ? 1 : 0 ) ] ;
+
+ }
+
+ free(strbfr) ;
+}
+
Modified: fcode-utils/detok/stream.c
===================================================================
--- fcode-utils/detok/stream.c 2006-08-18 09:45:11 UTC (rev 75)
+++ fcode-utils/detok/stream.c 2006-08-18 12:47:12 UTC (rev 76)
@@ -24,20 +24,60 @@
*
*/
+/* **************************************************************************
+ * Modifications made in 2005 by IBM Corporation
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Modifications Author: David L. Paktor dlpaktor(a)us.ibm.com
+ **************************************************************************** */
+
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/stat.h>
+#include <setjmp.h>
+#include "stream.h"
#include "detok.h"
+#include "pcihdr.h"
-extern bool offs16;
-extern u32 fcpos;
+extern jmp_buf eof_exception;
+/* **************************************************************************
+ *
+ * Global Variables Exported:
+ * Name Value
+ * fcode The FCode-token last read. Not necessarily the byte
+ * last read, if its function has in-line parameters
+ * stream_max The maximum position -- length -- of the input stream
+ * pc Pointer to "Current byte" in the input-data image.
+ * max Just after the end of the input-data image.
+ * This is *NOT* a byte-count.
+ *
+ **************************************************************************** */
+
u16 fcode;
-u8 inbyte;
+unsigned int stream_max;
+u8 *pc;
+u8 *max;
-static u8 *indata, *pc, *max;
+/* **************************************************************************
+ *
+ * Local/Static Variables:
+ * Name Pointer to:
+ * indata Start of input-data image taken from input file.
+ * This memory was "malloc"ed; keep it around
+ * for when we "free" that memory.
+ * fc_start Start of the FCode. This might not be the same
+ * as the start of the input file data, especially
+ * if the input file data starts with a PCI header.
+ * pci_image_found TRUE iff a valid PCI header was found
+ *
+ **************************************************************************** */
+u8 *indata;
+static u8 *fc_start;
+static bool pci_image_found = FALSE;
+
int init_stream(char *name)
{
FILE *infile;
@@ -62,119 +102,455 @@
fclose(infile);
pc=indata;
+ fc_start = indata;
max=pc+finfo.st_size;
+ stream_max = finfo.st_size;
+
return 0;
}
-int close_stream(void)
+/* **************************************************************************
+ *
+ * Function name: init_fcode_block
+ * Synopsis: Initialize all pointers and variables, etcetera,
+ * for an FCode-block.
+ *
+ **************************************************************************** */
+
+void init_fcode_block(void)
{
+ fc_start = pc;
+ linenum = 1 ;
+}
+
+
+void close_stream(void)
+{
free(indata);
- return 0;
+ stream_max = 0;
}
int get_streampos(void)
{
- return (int)((long)pc-(long)indata);
+ return (int)( pc - fc_start );
}
-void set_streampos(long pos)
+void set_streampos(int pos)
{
- pc=indata+pos;
+ pc = fc_start + pos;
}
-static int get_byte(void)
+
+/* **************************************************************************
+ *
+ * Function name: throw_eof
+ * Synopsis: Analyze and print the cause of the end-of-file
+ * and throw an exception.
+ *
+ * Inputs:
+ * Parameters:
+ * premature TRUE iff end-of-file was out-of-sync
+ * Global/Static Variables:
+ * end_found Indicates if normal end of fcode was read.
+ * eof_exception Long-Jump environment to which to jump.
+ *
+ * Outputs: Does a Long-Jump
+ * Returned Value: NONE
+ * Printout:
+ * "End-of-file" message, along with a descriptor, if applicable:
+ * Premature, Unexpected.
+ * The calling routine notifies us if the number of bytes requested
+ * overflowed the input buffer, by passing us a TRUE for the
+ * input parameter. That is a "Premature" end-of-file.
+ * If end_found is FALSE, it means the normal end of FCode
+ * wasn't seen. That is an "Unexpected" end-of-file.
+ *
+ **************************************************************************** */
+
+static void throw_eof(bool premature)
{
- inbyte=*pc;
- pc++;
+ char yoo = 'U';
+ char eee = 'E';
+ if ( premature)
+ {
+ printf("Premature ");
+ yoo = 'u';
+ eee = 'e';
+ }
+ if ( ! end_found )
+ {
+ printf("%cnexpected ",yoo);
+ eee = 'e';
+ }
+ printf("%cnd of file.\n",eee);
+ longjmp(eof_exception, -1);
+}
- if (pc>max) {
- printf ("\nUnexpected end of file.\n");
- return 0;
+/* **************************************************************************
+ *
+ * Function name: get_bytes
+ * Synopsis: Return the next string of bytes, as requested, from
+ * the FCode input-stream. Detect end-of-file
+ *
+ * Inputs:
+ * Parameters:
+ * nbytes The number of bytes requested
+ * Global/Static Variables:
+ * pc Pointer to "where we are" in the FCode
+ * max Pointer to just after end of input file data.
+ *
+ * Outputs:
+ * Returned Value:
+ * Pointer to the requested bytes in the FCode input-stream.
+ * Global/Static Variables:
+ * pc Incremented by the number of bytes requested
+ *
+ * Exception:
+ * When end-of-file is reached, or is about to be exceeded,
+ * throw an end-of-file exception.
+ *
+ * Process Explanation:
+ * End-of-file is not exactly an error, so its detection is more
+ * a part of normal processing.
+ * If we entered this routine with PC pointing exactly at MAX,
+ * we are probably at the end the way we expect to be, so we
+ * call our EOF-handling routine with a "non-premature" flag.
+ * If the requested number of bytes puts us just even with MAX,
+ * we have neither reached nor over-run the input stream, so
+ * there's no call to our EOF-handling routine needed at all.
+ * Only if the requested number of bytes puts us past MAX have we
+ * over-run our input stream with a "premature" condition.
+ *
+ * Extraneous Remarks:
+ * This is another one where it was easier to write the code
+ * than the explanation ... ;-}
+ *
+ **************************************************************************** */
+
+static u8 *get_bytes(int nbytes)
+{
+ u8 *retval = pc;
+ if ( pc == max )
+ {
+ throw_eof(FALSE);
+ }
+ if ( pc + nbytes > max )
+ {
+ throw_eof(TRUE);
+ }
+ pc += nbytes;
+ return( retval);
}
- return 1;
+
+/* **************************************************************************
+ *
+ * Function name: more_to_go
+ * Synopsis: Return FALSE when the last byte has been
+ * read from the input-stream.
+ *
+ **************************************************************************** */
+
+bool more_to_go(void)
+{
+ bool retval;
+ retval = INVERSE( pc == max );
+ return( retval);
}
-u16 get_token(void)
+
+/* **************************************************************************
+ *
+ * Function name: next_token
+ * Synopsis: Retrieve the next FCode-token from the input-stream.
+ *
+ * Inputs:
+ * Parameters: NONE
+ *
+ * Outputs:
+ * Returned Value: The next FCode-token
+ * Global/Static Variables:
+ * fcode The FCode-token last read.
+ * token_streampos Streampos() of token just gotten
+ *
+ **************************************************************************** */
+
+u16 next_token(void)
{
u16 tok;
- get_byte();
- tok=inbyte;
- if (tok != 0x00 && tok < 0x10) {
- get_byte();
+ token_streampos = get_streampos();
+ tok = *(get_bytes(1));
+ if ( tok != 0x00 && tok < 0x10)
+ {
tok<<=8;
- tok|=inbyte;
+ tok |= *(get_bytes(1));
}
fcode=tok;
- return tok;
+ return(tok);
}
u32 get_num32(void)
{
- u32 ret;
+ u32 retval;
+ u8 *num_str;
- get_byte();
- ret=inbyte<<24;
- get_byte();
- ret|=(inbyte<<16);
- get_byte();
- ret|=(inbyte<<8);
- get_byte();
- ret|=inbyte;
+ num_str = get_bytes(4);
+ retval = BIG_ENDIAN_LONG_FETCH(num_str);
- return ret;
+ return ( retval);
}
u16 get_num16(void)
{
- u16 ret;
+ u16 retval;
+ u8 *num_str;
- get_byte();
- ret=inbyte<<8;
- get_byte();
- ret|=inbyte;
+ num_str = get_bytes(2);
+ retval = BIG_ENDIAN_WORD_FETCH(num_str);
- return ret;
+ return ( retval);
}
u8 get_num8(void)
{
- get_byte();
+ u8 inbyte;
+
+ inbyte = *(get_bytes(1));
return(inbyte);
}
-u16 get_offset(void)
+s16 get_offset(void)
{
+ s16 retval;
if (offs16)
- return (get_num16());
+ {
+ retval = (s16)get_num16();
+ }else{
+ retval = (s16)get_num8();
+ /* Make sure it's sign-extended */
+ retval |= ( retval & 0x80 ) ? 0xff00 : 0 ;
+ }
- return (get_num8());
+ return (retval);
}
+/* **************************************************************************
+ *
+ * Function name: get_string
+ * Synopsis: Return a pointer to a Forth-Style string within the
+ * input stream. Note: this cannot be used to create
+ * a new token-name; use get_name() for that.
+ *
+ * Inputs:
+ * Parameters:
+ * *len Pointer to where the length will go
+ *
+ * Outputs:
+ * Returned Value:
+ * Pointer to the string within the input stream.
+ * Supplied Pointers:
+ * *len Length of the string
+ *
+ * Process Explanation:
+ * Get one byte representing the length of the FORTH-style string.
+ * Get as many bytes as the length indicates.
+ * That's the string. The pointer returned by get_bytes() is
+ * our return value.
+ *
+ **************************************************************************** */
-int scnt=0;
-u8 *get_string(void)
+u8 *get_string(u8 *len)
{
- u8 *data;
- u8 size;
- unsigned int i;
+ char *retval;
+
+ *len = get_num8();
+ retval = get_bytes((int)*len);
- get_byte();
- size=inbyte;
+ return (retval);
+}
- scnt++;
- data=malloc(size+2);
- if (!data) printf ("No more memory.\n");
- data[0]=size;
+/* **************************************************************************
+ *
+ * Function name: get_name
+ * Synopsis: Retrieve a copy of the next string in the input-stream
+ * when it is expected to be a new function-name.
+ *
+ * Inputs:
+ * Parameters:
+ * *len Pointer to where the length will go
+ * Global/Static Variables:
+ * pc "Where we are" in the file-stream
+ *
+ * Outputs:
+ * Returned Value:
+ * Pointer to allocated memory containing a copy of the string
+ * Supplied Pointers:
+ * *len Length of the name
+ * Memory Allocated
+ * Memory for the copy of the string is allocated by strdup()
+ * When Freed?
+ * Never. Retained for duration of the program.
+ *
+ * Process Explanation:
+ * Get the FORTH-style string.
+ * At this point, PC points to the byte that follows the string;
+ * we are going to save that byte and replace it with a zero,
+ * thus creating a C-style string.
+ * We will pass that C-style string as an argument to strdup() ,
+ * which will give us our return value.
+ * Then, of course, we restore the byte we so rudely zeroed, and
+ * proceed merrily on our way.
+ *
+ **************************************************************************** */
+
+char *get_name(u8 *len)
+{
+ char *str_start;
+ char *retval;
+ u8 sav_byt;
- for (i=1; i<size+1; i++) {
- get_byte();
- data[i]=inbyte;
+ str_start = get_string( len );
+
+ sav_byt = *pc;
+ *pc = 0;
+
+ retval = strdup(str_start);
+ *pc = sav_byt;
+
+ return (retval);
}
- data[i]=0;
- return data;
+/* **************************************************************************
+ *
+ * Function name: calc_checksum
+ * Synopsis: Calculate the checksum.
+ * Leave the input position unchanged.
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global/Static Variables:
+ * pc Pointer to "where we are" in the file-stream
+ *
+ * Outputs:
+ * Returned Value: Calculated checksum.
+ * Global/Static Variables:
+ * pc Reset to value upon entry
+ *
+ * Process Explanation:
+ * When this routine is entered, the PC is presumed to be pointing
+ * just after the stored checksum, and just before the length
+ * field in the FCode header. This is the point at which we
+ * will preserve the PC
+ * Extract the length from the FCode header. It includes the eight
+ * bytes of the FCode header, so we will need to adjust for that.
+ * The first byte after the FCode header is where the checksum
+ * calculation begins.
+ *
+ **************************************************************************** */
+
+u16 calc_checksum(void)
+{
+ u16 retval = 0;
+ u8 *cksmptr;
+ u8 *save_pc;
+ u32 fc_blk_len;
+ int indx;
+
+ save_pc = pc;
+
+ fc_blk_len = get_num32(); /* Read len */
+ cksmptr = get_bytes(fc_blk_len-8); /* Make sure we have all our data */
+
+ for ( indx = 8; indx < fc_blk_len; indx++)
+ {
+ retval += *cksmptr++;
}
+ pc = save_pc;
+ return( retval);
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: adjust_for_pci_header
+ * Synopsis: Skip the PCI Header. Adjust the pointer to
+ * the start of FCode in the file-stream,
+ * and our pointer to "where we are" in the FCode,
+ * by the size of the PCI header.
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global/Static Variables: (Pointer to:)
+ * pc "where we are" in the file-stream
+ * fc_start start of FCode in the file-stream
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global/Static Variables:
+ * pc Advanced past PCI header
+ * fc_start Likewise.
+ * pci_image_found Set or cleared as appropriate.
+ * last_defined_token Re-initialized
+ *
+ * Process Explanation:
+ * Call handle_pci_header to get the size of the PCI header,
+ * if any, and increment pc and fc_start by the number
+ * of bytes it returns; also, set pci_image_found based
+ * on whether the "size of the PCI header" was non-zero.
+ * (Re-)Initialize overlap detection here. Images with multiple
+ * PCI blocks can safely re-cycle FCode numbers; this is
+ * not necessarily true of multiple FCode blocks within
+ * the same PCI block...
+ *
+ **************************************************************************** */
+
+void adjust_for_pci_header(void)
+{
+ int pci_header_size;
+
+ pci_header_size = handle_pci_header(pc);
+ pci_image_found = pci_header_size > 0 ? TRUE : FALSE;
+ pc += pci_header_size;
+ fc_start += pci_header_size;
+ last_defined_token = 0;
+}
+
+/* **************************************************************************
+ *
+ * Function name: adjust_for_pci_filler
+ * Synopsis: Dispatch call to pci-filler-handler
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global/Static Variables:
+ * pci_image_found Whether to proceed...
+ * pci_image_end Pointer to just after the end of
+ * the current PCI image
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global/Static Variables:
+ * pci_image_found Reset to FALSE
+ *
+ * Error Detection:
+ * Confirm that the data-stream has the complete filler,
+ * via a call to get_bytes()
+ *
+ **************************************************************************** */
+
+void adjust_for_pci_filler(void)
+{
+ if ( pci_image_found )
+ {
+ int pci_filler_len;
+ u8 *pci_filler_ptr;
+
+ pci_filler_len = pci_image_end - pc;
+ pci_filler_ptr = get_bytes(pci_filler_len);
+ handle_pci_filler( pci_filler_ptr );
+ pci_image_found = FALSE;
+ }
+}
Modified: fcode-utils/detok/stream.h
===================================================================
--- fcode-utils/detok/stream.h 2006-08-18 09:45:11 UTC (rev 75)
+++ fcode-utils/detok/stream.h 2006-08-18 12:47:12 UTC (rev 76)
@@ -1,3 +1,6 @@
+#ifndef _UTILS_DETOK_STREAM_H
+#define _UTILS_DETOK_STREAM_H
+
/*
* OpenBIOS - free your system!
* ( detokenizer )
@@ -24,16 +27,42 @@
*
*/
+/* **************************************************************************
+ * Modifications made in 2005 by IBM Corporation
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Modifications Author: David L. Paktor dlpaktor(a)us.ibm.com
+ **************************************************************************** */
+
+#include "types.h"
+
+/* Prototypes for functions exported from stream.c */
+
+
int init_stream(char *name);
-int close_stream(void);
+void close_stream(void);
+bool more_to_go(void);
+void adjust_for_pci_header(void);
+void adjust_for_pci_filler(void);
+void init_fcode_block(void);
+
int get_streampos(void);
-void set_streampos(long pos);
+void set_streampos(int pos);
-u16 get_token(void);
+u16 next_token(void);
u8 get_num8(void);
u16 get_num16(void);
u32 get_num32(void);
-u16 get_offset(void);
-u8 *get_string(void);
+s16 get_offset(void);
+u8 *get_string(u8 *len);
+char *get_name(u8 *len);
+u16 calc_checksum(void);
+/* External declarations for variables defined in stream.c */
+
+extern unsigned int stream_max;
+extern u8 *indata;
+extern u8 *pc;
+extern u8 *max;
+
+#endif /* _UTILS_DETOK_STREAM_H */
Modified: fcode-utils/romheaders/Makefile
===================================================================
--- fcode-utils/romheaders/Makefile 2006-08-18 09:45:11 UTC (rev 75)
+++ fcode-utils/romheaders/Makefile 2006-08-18 12:47:12 UTC (rev 76)
@@ -21,20 +21,21 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
#
-
CC = gcc
-CFLAGS= -O2 -Wall -W -ansi
+CFLAGS= -O2 -Wall -W -ansi -I../shared
-.SUFFIXES: .c .o
+SOURCES = romheaders.c ../shared/classcodes.c
+.SUFFIXES: .c
+
all: romheaders
-romheaders: romheaders.o
- $(CC) $(CFLAGS) romheaders.o -o romheaders
+romheaders: $(SOURCES)
+ $(CC) $(CFLAGS) $(SOURCES) -o $@
strip romheaders
clean:
- rm -f *.o
+ rm -f *~
distclean: clean
rm -f romheaders
Modified: fcode-utils/romheaders/romheaders.c
===================================================================
--- fcode-utils/romheaders/romheaders.c 2006-08-18 09:45:11 UTC (rev 75)
+++ fcode-utils/romheaders/romheaders.c 2006-08-18 12:47:12 UTC (rev 76)
@@ -23,6 +23,11 @@
*
*/
+/* **************************************************************************
+ * Modifications made in 2005 by IBM Corporation
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Modifications Author: David L. Paktor dlpaktor(a)us.ibm.com
+ **************************************************************************** */
#include <stdio.h>
#include <stdlib.h>
@@ -30,60 +35,32 @@
#include <sys/stat.h>
#include <unistd.h>
-#define u8 unsigned char
-#define u16 unsigned short
-#define u32 unsigned int
+#include "pcihdr.h"
-#define PCI_DATA_HDR (u32) ( ('R' << 24) | ('I' << 16) | ('C' << 8) | 'P' )
-
-typedef struct {
- u16 signature;
- u8 reserved[0x16];
- u16 dptr;
-} rom_header_t;
-
-typedef struct {
- u32 signature;
- u16 vendor;
- u16 device;
- u16 reserved_1;
- u16 dlen;
- u8 drevision;
- u8 class_hi;
- u16 class_lo;
- u16 ilen;
- u16 irevision;
- u8 type;
- u8 indicator;
- u16 reserved_2;
-} pci_data_t;
-
char *rom=NULL;
size_t romlen=0;
-/* make this endian safe without fancy system headers */
-static u16 little_word(u16 val)
-{
- u8 *ptr=(u8 *)&val;
- return (ptr[0]|(ptr[1]<<8));
-}
+/* Prototypes for functions exported from shared/classcodes.c */
-static u16 little_dword(u16 val)
-{
- u8 *ptr=(u8 *)&val;
- return (ptr[0]|(ptr[1]<<8)|(ptr[2]<<16)|(ptr[3]<<24));
-}
+char *pci_device_class_name(u32 code);
+char *pci_code_type_name(unsigned char code);
-/* dump the rom headers */
+/* Functions local to this file:
+ int dump_rom_header(rom_header_t *data);
+ int dump_pci_data(pci_data_t *data);
+ void dump_platform_extensions(u8 type, rom_header_t *data);
+ */
+
static int dump_rom_header(rom_header_t *data)
-{
- u16 sig=little_word(data->signature);
+{ /* Return TRUE for "no problem" */
+ const u16 pci_header_signature = 0x55aa;
+ u16 sig=BIG_ENDIAN_WORD_FETCH(data->signature);
int i;
printf ("PCI Expansion ROM Header:\n");
- printf (" Signature: 0x%02x%02x (%s)\n",
- sig&0xff,sig>>8,sig==0xaa55?"Ok":"Not Ok");
+ printf (" Signature: 0x%04x (%s)\n",
+ sig, sig == pci_header_signature ? "Ok":"Not Ok");
printf (" CPU unique data:");
for (i=0;i<16;i++) {
@@ -92,97 +69,41 @@
}
printf ("\n Pointer to PCI Data Structure: 0x%04x\n\n",
- little_word(data->dptr));
+ LITTLE_ENDIAN_WORD_FETCH(data->data_ptr));
- return (sig==0xaa55);
+ return (sig == pci_header_signature);
}
static int dump_pci_data(pci_data_t *data)
-{
- u32 sig=little_dword(data->signature);
- u32 classcode=(data->class_hi<<16)|(little_word(data->class_lo));
+{ /* Return TRUE for "no problem" */
+ const u32 pci_data_hdr = PCI_DATA_HDR ;
+
+ u32 sig = BIG_ENDIAN_LONG_FETCH(data->signature);
+ u32 classcode= CLASS_CODE_FETCH(data->class_code);
+ u32 dlen = (u32)LITTLE_ENDIAN_WORD_FETCH(data->dlen);
+ u32 ilen = (u32)LITTLE_ENDIAN_WORD_FETCH(data->ilen);
printf("PCI Data Structure:\n");
- printf(" Signature: '%c%c%c%c' (%s)\n", sig&0xff,(sig>>8)&0xff,
- (sig>>16)&0xff, sig>>24, sig==PCI_DATA_HDR?"Ok":"Not Ok");
- printf(" Vendor ID: 0x%04x\n", little_word(data->vendor));
- printf(" Device ID: 0x%04x\n", little_word(data->device));
- printf(" Reserved: 0x%04x\n", little_word(data->reserved_1));
- printf(" PCI Data Structure Length: 0x%04x (%d bytes)\n",
- little_word(data->dlen), little_word(data->dlen));
+ printf(" Signature: 0x%04x '%c%c%c%c' ", sig,
+ sig>>24,(sig>>16)&0xff, (sig>>8)&0xff, sig&0xff);
+ printf("(%s)\n", sig == pci_data_hdr ?"Ok":"Not Ok");
+
+ printf(" Vendor ID: 0x%04x\n", LITTLE_ENDIAN_WORD_FETCH(data->vendor));
+ printf(" Device ID: 0x%04x\n", LITTLE_ENDIAN_WORD_FETCH(data->device));
+ printf(" Vital Product Data: 0x%04x\n",
+ LITTLE_ENDIAN_WORD_FETCH(data->vpd));
+ printf(" PCI Data Structure Length: 0x%04x (%d bytes)\n", dlen, dlen);
printf(" PCI Data Structure Revision: 0x%02x\n", data->drevision);
- printf(" Class Code: 0x%06x (",classcode);
- switch (classcode) {
- case 0x0100:
- printf("SCSI Storage");
- break;
- case 0x0101:
- printf("IDE Storage");
- break;
- case 0x0103:
- printf("IPI Storage");
- break;
- case 0x0104:
- printf("RAID Storage");
- break;
- case 0x0180:
- printf("Storage");
- break;
-
- case 0x0200:
- printf("Ethernet");
- break;
- case 0x0201:
- printf("Token Ring");
- break;
- case 0x0202:
- printf("FDDI");
- break;
- case 0x0203:
- printf("ATM");
- break;
- case 0x0280:
- printf("Network");
-
- case 0x0300:
- printf("VGA Display");
- break;
- case 0x0301:
- printf("XGA Display");
- break;
- case 0x0302:
- printf("3D Display");
- break;
- case 0x0380:
- printf("Display");
- break;
-
- default:
- printf("unkown");
- }
- printf(")\n Image Length: 0x%04x blocks (%d bytes)\n",
- little_word(data->ilen), little_word(data->ilen)*512);
+ printf(" Class Code: 0x%06x (%s)\n",classcode,
+ pci_device_class_name(classcode));
+ printf(" Image Length: 0x%04x blocks (%d bytes)\n", ilen, ilen*512);
printf(" Revision Level of Code/Data: 0x%04x\n",
- little_word(data->irevision));
- printf(" Code Type: 0x%02x (", data->type);
- switch (data->type) {
- case 0:
- printf("Intel x86");
- break;
- case 1:
- printf("Open Firmware");
- break;
- case 2:
- printf("HP PA Risc");
- break;
- case 3:
- printf("Intel EFI (unofficial)");
- break;
- default:
- printf("unknown as of PCI specs 2.2");
- }
- printf(")\n Indicator: 0x%02x %s\n", data->indicator,
- data->indicator&0x80?"(last image in rom)":"");
+ (u32)LITTLE_ENDIAN_WORD_FETCH(data->irevision));
+ printf(" Code Type: 0x%02x (%s)\n", data->code_type,
+ pci_code_type_name(data->code_type) );
+ printf(" Last-Image Flag: 0x%02x (%slast image in rom)\n",
+ data->last_image_flag,
+ data->last_image_flag&0x80?"":"not ");
printf(" Reserved: 0x%04x\n\n", little_word(data->reserved_2));
return (sig==PCI_DATA_HDR);
@@ -225,7 +146,7 @@
printf( " Entry point for INIT function:"
" 0x%x\n\n",entry);
} else
- printf( " Unable to determin entry point for INIT"
+ printf( " Unable to determine entry point for INIT"
" function. Please report.\n\n");
break;
@@ -252,9 +173,9 @@
if (argc!=2) {
printf ("\nUsage: %s <romimage.img>\n",argv[0]);
- printf ("\nromheaders dumps pci option rom headers "
+ printf ("\n romheaders dumps pci option rom headers "
"according to PCI \n"
- "specs 2.2 in human readable form\n\n");
+ " specs 2.2 in human readable form\n\n");
return -1;
}
@@ -290,23 +211,25 @@
do {
printf("\nImage %d:\n",i);
if (!dump_rom_header(rom_header)) {
- printf("Error occured. Bailing out.\n");
+ printf("Rom Header error occured. Bailing out.\n");
break;
}
- pci_data=(pci_data_t *)(rom+little_word(rom_header->dptr));
+ pci_data = (pci_data_t *)((char *)rom_header +
+ LITTLE_ENDIAN_WORD_FETCH(rom_header->data_ptr));
if (!dump_pci_data(pci_data)) {
- printf("Error occured. Bailing out.\n");
+ printf("PCI Data error occured. Bailing out.\n");
break;
}
- dump_platform_extensions(pci_data->type, rom_header);
+ dump_platform_extensions(pci_data->code_type, rom_header);
- rom_header+=little_word(pci_data->ilen)*512;
+ rom_header = (rom_header_t *)((char *)rom_header +
+ LITTLE_ENDIAN_WORD_FETCH(pci_data->ilen)*512);
i++;
- } while ((pci_data->indicator&0x80)!=0x80 &&
- romlen<(unsigned long)rom_header-(unsigned long)romlen);
+ } while ((pci_data->last_image_flag&0x80)!=0x80 &&
+ (char *)rom_header < rom+(int)romlen );
return 0;
}
Modified: fcode-utils/toke/Makefile
===================================================================
--- fcode-utils/toke/Makefile 2006-08-18 09:45:11 UTC (rev 75)
+++ fcode-utils/toke/Makefile 2006-08-18 12:47:12 UTC (rev 76)
@@ -1,11 +1,12 @@
#
-# OpenBIOS - free your system!
-# ( FCode tokenizer )
-#
-# This program is part of a free implementation of the IEEE 1275-1994
+# OpenBIOS - free your system!
+# ( Utilities )
+#
+# This program is part of a free implementation of the IEEE 1275-1994
# Standard for Boot (Initialization Configuration) Firmware.
#
-# Copyright (C) 2001-2005 Stefan Reinauer, <stepan(a)openbios.org>
+# Copyright (C) 2001-2006 Stefan Reinauer <stepan(a)openbios.org>
+# Copyright (C) 2006 coresystems GmbH <info(a)coresystems.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -21,52 +22,39 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
#
-ARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/x86_64/amd64/)
-TOPDIR := $(shell /bin/pwd)
-BUILDDIR ?= $(TOPDIR)/obj-$(ARCH)
-VPATH := $(BUILDDIR)
+PROGRAM = toke
-include $(TOPDIR)/Rules.make
+CC = gcc
+STRIP = strip
+INCLUDES = -I../shared
+#CFLAGS = -O2 -g -Wall
+CFLAGS = -Os -Wall -Wno-pointer-sign -DSYS_IS_GNU_Linux
+LDFLAGS =
-CC = gcc
-CFLAGS = -O2 -Wall -W -ansi -pedantic
-# CFLAGS = -O -g -Wall -ansi -pedantic
+OBJS = clflags.o conditl.o devnode.o dictionary.o emit.o errhandler.o \
+ flowcontrol.o macros.o nextfcode.o parselocals.o scanner.o stack.o \
+ stream.o strsubvocab.o ticvocab.o toke.o tokzesc.o tracesyms.o \
+ usersymbols.o ../shared/classcodes.o
-# CFLAGS := $(CFLAGS) -DDEBUG_SCANNER
-# CFLAGS := $(CFLAGS) -DDEBUG_DSTACK
+all: .dependencies $(PROGRAM)
-OBJECTS= toke.o stack.o stream.o dictionary.o macros.o scanner.o emit.o
+$(PROGRAM): $(OBJS)
+ $(CC) -o $(PROGRAM) $(OBJS) $(LDFLAGS)
+ $(STRIP) -s $(PROGRAM)
-.SUFFIXES: .c .o
+clean:
+ rm -f $(OBJS) *~
-all: main toke
- @cd $(BUILDDIR) && strip toke
- @echo -e "\nOpenBIOS tokenizer toke build finished\n"
+distclean: clean
+ rm -f $(PROGRAM) .dependencies
+
+.dependencies: *.c
+ @$(CC) $(CFLAGS) $(INCLUDES) -MM *.c > .dependencies
-# main should go to rules.make
-main:
- @echo -e "\nWelcome to toke, the OpenBIOS fcode tokenizer.."
- @test -r $(BUILDDIR) || ( mkdir -p $(BUILDDIR); \
- echo -e "\nCreating build directory $(BUILDDIR)" )
+.PHONY: all clean distclean
-toke: $(OBJECTS)
- @echo -n " linking tokenizer executable... "
- @cd $(BUILDDIR) && $(CC) $(CFLAGS) -o $@ $^
- @echo -e "\tok"
-
-clean:
- @test ! -d $(BUILDDIR) && \
- echo "Architecture $(ARCH) is already clean." || \
- ( \
- echo "Cleaning up architecture $(ARCH)"; \
- rm -rf $(BUILDDIR) \
- rm forth.dict.core \
- )
+-include .dependencies
-toke.o: toke.c toke.h stack.h stream.h emit.h
-dictionary.o: dictionary.c toke.h dictionary.h
-emit.o: emit.c toke.h stack.h
-macros.o: macros.c toke.h
-scanner.o: scanner.c toke.h stack.h stream.h dictionary.h
-stack.o: stack.c toke.h stack.h
-stream.o: stream.c toke.h
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCLUDES) $< -o $@
+
Deleted: fcode-utils/toke/Rules.make
===================================================================
--- fcode-utils/toke/Rules.make 2006-08-18 09:45:11 UTC (rev 75)
+++ fcode-utils/toke/Rules.make 2006-08-18 12:47:12 UTC (rev 76)
@@ -1,17 +0,0 @@
-# tag: Makefile rules
-
-VPATH := $(VPATH):.
-
-.S.o:
- echo -n " assembling $<... "
- $(CC) -c -nostdlib $(INCLUDES) $(CFLAGS) $< -o $(BUILDDIR)/$@ && \
- echo -e " \t\tok" || \
- echo -e " \t\tfailed"
-
-.c.o:
- @echo -n " compiling $<... "
- @$(CC) -c $(CFLAGS) $(INCLUDES) $< -o $(BUILDDIR)/$@ && \
- echo -e " \t\tok" || \
- echo -e " \t\failed"
-
-
Added: fcode-utils/toke/clflags.c
===================================================================
--- fcode-utils/toke/clflags.c (rev 0)
+++ fcode-utils/toke/clflags.c 2006-08-18 12:47:12 UTC (rev 76)
@@ -0,0 +1,729 @@
+/*
+ * OpenBIOS - free your system!
+ * ( FCode tokenizer )
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 2001-2005 Stefan Reinauer, <stepan(a)openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+/* **************************************************************************
+ *
+ * Command-Line Flags are used to control certain non-Standard
+ * variant behaviors of the Tokenizer.
+ * Support Functions for setting, clearing, displaying, etc.
+ * Call them "Special-Feature Flags" in messages to the User
+ *
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Module Author: David L. Paktor dlpaktor(a)us.ibm.com
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * For a given CLFlag name, the user may enter either:
+ *
+ * -f CLFlagName
+ * or
+ * -f noCLFlagName
+ *
+ * to either enable or disable the associated function
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Functions Exported:
+ * set_cl_flag Set (or clear) a CL Flag Variable
+ * show_all_cl_flag_settings Show CL Flags' settings unconditionally.
+ * list_cl_flag_settings Display CL Flags' settings if changed.
+ * list_cl_flag_names Display just the names of the CL Flags.
+ * cl_flags_help Help Message for CL Flags
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Revision History:
+ * Updated Mon, 08 Aug 2005 by David L. Paktor
+ * They're not just for setting from the Command-Line anymore,
+ * but let's still keep these names for internal use....
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * The CL_FLAGS data structure has a field for the CLFlagName,
+ * one for a text explanation of the function it controls, and
+ * one for the address of the boolean variable ("flag")
+ *
+ **************************************************************************** */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "clflags.h"
+#include "errhandler.h"
+
+
+/* **************************************************************************
+ *
+ * Global Variables Exported
+ * (The "flags" controlled by this means)
+ *
+ **************************************************************************** */
+
+bool ibm_locals = FALSE ;
+bool ibm_locals_legacy_separator = TRUE ;
+bool ibm_legacy_separator_message = TRUE ;
+bool enable_abort_quote = TRUE ;
+bool sun_style_abort_quote = TRUE ;
+bool abort_quote_throw = TRUE ;
+bool string_remark_escape = TRUE ;
+bool hex_remark_escape = TRUE ;
+bool c_style_string_escape = TRUE ;
+bool always_headers = FALSE ;
+bool always_external = FALSE ;
+bool verbose_dup_warning = TRUE ;
+bool obso_fcode_warning = TRUE ;
+bool trace_conditionals = FALSE ;
+bool big_end_pci_image_rev = FALSE ;
+
+/* And one to trigger a "help" message */
+bool clflag_help = FALSE;
+
+/* **************************************************************************
+ *
+ * The addition of the "upper/lower-case-tokens" flags introduces
+ * some complications. These are the variables we will actually
+ * be exporting:
+ *
+ **************************************************************************** */
+
+bool force_tokens_case = FALSE ;
+bool force_lower_case_tokens = FALSE ;
+
+/* **************************************************************************
+ *
+ * but we will be entering two static variables into the table,
+ * and keep two more to detect when a change is made...
+ *
+ **************************************************************************** */
+static bool upper_case_tokens = FALSE ;
+static bool lower_case_tokens = FALSE ;
+static bool was_upper_case_tk = FALSE ;
+static bool was_lower_case_tk = FALSE ;
+
+/* **************************************************************************
+ *
+ * Internal Static Variables
+ * cl_flag_change A change was made to any of the CL Flags
+ * Internal Static Constants
+ * cl_flags_list List of CL Flags and their data.
+ *
+ **************************************************************************** */
+
+static bool cl_flag_change = FALSE;
+
+static const cl_flag_t cl_flags_list[] = {
+ /* The clflag_tabs field takes at least one tab.
+ * If the name has fewer than 16 characters,
+ * stick in an extra tab, and yet another tab
+ * if the name is shorter than 8 characters
+ * to make the formatting of the "explanation"
+ * come out prettier.
+ */
+ { "Local-Values",
+ &ibm_locals,
+ "\t\t",
+ "Support IBM-style Local Values (\"LV\"s)" } ,
+
+ { "LV-Legacy-Separator",
+ &ibm_locals_legacy_separator,
+ "\t",
+ "Allow Semicolon for Local Values Separator (\"Legacy\")" } ,
+
+ { "LV-Legacy-Message",
+ &ibm_legacy_separator_message,
+ "\t",
+ "Display a Message when Semicolon is used as the "
+ "Local Values Separator" } ,
+
+ { "ABORT-Quote",
+ &enable_abort_quote,
+ "\t\t",
+ "Allow ABORT\" macro" } ,
+
+ { "Sun-ABORT-Quote",
+ &sun_style_abort_quote,
+ "\t\t",
+ "ABORT\" with implicit IF ... THEN" } ,
+
+ { "ABORT-Quote-Throw",
+ &abort_quote_throw,
+ "\t",
+ "Use -2 THROW in an Abort\" phrase, rather than ABORT" } ,
+
+ { "String-remark-escape",
+ &string_remark_escape,
+ "\t",
+ "Allow \"\\ (Quote-Backslash) to interrupt string parsing" } ,
+
+ { "Hex-remark-escape",
+ &hex_remark_escape,
+ "\t",
+ "Allow \\ (Backslash) to interrupt "
+ "hex-sequence parsing within a string" } ,
+
+ { "C-Style-string-escape",
+ &c_style_string_escape ,
+ "\t",
+ "Allow \\n \\t and \\xx\\ for special chars in string parsing" } ,
+
+ { "Always-Headers",
+ &always_headers ,
+ "\t\t",
+ "Override \"headerless\" and force to \"headers\"" } ,
+
+ { "Always-External",
+ &always_external ,
+ "\t\t",
+ "Override \"headerless\" and \"headers\" and "
+ "force to \"external\"" } ,
+
+ { "Warn-if-Duplicate",
+ &verbose_dup_warning ,
+ "\t",
+ "Display a WARNING message when a duplicate definition is made" } ,
+
+ { "Obsolete-FCode-Warning",
+ &obso_fcode_warning ,
+ "\t",
+ "Display a WARNING message when an \"obsolete\" "
+ "(per the Standard) FCode is used" } ,
+
+ { "Trace-Conditionals",
+ &trace_conditionals,
+ "\t",
+ "Display ADVISORY messages about the state of "
+ "Conditional Tokenization" } ,
+
+ { "Upper-Case-Token-Names",
+ &upper_case_tokens,
+ "\t",
+ "Convert Token-Names to UPPER-Case" } ,
+
+
+ { "Lower-Case-Token-Names",
+ &lower_case_tokens,
+ "\t",
+ "Convert Token-Names to lower-Case" } ,
+
+
+ { "Big-End-PCI-Rev-Level",
+ &big_end_pci_image_rev,
+ "\t",
+ "Save the Vendor's Rev Level field of the PCI Header"
+ " in Big-Endian format" } ,
+
+
+ /* Keep the "help" pseudo-flag last in the list */
+ { "help",
+ &clflag_help,
+ /* Two extra tabs if the name is shorter than 8 chars */
+ "\t\t\t",
+ "Print this \"Help\" message for the Special-Feature Flags" }
+
+};
+
+static const int number_of_cl_flags =
+ sizeof(cl_flags_list)/sizeof(cl_flag_t);
+
+
+/* **************************************************************************
+ *
+ * CL Flags whose settings are changed in the source file should
+ * not stay in effect for the duration of the entire batch of
+ * tokenizations (i.e., if multiple input files are named on
+ * the command line) the way command-line settings should.
+ * To accomplish this we will collect the state of the flags into
+ * a bit-mapped variable after the command line has been parsed
+ * and restore them to their collected saved state before an
+ * input file is processed.
+ *
+ **************************************************************************** */
+
+static long int cl_flags_bit_map;
+/* If the number of CL Flags ever exceeds the number of bits in a long
+ * (presently 32), we will need to change both this variable and
+ * the routines that use it. Of course, if the number of CL Flags
+ * ever gets that high, it will be *seriously* unwieldy... ;-}
+ */
+
+/* **************************************************************************
+ *
+ * Function name: adjust_case_flags
+ * Synopsis: If the last CL Flag Variable setting changed one of
+ * the "upper/lower-case-tokens" flags, make the
+ * appropriate adjustments.
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Local Static Variables:
+ * was_upper_case_tk State of "upper-case-tokens" flag before
+ * last CL Flag Variable was processed
+ * was_lower_case_tk State of "lower-case-tokens" flag, before
+ * upper_case_tokens State of "upper-case-tokens" flag after
+ * last CL Flag V'ble was processed
+ * lower_case_tokens State of "lower-case-tokens" flag, after
+ * Global Variables:
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global Variables:
+ * force_tokens_case TRUE if "upper/lower-case-tokens"
+ * flag is in effect
+ * force_lower_case_tokens If force_tokens_case is TRUE, then
+ * this switches between "upper"
+ * or "lower" case
+ *
+ * Process Explanation:
+ * We cannot come out of this with both upper_case_tokens and
+ * lower_case_tokens being TRUE, though they may both be FALSE.
+ * If neither has changed state, we need not do anything here.
+ * If one has gone to TRUE, we must force the other to FALSE and
+ * we will set force_tokens_case to TRUE.
+ * If one has gone to FALSE, turn force_tokens_case to FALSE.
+ * If force_tokens_case is TRUE after all this, we must adjust
+ * force_lower_case_tokens according to lower_case_tokens
+ *
+ **************************************************************************** */
+
+static void adjust_case_flags( void)
+{
+ static bool *case_tokens[2] = { &upper_case_tokens, &lower_case_tokens };
+ static bool *was_case_tk[2] = { &was_upper_case_tk, &was_lower_case_tk };
+ int the_one = 0;
+ int the_other = 1;
+
+ for ( ; the_one < 2 ; the_one++ , the_other-- )
+ {
+ /* If one has changed state */
+ if ( *(case_tokens[the_one]) != *(was_case_tk[the_one]) )
+ {
+ if ( *(case_tokens[the_one]) )
+ {
+ /* If it has gone to TRUE, force the other to FALSE. */
+ *(case_tokens[the_other]) = FALSE;
+ /* and set force_tokens_case to TRUE */
+ force_tokens_case = TRUE;
+ }else{
+ /* If it has gone to FALSE turn force_tokens_case FALSE */
+ force_tokens_case = FALSE;
+ }
+ if ( force_tokens_case )
+ {
+ force_lower_case_tokens = lower_case_tokens;
+ }
+ break; /* Only one can have changed state. */
+ }
+ }
+}
+
+
+
+
+/* **************************************************************************
+ *
+ * Function name: set_cl_flag
+ * Synopsis: Set (or clear) the named CL Flag Variable
+ *
+ * Inputs:
+ * Parameters:
+ * flag_name The name as supplied by the user
+ * from_src TRUE if called from source-input file
+ * Static Constants:
+ * cl_flags_list
+ * number_of_cl_flags
+ *
+ * Outputs:
+ * Returned Value: TRUE if supplied name is not valid
+ * Global Variables:
+ * The CL Flag Variable associated with the supplied name will
+ * be set or cleared according to the leading "no"
+ * Local Static Variables:
+ * cl_flag_change TRUE if associated variable has changed
+ * Printout:
+ * If from_src is TRUE, print "En" or "Dis" abling:
+ * followed by the explanation
+ *
+ * Error Detection:
+ * If the supplied name is not a valid CL Flag name, or if
+ * it's too short to be a valid CL Flag name, return TRUE.
+ * Print a message; either a simple print if this function was
+ * called from a command-line argument, or an ERROR if it
+ * was called from a line in the from source-input file.
+ *
+ * Process Explanation:
+ * Save the current state of the "upper/lower-case-tokens" flags
+ * If the given name has a leading "no", make note of that fact
+ * and remove the leading "no" from the comparison.
+ * Compare with the list of valid CL Flag names.
+ * If no match was found, Error. See under Error Detection.
+ * If a match:
+ * Change the associated variable according to the leading "no"
+ * Set cl_flag_change to TRUE unless the variable is the one
+ * associated with the "help" flag; this permits the
+ * "Default" vs "Setting" part of cl_flags_help() to
+ * work properly...
+ * Do the conditional Printout (see above)
+ * Adjust the "upper/lower-case-tokens" flags if one has changed.
+ *
+ **************************************************************************** */
+static bool first_err_msg = TRUE; /* Need extra carr-ret for first err msg */
+bool set_cl_flag(char *flag_name, bool from_src)
+{
+ bool retval = TRUE;
+
+ was_upper_case_tk = upper_case_tokens;
+ was_lower_case_tk = lower_case_tokens;
+
+ if ( strlen(flag_name) > 3 )
+ {
+ int indx;
+ bool flagval = TRUE;
+ char *compar = flag_name;
+
+ if ( strncasecmp( flag_name, "no", 2) == 0 )
+ {
+ flagval = FALSE;
+ compar += 2;
+ }
+ for ( indx = 0 ; indx < number_of_cl_flags ; indx++ )
+ {
+ if ( strcasecmp( compar, cl_flags_list[indx].clflag_name ) == 0 )
+ {
+ retval = FALSE;
+ *(cl_flags_list[indx].flag_var) = flagval;
+
+ /* The "help" flag is the last one in the list */
+ if ( indx != number_of_cl_flags - 1 )
+ {
+ cl_flag_change = TRUE;
+ }
+ if ( from_src )
+ {
+ tokenization_error(INFO,
+ "%sabling: %s\n",
+ flagval ? "En" : "Dis", cl_flags_list[indx].clflag_expln);
+ }
+ break;
+ }
+ }
+ }
+
+ if ( retval )
+ {
+ const char* msg_txt = "Unknown Special-Feature Flag: %s\n" ;
+ if ( from_src )
+ {
+ tokenization_error( TKERROR, (char *)msg_txt, flag_name);
+ }else{
+ if ( first_err_msg )
+ {
+ printf( "\n");
+ first_err_msg = FALSE;
+ }
+ printf( msg_txt, flag_name);
+ }
+ }
+
+ adjust_case_flags();
+
+ return ( retval );
+}
+
+/* **************************************************************************
+ *
+ * Function name: show_all_cl_flag_settings
+ * Synopsis: Display the settings of the CL Flags, (except "help")
+ * regardless of whether they have been changed.
+ *
+ * Associated Tokenizer directive(s): [FLAGS]
+ * #FLAGS
+ * [#FLAGS]
+ * SHOW-FLAGS
+ * This routine may also be invoked by a combination of
+ * options on the command-line.
+ *
+ * Inputs:
+ * Parameters:
+ * from_src TRUE if called from source-input file
+ * Macro:
+ * ERRMSG_DESTINATION Error message destination;
+ * (Development-time switch)
+ * Static Constants:
+ * cl_flags_list
+ * number_of_cl_flags
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Printout: Directed to stdout or to stderr
+ * (see definition of ERRMSG_DESTINATION)
+ * A header line, followed by the names of the CL Flags,
+ * with "No" preceding name if value is FALSE, one to a line.
+ *
+ * Process Explanation:
+ * If from_src is TRUE, print the header line as a Message, and
+ * then direct output to ERRMSG_DESTINATION .
+ * Don't print the "help" trigger (the last flag in the array).
+ *
+ **************************************************************************** */
+
+void show_all_cl_flag_settings(bool from_src)
+{
+ const char* hdr_txt = "Special-Feature Flag settings:" ;
+ int indx;
+
+ if ( from_src )
+ {
+ tokenization_error(MESSAGE, (char *)hdr_txt);
+ }else{
+ printf("\n%s\n", hdr_txt);
+ }
+
+ for ( indx = 0 ; indx < (number_of_cl_flags - 1) ; indx++ )
+ {
+ fprintf( from_src ? ERRMSG_DESTINATION : stdout ,
+ "\t%s%s\n",
+ *(cl_flags_list[indx].flag_var) ? " " : "No" ,
+ cl_flags_list[indx].clflag_name );
+ }
+ if ( from_src ) fprintf( ERRMSG_DESTINATION, "\n");
+}
+
+/* **************************************************************************
+ *
+ * Function name: list_cl_flag_settings
+ * Synopsis: Display the settings of the CL Flags, (except "help")
+ * if any of them have been changed
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Local Static Variables:
+ * cl_flag_change TRUE if a Flag setting has been changed.
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Printout:
+ * Settings of the CL Flags. See show_all_cl_flag_settings()
+ *
+ * Process Explanation:
+ * Don't print anything if cl_flag_change is not TRUE
+ *
+ **************************************************************************** */
+
+void list_cl_flag_settings(void)
+{
+
+ if ( cl_flag_change )
+ {
+ show_all_cl_flag_settings( FALSE);
+ }
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: list_cl_flag_names
+ * Synopsis: Display just the names of the CL Flags
+ * for the Usage message
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Static Constants:
+ * cl_flags_list
+ * number_of_cl_flags
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Printout:
+ * A header line, followed by the names of the CL Flags,
+ *
+ **************************************************************************** */
+
+void list_cl_flag_names(void)
+{
+ int indx;
+
+ printf("Valid Special-Feature Flags are:\n");
+ for ( indx = 0 ; indx < number_of_cl_flags ; indx++ )
+ {
+ printf("\t%s\n", cl_flags_list[indx].clflag_name );
+ }
+}
+
+/* **************************************************************************
+ *
+ * Function name: cl_flags_help
+ * Synopsis: Display Usage of the CL Flags and their defaults
+ *
+ *
+ * Inputs:
+ * Parameters:: NONE
+ * Static Constants:
+ * cl_flags_list
+ * number_of_cl_flags
+ * Local Static Variables:
+ * cl_flag_change TRUE if setting has been changed.
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Printout:
+ * A few lines of header, followed by the default, the name
+ * and the "explanation" of each of the CL Flags, one to a line.
+ *
+ * Extraneous Remarks:
+ * We take advantage of the facts that this routine is called
+ * (1) only from the command-line, before any settings
+ * have been changed, and (2) via changing the flag for
+ * "help" to TRUE. (Technically, I suppose, the default
+ * for the "help" feature is "no", but showing will, I
+ * think be more confusing than enlightening to the user.)
+ * Also, I suppose a perverse user could change setting(s) on
+ * the same command-line with a "-f help" request; we cannot
+ * stop users from aiming at their boot and pulling the
+ * trigger. As my buddies in Customer Support would say:
+ * "KMAC YOYO" (Approximately, "You're On Your Own, Clown")...
+ *
+ * Revision History:
+ * Oh, all right. If the user changed setting(s), we can do
+ * them the minor courtesy of printing "Setting" instead
+ * of "Default".
+ *
+ *
+ **************************************************************************** */
+
+void cl_flags_help(void )
+{
+ int indx;
+
+ printf("\n"
+ "Special-Feature Flags usage:\n"
+ " -f FlagName to enable the feature associated with FlagName,\n"
+ "or\n"
+ " -f noFlagName to disable the feature.\n\n"
+ "%s Flag-Name\t\t Feature:\n\n",
+ cl_flag_change ? "Setting" : "Default" );
+
+ for ( indx = 0 ; indx < number_of_cl_flags ; indx++ )
+ {
+ printf(" %s %s%s%s\n",
+ *(cl_flags_list[indx].flag_var) ? " " : "no" ,
+ cl_flags_list[indx].clflag_name,
+ cl_flags_list[indx].clflag_tabs,
+ cl_flags_list[indx].clflag_expln);
+ }
+
+}
+
+
+
+/* **************************************************************************
+ *
+ * Function name: save_cl_flags
+ * Synopsis: Collect the state of the CL Flags
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Local Static Variables:
+ * cl_flags_list
+ * Static Constants:
+ * number_of_cl_flags
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Local Static Variables:
+ * cl_flags_bit_map Will be set to reflect the state
+ * of the CL Flags in the list.
+ *
+ * Process Explanation:
+ * The correspondence of bits to the list is that the first item
+ * in the list corresponds to the low-order bit, and so on
+ * moving toward the high-order with each successive item.
+ * Do not save the "help" flag (last item on the list).
+ * This routine is called after the command line has been parsed.
+ *
+ **************************************************************************** */
+
+void save_cl_flags(void)
+{
+ int indx;
+ long int moving_bit = 1;
+
+ cl_flags_bit_map = 0;
+ for ( indx = 0 ; indx < (number_of_cl_flags - 1) ; indx++ )
+ {
+ if ( *(cl_flags_list[indx].flag_var) )
+ {
+ cl_flags_bit_map |= moving_bit; /* The moving finger writes, */
+ }
+ moving_bit <<= 1; /* and having writ, moves on. */
+ }
+}
+
+/* **************************************************************************
+ *
+ * Function name: reset_cl_flags
+ * Synopsis: Restore the CL Flags to the state that was saved.
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Local Static Variables:
+ * cl_flags_bit_map Reflects the state of the CL Flags
+ * Static Constants:
+ * number_of_cl_flags
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Local Static Variables:
+ * cl_flags_list
+ * Global Variables:
+ * The CL Flag Variables will be set or cleared
+ * to their saved state
+ *
+ * Process Explanation:
+ * This routine is called before starting a new input file.
+ * Any changes made in the source file will not stay
+ * in effect for the next tokenization.
+ *
+ **************************************************************************** */
+
+void reset_cl_flags(void)
+{
+ int indx;
+ long int moving_bit = 1;
+
+ for ( indx = 0 ; indx < (number_of_cl_flags - 1) ; indx++ )
+ {
+ *(cl_flags_list[indx].flag_var) =
+ BOOLVAL( cl_flags_bit_map & moving_bit) ;
+ moving_bit <<= 1;
+ }
+}
Added: fcode-utils/toke/clflags.h
===================================================================
--- fcode-utils/toke/clflags.h (rev 0)
+++ fcode-utils/toke/clflags.h 2006-08-18 12:47:12 UTC (rev 76)
@@ -0,0 +1,144 @@
+#ifndef _TOKE_CLFLAGS_H
+#define _TOKE_CLFLAGS_H
+
+/*
+ * OpenBIOS - free your system!
+ * ( FCode tokenizer )
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 2001-2005 Stefan Reinauer, <stepan(a)openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+/* **************************************************************************
+ *
+ * Function Prototypes and External declarations
+ * for Command-Line Flags Support
+ *
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Module Author: David L. Paktor dlpaktor(a)us.ibm.com
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Structure-Types:
+ * cl_flag_t Data for recognizing and setting Command-Line
+ * Flags, and for displaying the help message
+ *
+ * Function Prototypes / Functions Exported:
+ * set_cl_flag
+ * list_cl_flag_settings
+ * list_cl_flag_names Display just the names of the CL Flags
+ * cl_flags_help
+ *
+ * Global Variables Exported
+ * (These flags, which are set by the set_cl_flag() routine,
+ * are used throughout the Tokenizer to control certain
+ * non-Standard variant behaviors.)
+ * ibm_locals
+ * ibm_locals_legacy_separator
+ * ibm_legacy_separator_message
+ * enable_abort_quote
+ * sun_style_abort_quote
+ * string_remark_escape
+ * hex_remark_escape
+ * c_style_string_escape
+ * always_headers
+ * always_external
+ * verbose_dup_warning
+ * obso_fcode_warning
+ * trace_conditionals
+ * force_tokens_case
+ * force_lower_case_tokens
+ * big_end_pci_image_rev
+ * clflag_help
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ * Structure-Type Name: cl_flag_t
+ * Data for recognizing and setting Command-Line Flags,
+ * and for displaying the help message
+ *
+ * Fields:
+ * clflag_name *char CL Flag name, as entered by the user
+ * flag_var *bool Address of boolean ("flag") variable
+ * clflag_tabs *char Tabs to align the explanations, in
+ * the help message display
+ * clflag_expln *char Explanation, used in help message
+ *
+ * Since this structure will be initialized by the program, and will not
+ * be added-to, we can structure it as purely an array, and have no
+ * need to treat it as a linked list, hence no link-field.
+ *
+ **************************************************************************** */
+
+#include "types.h"
+
+typedef struct cl_flag
+ {
+ char *clflag_name;
+ bool *flag_var;
+ char *clflag_tabs;
+ char *clflag_expln;
+ } cl_flag_t ;
+
+
+/* **************************************************************************
+ *
+ * Exported Global Variables
+ *
+ **************************************************************************** */
+
+extern bool ibm_locals;
+extern bool ibm_locals_legacy_separator;
+extern bool ibm_legacy_separator_message;
+extern bool enable_abort_quote;
+extern bool sun_style_abort_quote;
+extern bool abort_quote_throw;
+extern bool string_remark_escape;
+extern bool hex_remark_escape;
+extern bool c_style_string_escape;
+extern bool always_headers;
+extern bool always_external;
+extern bool verbose_dup_warning;
+extern bool obso_fcode_warning;
+extern bool trace_conditionals;
+extern bool big_end_pci_image_rev;
+
+extern bool force_tokens_case;
+extern bool force_lower_case_tokens;
+
+extern bool clflag_help;
+
+/* **************************************************************************
+ *
+ * Exported Functions
+ *
+ **************************************************************************** */
+
+bool set_cl_flag(char *flag_name, bool print_message);
+void cl_flags_help(void);
+void list_cl_flag_names(void);
+void show_all_cl_flag_settings(bool from_src);
+void list_cl_flag_settings(void);
+void save_cl_flags(void);
+void reset_cl_flags(void);
+
+#endif /* _TOKE_CLFLAGS_H */
Added: fcode-utils/toke/conditl.c
===================================================================
--- fcode-utils/toke/conditl.c (rev 0)
+++ fcode-utils/toke/conditl.c 2006-08-18 12:47:12 UTC (rev 76)
@@ -0,0 +1,772 @@
+/*
+ * OpenBIOS - free your system!
+ * ( FCode tokenizer )
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 2001-2005 Stefan Reinauer, <stepan(a)openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+/* **************************************************************************
+ *
+ * Conditional-Compilation support for Tokenizer
+ *
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Module Author: David L. Paktor dlpaktor(a)us.ibm.com
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Functions Exported:
+ * init_conditionals_vocab Initialize the "Conditionals" Vocabulary.
+ * handle_conditional Confirm whether a given name is a valid
+ * Conditional, and, if so, perform its
+ * function and return an indication.
+ * create_conditional_alias Add an alias to "Conditionals" vocab
+ * reset_conditionals Reset the "Conditionals" Vocabulary
+ * to its "Built-In" position.
+ *
+ **************************************************************************** */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <errno.h>
+
+#include "scanner.h"
+#include "errhandler.h"
+#include "ticvocab.h"
+#include "conditl.h"
+#include "stack.h"
+#include "dictionary.h"
+#include "vocabfuncts.h"
+#include "usersymbols.h"
+#include "stream.h"
+#include "clflags.h"
+
+/* **************************************************************************
+ *
+ * Global Variables Imported
+ * statbuf Start of input-source buffer
+ * pc Input-source Scanning pointer
+ * iname Current Input File name
+ * lineno Current Line Number in Input File
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Local Static Variables
+ * already_ignoring Location from which to pass a parameter,
+ * called "alr_ign" to the main routine. Each
+ * "Conditional" will have an associated routine
+ * that takes the pointer to this as its argument.
+ * The pointer to this will satisfy the "param-field"
+ * requirement of a TIC_HDR-style "Vocabulary"-list.
+ * conditionals_tbl TIC_HDR-style "Vocabulary"-list table, initialized
+ * as an array.
+ * conditionals Pointer to "tail" of Conditionals Vocabulary-list
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * The lists of synonymous forms of the #ELSE and #THEN operators
+ * are incorporated into the "Shared Words" Vocabulary.
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Function name: is_a_then / is_an_else
+ * Synopsis: Indicate whether the given name is one of the
+ * [then] / [else] synonyms
+ *
+ * Inputs:
+ * Parameters:
+ * a_word Word to test
+ *
+ * Outputs:
+ * Returned Value: TRUE if the given name is one of the synonyms
+ *
+ * Process Explanation:
+ * The functions are twins, hence bundling them like this...
+ *
+ **************************************************************************** */
+
+
+/* **************************************************************************
+ *
+ * Support function: is_a_type
+ * Synopsis: Indicate whether the given name is a "shared word"
+ * whose FWord Token matches the one given
+ *
+ * Inputs:
+ * Parameters:
+ * tname Target name to look for
+ * fw_type The FWord Token type to match
+ *
+ * Outputs:
+ * Returned Value: TRUE if it matches
+ *
+ **************************************************************************** */
+
+
+static bool is_a_type( char *tname, fwtoken fw_type)
+{
+ bool retval = FALSE;
+ tic_fwt_hdr_t *found = (tic_fwt_hdr_t *)lookup_shared_f_exec_word( tname );
+ if ( found != NULL )
+ {
+ if ( found->pfield.fw_token == fw_type ) retval = TRUE;
+ }
+ return ( retval );
+}
+
+static bool is_a_then( char *a_word)
+{
+ bool retval = is_a_type( a_word, CONDL_ENDER);
+ return ( retval );
+}
+
+static bool is_an_else( char *a_word)
+{
+ bool retval = is_a_type( a_word, CONDL_ELSE);
+ return ( retval );
+}
+
+/* **************************************************************************
+ *
+ * This is a somewhat roundabout way of passing an "already ignoring"
+ * parameter to the various Conditional Operators. Each operator's
+ * Parameter-Field Pointer points to this. The calling routine
+ * must set it (or rely on the default); the routine that handles
+ * nesting of Conditionals must save and restore a local copy.
+ *
+ **************************************************************************** */
+
+static bool already_ignoring = FALSE;
+
+/* **************************************************************************
+ *
+ * Further down, will define and initialize a word-list table with
+ * all the functions that implement the Conditional Operators,
+ * and we'll link it in with the "Global Vocabulary" pointer.
+ *
+ * We'll call the word-list the "Conditionals Vocabulary Table",
+ * and refer to its entries as the "Conditionals Vocabulary",
+ * even though it isn't really a separate vocabulary...
+ *
+ **************************************************************************** */
+
+
+/* **************************************************************************
+ *
+ * We also need a few common routines to pass as "Ignoring" functions
+ * for a few occasional words that take another word or two from
+ * the input stream as their arguments. For example, if the user
+ * were to write: alias [otherwise] [else] and that were to
+ * occur within a segment already being ignored, we need to make
+ * sure that this doesn't get processed as an occurrence of [else]
+ * Similarly with macro-definitions.
+ *
+ * Since we are using the term "ignore a word" to mean "look it up and
+ * process it in Ignoring-state", we need a different term to name
+ * this class of routine; let's use the term "skip a word" where
+ * the "word" is strictly an input token, delimited by whitespace.
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Function name: skip_a_word
+ * Synopsis: Consume one input-token ("word") from the
+ * Input Stream, with no processing
+ *
+ * Inputs:
+ * Parameters:
+ * pfield "Parameter field" pointer, to satisfy
+ * the calling convention, but not used
+ *
+ * Outputs:
+ * Returned Value: NONE
+ *
+ **************************************************************************** */
+
+void skip_a_word( tic_bool_param_t pfield )
+{
+ /* signed long wlen = */ get_word();
+}
+
+/* **************************************************************************
+ *
+ * Function name: skip_a_word_in_line
+ * Synopsis: Consume one input-token ("word") on the same line
+ * as the current line of input, from the Input
+ * Stream, with no processing.
+ *
+ * Inputs:
+ * Parameters:
+ * pfield "Parameter field" pointer, to satisfy
+ * the calling convention, but not used
+ * Global Variables:
+ * statbuf The word being processed, which expects
+ * another word on the same line; used
+ * for the Error message.
+ *
+ * Outputs:
+ * Returned Value: NONE
+ *
+ * Error Detection:
+ * get_word_in_line() will check and report if no word on same line.
+ *
+ **************************************************************************** */
+void skip_a_word_in_line( tic_bool_param_t pfield )
+{
+ /* bool isokay = */ get_word_in_line( statbuf);
+}
+
+/* **************************************************************************
+ *
+ * Function name: skip_two_words_in_line
+ * Synopsis: Consume two input-tokens ("words") on the same line
+ * as the current line of input, from the Input
+ * Stream, with no processing.
+ *
+ * Inputs:
+ * Parameters:
+ * pfield "Parameter field" pointer, to satisfy
+ * the calling convention, but not used
+ * Global Variables:
+ * statbuf The word being processed, which expects
+ * two words on the same line; used for
+ * the Error message.
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Memory Allocated
+ * Copy of statbuf for Error message.
+ * When Freed?
+ * End of this routine
+ *
+ * Error Detection:
+ * get_word_in_line() will check and report
+ *
+ **************************************************************************** */
+
+void skip_two_words_in_line( tic_bool_param_t pfield )
+{
+ char *func_cpy = strupr( strdup( statbuf));
+ if ( get_word_in_line( func_cpy) )
+ {
+ /* bool isokay = */ get_word_in_line( func_cpy);
+ }
+ free( func_cpy);
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: ignore_one_word
+ * Synopsis: Handle a word that needs processing while "ignoring"
+ * Ignore the rest.
+ *
+ * Inputs:
+ * Parameters:
+ * tname Target name to test
+ * Local Static Variables:
+ * already_ignoring The "Already Ignoring" flag
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global Variables:
+ * tic_found Set to the TIC-entry that has just been
+ * found, in case it's a Macro.
+ * Local Static Variables:
+ * already_ignoring Intermediately set to TRUE, then
+ * returned to former state.
+ *
+ * Process Explanation:
+ * When we are ignoring source input, we still need to be
+ * sensitive to the nesting of Conditional Operators, to
+ * consume comments and user -message text-bodies, and to
+ * expand Macros, among other things.
+ * Rather than create special cases here for each one, we have
+ * added an "ign_funct" pointer to those words where this
+ * is relevant, including Conditional Operators.
+ * Save the state of already_ignoring and set it to TRUE
+ * Execute the "Ignoring" Function associated with the entry
+ * Restore already_ignoring to its previous state.
+ * This is necessary if the word is a Conditional Operator and
+ * is harmless otherwise.
+ *
+ **************************************************************************** */
+
+static void ignore_one_word( char *tname)
+{
+ tic_bool_hdr_t *found = (tic_bool_hdr_t *)lookup_word( tname, NULL, NULL);
+ if ( found != NULL )
+ {
+ if ( found->ign_func != NULL )
+ {
+ bool save_already_ignoring = already_ignoring;
+ already_ignoring = TRUE ;
+ tic_found = (tic_hdr_t *)found;
+
+ found->ign_func( found->pfield);
+
+ already_ignoring = save_already_ignoring;
+ }
+ }
+}
+
+/* **************************************************************************
+ *
+ * Function name: conditionally_tokenize
+ * Synopsis: Conduct tokenization while a Conditional-Tokenization
+ * operator is in effect. This is the core of the
+ * implementation of Conditional-Tokenization.
+ *
+ * Inputs:
+ * Parameters:
+ * cond The state of the Condition-Flag that the
+ * immediate Conditional Operator acquired.
+ * TRUE means "do not ignore". Its sense
+ * is reversed when [ELSE] is encountered.
+ * alr_ign TRUE means we are Already Ignoring source input,
+ * except for Conditional Operators...
+ * Global Variables:
+ * statbuf The symbol (word) just retrieved from input stream.
+ * iname Current Input File name (for Error Messages)
+ * lineno Current Line Number in Input File (ditto)
+ * trace_conditionals Whether to issue ADVISORY messages about
+ * the state of Conditional Tokenization.
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global Variables:
+ * statbuf Will be advanced to the balancing [THEN] op'r.
+ * already_ignoring Set to TRUE if nested Conditional encountered;
+ * restored to previous state when done.
+ * Memory Allocated
+ * Duplicate of Input File name, for Error Messages
+ * When Freed?
+ * Just prior to exit from routine.
+ * Printout:
+ * ADVISORY messages, if "Trace-Conditionals" flag was selected.
+ *
+ * Global Behavior:
+ * Tokenization happens, or inputs are ignored, as necessary.
+ *
+ * Error Detection:
+ * End-of-file encountered on reading a word
+ * ERROR. Conditional Operators must be balanced within a file
+ * More than one [ELSE] encountered: ERROR if processing segment;
+ * if ignoring, WARNING.
+ *
+ * Process Explanation:
+ * Read a word at a time. Allow Macros to "pop" transparently,
+ * but not source files.
+ * If the word is a [THEN], we are done.
+ * If the word is an [ELSE], then, if we are not Already Ignoring,
+ * invert the sense of whether we are ignoring source input.
+ * If this is not the only [ELSE] in the block, report an Error
+ * and disregard it.
+ * If we are ignoring source input, for whatever reason, we still
+ * need to be sensitive to the nesting of Conditional Operators:
+ * If the word is a Conditional Operator, activate it with the
+ * "Already Ignoring" parameter set to TRUE; doing so will
+ * result in a nested call to this routine.
+ * Otherwise, i.e., if the word is not a Conditional Operator,
+ * we may still need to process it in "ignoring" mode:
+ * we need, for instance, to consume strings, comments
+ * and the text-bodies of user-messages in their entirety,
+ * in case there is a reference to an [ELSE] or suchlike.
+ * The words that need processing while "ignoring" will
+ * have a valid function-pointer in their ign_func field.
+ * If we are not ignoring source input, pass the word along to the
+ * tokenize_one_word routine and process it. If the word is
+ * a Conditional Operator, it will be handled in the context
+ * of normal (i.e., non-ignored) tokenization, and, again, a
+ * nested call to this routine will result...
+ *
+ * Revision History:
+ * Updated Thu, 23 Feb 2006 by David L. Paktor
+ * Conditional Blocks may begin with a Conditional Operator in
+ * a Macro definition and do not need to be concluded in
+ * the body of the Macro.
+ * Updated Fri, 10 Mar 2006 by David L. Paktor
+ * Recognize aliased string, comment and user-message delimiters
+ * in a segment that is being ignored; Conditional Operators
+ * within the text body of any of these are always consumed
+ * and never unintentionally processed. Macros are always
+ * processed; Conditional Operators inside a Macro body are
+ * recognized, so the Macro continues to function as intended.
+ *
+ **************************************************************************** */
+
+static void conditionally_tokenize( bool cond, bool alr_ign )
+{
+
+ signed long wlen;
+
+ /* Note: The following variables *must* remain within
+ * the scope of this routine; a distinct instance
+ * is needed each time this routine is re-entered
+ * (aka "a nested call").
+ */
+ bool ignoring;
+ bool first_else = TRUE; /* The "else" we see is the first. */
+ bool not_done = TRUE;
+ unsigned int cond_strt_lineno = lineno;
+ char *cond_strt_ifile_nam = strdup( iname);
+
+ ignoring = BOOLVAL( ( cond == FALSE ) || ( alr_ign != FALSE ) );
+
+ if ( trace_conditionals )
+ {
+ char *cond_val = cond ? "True" : "False" ;
+ char *cond_junct = alr_ign ? ", but Already " : "; ";
+ char *processg = ignoring ? "Ignoring" : "Processing" ;
+ tokenization_error( INFO,
+ "Tokenization-Condition is %s%s%s.\n",
+ cond_val, cond_junct, processg);
+ }
+
+ while ( not_done )
+ {
+ wlen = get_word();
+ if ( wlen == 0 )
+ {
+ continue;
+ }
+
+ if ( wlen < 0 )
+ {
+ tokenization_error( TKERROR,
+ "Conditional without conclusion; started");
+ just_where_started( cond_strt_ifile_nam, cond_strt_lineno);
+ not_done = FALSE ;
+ continue;
+ }
+
+ if ( is_a_then ( statbuf ) )
+ {
+ if ( trace_conditionals )
+ {
+ tokenization_error( INFO,
+ "Concluding Conditional");
+ just_started_at( cond_strt_ifile_nam, cond_strt_lineno);
+ }
+ not_done = FALSE ;
+ continue;
+ }
+
+ if ( is_an_else( statbuf ) )
+ {
+ if ( ! alr_ign )
+ {
+ if ( first_else )
+ {
+ ignoring = INVERSE( ignoring);
+ }
+ }
+
+ if ( ! first_else )
+ {
+ int severity = ignoring ? WARNING : TKERROR ;
+ char *the_scop = ignoring ? "(ignored)" : "the" ;
+ tokenization_error( severity, "Multiple %s directives "
+ "within %s scope of the Conditional",
+ strupr(statbuf), the_scop);
+ just_started_at( cond_strt_ifile_nam, cond_strt_lineno);
+ }else{
+ first_else = FALSE;
+ if ( trace_conditionals )
+ {
+ char *when_enc = alr_ign ? "While already" : "Now" ;
+ char *processg = alr_ign ? "ignoring" :
+ ignoring ? "Ignoring" : "Processing" ;
+ char *enc = alr_ign ? ", e" : ". E" ;
+
+ tokenization_error( INFO,
+ "%s %s%sncountered %s belonging to Conditional",
+ when_enc, processg, enc, strupr(statbuf) );
+ just_started_at( cond_strt_ifile_nam, cond_strt_lineno);
+ }
+ }
+
+ continue;
+ }
+
+ /* If we are ignoring source input, for whatever reason, we still
+ * need to be sensitive to the nesting of Conditional Operators
+ * and some other commands and directives, as indicated...
+ */
+ if ( ignoring )
+ {
+ ignore_one_word( statbuf );
+ }else{
+ /* And if we're not ignoring source input, process it! */
+ tokenize_one_word ( wlen );
+ }
+ }
+}
+
+/* **************************************************************************
+ *
+ * We will now define a series of fairly simple functions that
+ * will be performed by the various Conditional Operators in
+ * the "Conditionals Vocabulary".
+ *
+ * Each one takes, as an argument, the "parameter field" pointer,
+ * which, in all cases, points to the local already_ignoring
+ * flag, passed as an int to satisfy C's strong-typing. The
+ * routine will internally recast it as a bool .
+ *
+ * If it is TRUE, the routine will bypass the test for its particular
+ * type of condition, and go directly to conditionally_tokenize
+ * In most cases, testing for the condition would be harmless,
+ * but in the case where the test is for an item on the stack,
+ * it would be harmful because the sequence that put the item
+ * on the stack was also being ignored...
+ *
+ * We'll give these functions short prologs. Synonyms will simply
+ * have separate entries in the Vocabulary Table, associated
+ * with the same function.
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * But first, a support routine...
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Function name: conditional_word_in_line
+ * Synopsis: Common code for the types of conditionals that
+ * require a word on the same line.
+ *
+ * Inputs:
+ * Parameters:
+ * alr_ign TRUE if we are already ignoring
+ * exist_test TRUE if the test is for "existence" of the word
+ * exist_funct Name of the function to call for the test
+ * Global Variables:
+ * stat_word Word for which to test
+ *
+ * Outputs:
+ * Returned Value: NONE
+ *
+ * Error Detection:
+ * The word in question must appear on the same line as the directive;
+ * the call to get_word_in_line() checks for that and reports.
+ * If the word did not appear on the same line, then the directive
+ * will be disregarded and processing will proceed as though it
+ * were absent. This may lead to a cascade of errors...
+ *
+ * Process Explanation:
+ * The supplied exist_funct() will test for the existence of
+ * the word, now read into statbuf , in the appropriate
+ * venue.
+ * We only call the exist_funct() if we are not already ignoring.
+ *
+ **************************************************************************** */
+
+static void conditional_word_in_line( bool alr_ign,
+ bool exist_test,
+ bool (*exist_funct)() )
+{
+ if ( get_word_in_line( statbuf) )
+ {
+ bool cond = FALSE;
+ if ( INVERSE( alr_ign) )
+ {
+ bool exists = exist_funct( statbuf);
+ cond = BOOLVAL( exists == exist_test);
+ }
+ conditionally_tokenize( cond, alr_ign );
+ }
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: if_exists
+ * Synopsis: Test for existence of a given word, in the dictionary.
+ *
+ * Associated Tokenizer directives: [ifexist]
+ * #ifexist
+ * [#ifexist]
+ * [ifexists]
+ * #ifexists
+ * [#ifexists]
+ * (Note variants with and without final 's'
+ *
+ **************************************************************************** */
+
+static void if_exists( tic_param_t pfield )
+{
+ bool alr_ign = *pfield.bool_ptr;
+ conditional_word_in_line( alr_ign, TRUE, exists_in_current );
+}
+
+/* **************************************************************************
+ *
+ * Function name: if_not_exist
+ * Synopsis: Test for Non-existence, in the appropriate dictionary,)
+ * of the given word.
+ *
+ * Associated Tokenizer directives: [ifnexist]
+ * #ifnexist
+ * [#ifnexist]
+ * (Note: Variants with final 's' didn't make sense here.)
+ *
+ * Explanatory Notes:
+ * This is the exact inverse of if_exists
+ *
+ **************************************************************************** */
+
+static void if_not_exist( tic_bool_param_t pfield )
+{
+ bool alr_ign = *pfield.bool_ptr;
+ conditional_word_in_line( alr_ign, FALSE, exists_in_current );
+}
+
+/* **************************************************************************
+ *
+ * Function name: if_defined
+ * Synopsis: Test for existence of a user-defined symbol
+ *
+ * Associated Tokenizer directives: [ifdef]
+ * #ifdef
+ * [#ifdef]
+ *
+ **************************************************************************** */
+
+static void if_defined( tic_bool_param_t pfield )
+{
+ bool alr_ign = *pfield.bool_ptr;
+ conditional_word_in_line( alr_ign, TRUE, exists_as_user_symbol );
+}
+
+/* **************************************************************************
+ *
+ * Function name: if_not_defined
+ * Synopsis: Test for NON-existence of a user-defined symbol
+ *
+ * Associated Tokenizer directives: [ifndef]
+ * #ifndef
+ * [#ifndef]
+ *
+ **************************************************************************** */
+
+static void if_not_defined( tic_bool_param_t pfield )
+{
+ bool alr_ign = *pfield.bool_ptr;
+ conditional_word_in_line( alr_ign, FALSE, exists_as_user_symbol );
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: if_from_stack
+ * Synopsis: Test the number on top of the run-time stack
+ *
+ * Associated Tokenizer directive: [if]
+ *
+ * Process Explanation:
+ * When we are ignoring source input, and we still need to be
+ * sensitive to the nesting of Conditional Operators, we
+ * will not consume the number on the stack; this function
+ * is after all, being ignored and should not perform any
+ * action other than making sure the [else]s and [then]s
+ * get properly counted.
+ *
+ **************************************************************************** */
+
+static void if_from_stack( tic_bool_param_t pfield )
+{
+ bool alr_ign = *pfield.bool_ptr;
+ bool cond = FALSE;
+
+ if ( ! alr_ign )
+ {
+ long num = dpop();
+ if (num != 0)
+ {
+ cond = TRUE;
+ }
+ }
+ conditionally_tokenize( cond, alr_ign );
+}
+
+/* For future functions, use conditl.BlankTemplate.c */
+
+/* **************************************************************************
+ *
+ * Here, at long last, we define and initialize the structure containing
+ * all the functions we support for Conditional Operators.
+ *
+ **************************************************************************** */
+
+#define ADD_CONDL(str, func ) BUILTIN_BOOL_TIC(str, func, already_ignoring )
+
+static tic_bool_hdr_t conditionals_vocab_tbl[] = {
+ ADD_CONDL ("[ifexist]" , if_exists ) ,
+ ADD_CONDL ("[ifexists]" , if_exists ) ,
+ ADD_CONDL ("#ifexist" , if_exists ) ,
+ ADD_CONDL ("#ifexists" , if_exists ) ,
+ ADD_CONDL ("[#ifexist]" , if_exists ) ,
+ ADD_CONDL ("[#ifexists]" , if_exists ) ,
+ ADD_CONDL ("[ifnexist]" , if_not_exist ) ,
+ ADD_CONDL ("#ifnexist" , if_not_exist ) ,
+ ADD_CONDL ("[#ifnexist]" , if_not_exist ) ,
+ ADD_CONDL ("[ifdef]" , if_defined ) ,
+ ADD_CONDL ("#ifdef" , if_defined ) ,
+ ADD_CONDL ("[#ifdef]" , if_defined ) ,
+ ADD_CONDL ("[ifndef]" , if_not_defined ) ,
+ ADD_CONDL ("#ifndef" , if_not_defined ) ,
+ ADD_CONDL ("[#ifndef]" , if_not_defined ) ,
+ ADD_CONDL ("[if]" , if_from_stack )
+};
+
+
+/* **************************************************************************
+ *
+ * Function name: init_conditionals_vocab
+ * Synopsis: Initialize the "Conditionals Vocabulary Table"
+ * link-pointers dynamically, and link it in
+ * with the given ("Global") Vocabulary pointer.
+ *
+ **************************************************************************** */
+
+void init_conditionals_vocab( tic_hdr_t **tic_vocab_ptr )
+{
+ static const int conditionals_vocab_max_indx =
+ sizeof(conditionals_vocab_tbl)/sizeof(tic_bool_hdr_t);
+
+ init_tic_vocab( (tic_hdr_t *)conditionals_vocab_tbl,
+ conditionals_vocab_max_indx,
+ tic_vocab_ptr );
+}
+
Added: fcode-utils/toke/conditl.h
===================================================================
--- fcode-utils/toke/conditl.h (rev 0)
+++ fcode-utils/toke/conditl.h 2006-08-18 12:47:12 UTC (rev 76)
@@ -0,0 +1,46 @@
+#ifndef _TOKE_CONDITL_H
+#define _TOKE_CONDITL_H
+
+/*
+ * OpenBIOS - free your system!
+ * ( FCode tokenizer )
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 2001-2005 Stefan Reinauer, <stepan(a)openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+/* **************************************************************************
+ *
+ * Function Prototypes for Conditional-Compilation support for Tokenizer
+ *
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Module Author: David L. Paktor dlpaktor(a)us.ibm.com
+ *
+ **************************************************************************** */
+
+#include "types.h"
+#include "ticvocab.h"
+
+void init_conditionals_vocab( tic_hdr_t **tic_vocab_ptr );
+
+void skip_a_word( tic_bool_param_t pfield );
+void skip_a_word_in_line( tic_bool_param_t pfield );
+void skip_two_words_in_line( tic_bool_param_t pfield );
+
+#endif /* _TOKE_CONDITL_H */
Added: fcode-utils/toke/devnode.c
===================================================================
--- fcode-utils/toke/devnode.c (rev 0)
+++ fcode-utils/toke/devnode.c 2006-08-18 12:47:12 UTC (rev 76)
@@ -0,0 +1,595 @@
+/*
+ * OpenBIOS - free your system!
+ * ( FCode tokenizer )
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 2001-2005 Stefan Reinauer, <stepan(a)openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+/* **************************************************************************
+ *
+ * Support routines for managing device-node vocabularies
+ *
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Module Author: David L. Paktor dlpaktor(a)us.ibm.com
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * The vocabulary that is created for a device-node must not remain
+ * available outside of that node. Also, nodes may be nested,
+ * child within parent.
+ * An attempt within a child-node to access directly a method defined
+ * in the parent must be flagged as an error. (Consider what would
+ * happen if the method in the parent-node used instance data, and
+ * the child-node has an instance of its own.)
+ * The correct way is to invoke the method via "$call-parent" or the like.
+ *
+ * We will, however, allow the user to specify a group of exceptions,
+ * words whose scope will be "global" within the tokenization.
+ * When "global" scope is initiated, definitions will be made to
+ * the "core" vocabulary until "device" scope is resumed.
+ * That will (mostly) all be handled in dictionary.c
+ *
+ **************************************************************************** */
+
+
+/* **************************************************************************
+ *
+ * Functions Exported:
+ * new_device_vocab Create the new device-node's data-structure
+ * delete_device_vocab Remove device-node's data-structure
+ * finish_device_vocab Remove struct and give messages when
+ * device is "finish"ed.
+ * exists_in_ancestor Issue a Message if the given word exists
+ * in an ancestor of the current dev-node.
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Still to be done:
+ * Add a pair of fields to the data-structure for the Input File and
+ * Line Number where "finish-device" occurred. When a device-node
+ * is "finish"ed, do not delete it, but instead fill in those
+ * fields and the move the node to a separate linked-list.
+ * When looking whether a word exists in an ancestor-node, also
+ * check whether it was in a device-node that was finished and
+ * print both where it was started and where it was finished.
+ *
+ **************************************************************************** */
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "devnode.h"
+#include "errhandler.h"
+#include "scanner.h"
+#include "vocabfuncts.h"
+#include "flowcontrol.h"
+#include "stream.h"
+#include "ticvocab.h"
+
+
+/* **************************************************************************
+ *
+ * Tokenization starts with an implicit "new-device" in effect.
+ * The top-level device-node is never removed.
+ *
+ * Initialize it here
+ *
+ **************************************************************************** */
+char default_top_dev_ifile_name[] = "Start of tokenization";
+
+static device_node_t top_level_dev_node = {
+ NULL , /* parent_node */
+ default_top_dev_ifile_name , /* ifile_name.
+ * Something to show, Just In Case
+ */
+ 0 , /* line_no */
+ NULL , /* tokens_vocab */
+};
+
+/* **************************************************************************
+ *
+ * Global Variables Exported.
+ * Pointers to:
+ * current_device_node data-structure of current device-node
+ * current_definitions vocab into which to add def'ns.
+ *
+ **************************************************************************** */
+
+device_node_t *current_device_node = &top_level_dev_node;
+tic_hdr_t **current_definitions = &(top_level_dev_node.tokens_vocab);
+
+
+/* **************************************************************************
+ *
+ * Internal Static Variables
+ * These are used to support the routines in_what_node()
+ * and show_node_start() , which are used to facilitate
+ * certain kinds of Messaging, as described later.
+ *
+ * in_what_buffr Buffer for the in_what_node() string
+ * show_where TRUE if the string needs to be followed-up
+ * show_which TRUE if follow-up should be just_where_started()
+ * rather than just_started_at()
+ * in_what_line Line Number to use in the follow-up
+ * in_what_file File Name to use in the follow-up
+ *
+ **************************************************************************** */
+
+static char in_what_buffr[50]; /* Ought to be more than enough. */
+static bool show_where = FALSE;
+static bool show_which;
+static int in_what_line;
+static char *in_what_file;
+
+
+/* **************************************************************************
+ *
+ * Function name: dev_vocab_control_struct_check
+ * Synopsis: Issue Warnings for unresolved flow-control constructs
+ * at start or end of a device-node.
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global Variables:
+ * statbuf The command being processed.
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Printout:
+ * Handled by announce_control_structs() routine
+ *
+ * Error Detection:
+ * Handled by announce_control_structs() routine
+ *
+ * Process Explanation:
+ * Set up a buffer with the error message, based on statbuf
+ * and pass it to announce_control_structs()
+ * Release it when done.
+ *
+ **************************************************************************** */
+
+static void dev_vocab_control_struct_check( void)
+{
+ char *ccs_messg;
+
+ ccs_messg = safe_malloc(strlen(statbuf) + 32,
+ "Device-Node control-structure check");
+
+ strcpy( ccs_messg, statbuf );
+ strupr( ccs_messg);
+ strcat( ccs_messg, " encountered");
+ announce_control_structs( WARNING, ccs_messg, 0 );
+ free( ccs_messg);
+}
+
+
+
+/* **************************************************************************
+ *
+ * Function name: new_device_vocab
+ * Synopsis: Create and initialize the data-structure for a
+ * new device-node when a "new-device" is created,
+ * with messages as appropriate.
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global Variables:
+ * statbuf The word that was just read.
+ * iname Current Input-File Name
+ * lineno Current line-number
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global Variables:
+ * current_device_node Will point to the new data-structure
+ * Memory Allocated
+ * Space for the new device_node_t data-structure
+ * Space for a copy of the current input file name
+ * When Freed?
+ * By delete_device_vocab(), when the device-node is "finish"ed.
+ * Printout:
+ * Advisory message.
+ *
+ * Error Detection:
+ * In immediate-execution mode, Control Structures that have not
+ * been completed are questionable; Issue WARNINGS via the
+ * dev_vocab_control_struct_check() routine.
+ *
+ * Process Explanation:
+ * This routine is called when "new-device" is invoked, but only
+ * if we are in immediate-execution mode.
+ * Later on, in ERROR- or INFOrmative messages, we will want to
+ * be able to refer to the file and line-number in which this
+ * was encountered, so we include them in the structure.
+ *
+ **************************************************************************** */
+
+void new_device_vocab( void )
+{
+ device_node_t *new_node_data;
+
+ dev_vocab_control_struct_check();
+
+ /* Advisory message will mention previous device-node
+ * if there was one. Either way starts out the same:
+ */
+#define NEW_DEV_MSG_START "Encountered %s. Starting new device-node."
+
+ if ( current_device_node == &top_level_dev_node )
+ {
+ tokenization_error(INFO, NEW_DEV_MSG_START "\n", statbuf );
+ }else{
+ tokenization_error(INFO, NEW_DEV_MSG_START
+ " Suspending definitions of parent-device node", statbuf );
+ started_at( current_device_node->ifile_name,
+ current_device_node->line_no );
+ }
+
+ /* Now to business... */
+ new_node_data = safe_malloc( sizeof(device_node_t),
+ "creating new-device vocab data" );
+ new_node_data->parent_node = current_device_node;
+ new_node_data->ifile_name = strdup(iname);
+ new_node_data->line_no = lineno;
+ new_node_data->tokens_vocab = NULL;
+
+ current_device_node = new_node_data;
+
+ current_definitions = &(current_device_node->tokens_vocab);
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: delete_device_vocab
+ * Synopsis: Remove the vocabularies of the current device-node,
+ * along with its data-structure, when the device
+ * is "finish"ed; do not print messages.
+ * Do not remove the top-level device-node data-struct.
+ *
+ * Associated FORTH words: FINISH_DEVICE (interpretive state)
+ * END0 END1
+ * Associated Tokenizer directives: RESET-SYMBOLS (in "Normal" mode)
+ * FCODE-END
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global Variables:
+ * current_device_node Points to current device's struct
+ * Leads to chain of dev-node structs
+ *
+ * Outputs:
+ * Returned Value:
+ * Global Variables:
+ * current_device_node Parent-device's struct becomes current
+ * Memory Freed
+ * All that was allocated for the tokens and the definers
+ * vocabs in the current device-node
+ * The copy of the input file name, except the top-level
+ * The current_device_node data-structure, except the top-level
+ *
+ **************************************************************************** */
+
+void delete_device_vocab( void )
+{
+ reset_tic_vocab( current_definitions, NULL );
+
+ if ( current_device_node != &top_level_dev_node )
+ {
+ device_node_t *temp_node = current_device_node;
+ current_device_node = current_device_node->parent_node;
+ free( temp_node->ifile_name );
+ free(temp_node);
+ }
+
+ current_definitions = &(current_device_node->tokens_vocab);
+}
+
+/* **************************************************************************
+ *
+ * Function name: finish_device_vocab
+ * Synopsis: Remove the device-node data-structure and all its
+ * vocabularies when the device is "finish"ed,
+ * with appropriate messages.
+ * Do not remove the top-level device node data-struct.
+ *
+ * Associated FORTH word: FINISH_DEVICE
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global Variables:
+ * current_device_node Current device's struct pointer
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global Variables:
+ * current_device_node Parent-device's struct becomes current
+ * Printout:
+ * Advisory message.
+ *
+ * Error Detection:
+ * If current_device_node is already pointing at the top-level
+ * device node, it means there was no corresponding NEW-DEVICE
+ * Issue an ERROR.
+ * In immediate-execution mode, Control Structures that have not
+ * been completed are questionable; Issue WARNINGS via the
+ * dev_vocab_control_struct_check() routine.
+ *
+ * Process Explanation:
+ * This routine is called when "finish-device" is invoked, but only
+ * if we are in immediate-execution mode.
+ *
+ **************************************************************************** */
+
+void finish_device_vocab( void )
+{
+ bool at_top_level;
+
+ dev_vocab_control_struct_check();
+
+ /* We never remove the top-level device-node vocabulary,
+ * so we need to test whether we're about to.
+ */
+
+ at_top_level = BOOLVAL( current_device_node == &top_level_dev_node );
+ if ( at_top_level )
+ {
+ tokenization_error( TKERROR,
+ "Encountered %s without corresponding NEW-DEVICE. "
+ "Resetting definitions since start of tokenization.\n",
+ statbuf );
+ }else{
+ tokenization_error(INFO,
+ "Encountered %s. Resetting definitions of device node",
+ statbuf );
+ started_at( current_device_node->ifile_name,
+ current_device_node->line_no );
+ }
+
+ /* Now to business... */
+ delete_device_vocab();
+
+ /* Did we just get to the top-level device-node vocabulary
+ * when we weren't before?
+ */
+ if ( INVERSE(at_top_level) )
+ {
+ if ( current_device_node == &top_level_dev_node )
+ {
+ tokenization_error(INFO,
+ "Resuming definitions since start of tokenization.\n" );
+ }else{
+ tokenization_error(INFO,
+ "Resuming definitions of parent device-node" );
+ started_at( current_device_node->ifile_name,
+ current_device_node->line_no );
+ }
+ }
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: in_what_node
+ * Synopsis: Format a string for use in a Message that might
+ * identify the start of the given device-node.
+ *
+ * Inputs:
+ * Parameters:
+ * the_node The device-node vocabulary about which
+ * to construct the identifying phrase.
+ * Local Static Variables:
+ * in_what_buffr Buffer in which to format the string.
+ * Global Variables:
+ * current_definitions Device-node vocabulary currently
+ * in effect.
+ *
+ * Outputs:
+ * Returned Value: Pointer to buffer w/ formatted string
+ * Local Static Variables:
+ * in_what_buffr Will contain the formatted string.
+ * show_where TRUE if the string needs to be followed-up
+ * (i.e., did not contain a terminating
+ * new-line) by just_where_started()
+ * or by just_started_at()
+ * show_which TRUE if the follow-up call should be
+ * to just_where_started() rather
+ * than to just_started_at()
+ * in_what_line Copy of line_no field from the_node
+ * in_what_file Copy of ifile_name field from the_node
+ *
+ * Process Explanation:
+ * Calling routine must ascertain that Global-scope is not in effect.
+ * The returned phrase can be used as a string argument in a Message.
+ * Set show_where TRUE if the_node->line_no is non-zero.
+ * Set show_which TRUE if the_node is either the Current or the
+ * Top-Level device-node
+ * If the originating line-number in the given Node structure is zero,
+ * the returned phrase will contain a terminating new-line.
+ * (This only happens if the given Node is the top-level Node,
+ * and it's the Current Node, and the "official" starting-point
+ * hasn't yet been established by an "FCode-Starter" such as
+ * FCODE-VERSION2 . Once that command has been given, even
+ * definitions that were made prior to it belong to the Node
+ * that started there.)
+ * Otherwise, show_where is returned TRUE, and show_which becomes
+ * relevant. If the given node is the Current or the Top-Level
+ * node, text about the originating file-name and line-number
+ * merely describes a node that is already uniquely identified,
+ * so the message appended to the buffer will have the phrase
+ * "which began" (which introduces what is known in grammar as
+ * an Appositive Subordinate Clause) and show_which will be
+ * returned TRUE. If the given node is not uniquely identifiable
+ * without the file- and line- phrase, then the Subordinate Clause
+ * is Indicative, and should be introduced with "that" (and no
+ * comma); in that case, we will return show_which as FALSE.
+ * After the calling routine displays the message in which the
+ * returned phrase is used, it must call show_node_start()
+ * to display the followe-up message, if any.
+ *
+ **************************************************************************** */
+
+char *in_what_node(device_node_t *the_node)
+{
+ bool top_node = BOOLVAL( the_node == &top_level_dev_node);
+ bool curr_node = BOOLVAL( the_node == current_device_node);
+ bool known_node = BOOLVAL( top_node || curr_node );
+ bool no_line = BOOLVAL( the_node->line_no == 0);
+
+ show_where = INVERSE( no_line );
+ show_which = known_node;
+ in_what_line = the_node->line_no;
+ in_what_file = the_node->ifile_name;
+
+ sprintf( in_what_buffr, "in the%s device-node%s",
+ INVERSE( known_node ) ? ""
+ : top_node ? " top-level" : " current" ,
+
+ no_line ? ".\n"
+ : known_node ? ", which began" : "" );
+
+
+ return( in_what_buffr);
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: show_node_start
+ * Synopsis: Follow-up to the in_what_node() call. Print out,
+ * if applicable, the text about the originating
+ * file-name and line-number
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Local Static Variables:
+ * show_where Nothing to do if not TRUE
+ * show_which TRUE if should call just_where_started()
+ * rather than just_started_at()
+ * in_what_line Line Number to use in the follow-up
+ * in_what_file File Name to use in the follow-up
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Local Static Variables:
+ * show_where Force to FALSE
+ * Printout:
+ * Follow-up to the in_what_node() call. Applicable text
+ * about the originating file-name and line-number.
+ *
+ * Process Explanation:
+ * By forcing show_where to FALSE after this is called, we
+ * can safely allow routines that might or might not have
+ * called in_what_node() to call this routine, without
+ * needing any additional "bookkeeping".
+ *
+ **************************************************************************** */
+
+void show_node_start( void)
+{
+ if ( show_where)
+ {
+ if ( show_which )
+ {
+ just_where_started( in_what_file, in_what_line);
+ }else{
+ just_started_at( in_what_file, in_what_line);
+ }
+ show_where = FALSE;
+ }
+}
+
+
+
+/* **************************************************************************
+ *
+ * Function name: exists_in_ancestor
+ * Synopsis: Issue a Message and return an indication if
+ * the given word exists in an ancestor of
+ * the current device-node.
+ * Used for additional error-message information.
+ *
+ *
+ * Inputs:
+ * Parameters:
+ * m_name "Method" name
+ * Global Variables:
+ * current_device_node Leads to chain of dev-node data-structs
+ * scope_is_global TRUE if "global" scope is in effect
+ *
+ * Outputs:
+ * Returned Value: TRUE if word found
+ * Printout:
+ * If m_name exists in an ancestor-node, print an ADVISORY
+ * giving the location where the ancestor originated.
+ *
+ * Error Detection:
+ * None here. Calling routine detected error; see below.
+ *
+ * Process Explanation:
+ * This routine was called as the result of detecting an error:
+ * viz., m_name was not found in either the current node
+ * or the base vocabulary. (Except: If "global" scope is
+ * in effect, we didn't search the current device-node).
+ *
+ **************************************************************************** */
+
+bool exists_in_ancestor( char *m_name)
+{
+ tic_hdr_t *found;
+ bool retval = FALSE;
+ if ( current_device_node != NULL )
+ {
+ device_node_t *grandpa = current_device_node->parent_node;
+
+ if ( scope_is_global ) grandpa = current_device_node;
+
+ for ( ; grandpa != NULL; grandpa = grandpa->parent_node )
+ {
+ found = lookup_tic_entry( m_name, grandpa->tokens_vocab);
+ if ( found != NULL )
+ {
+ retval = TRUE;
+ break;
+ }
+ }
+ if ( grandpa != NULL )
+ {
+ char as_what_buf[32] = "";
+ if ( as_a_what( found->fword_defr, as_what_buf) )
+ {
+ strcat( as_what_buf, " ");
+ }
+ tokenization_error(INFO, "%s is defined %s%s", m_name,
+ as_what_buf, in_what_node( grandpa) );
+ show_node_start();
+ }
+ }
+
+ return(retval );
+}
Added: fcode-utils/toke/devnode.h
===================================================================
--- fcode-utils/toke/devnode.h (rev 0)
+++ fcode-utils/toke/devnode.h 2006-08-18 12:47:12 UTC (rev 76)
@@ -0,0 +1,86 @@
+#ifndef _TOKE_DEVNODE_H
+#define _TOKE_DEVNODE_H
+
+/*
+ * OpenBIOS - free your system!
+ * ( FCode tokenizer )
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 2001-2005 Stefan Reinauer, <stepan(a)openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+/* **************************************************************************
+ *
+ * External/Prototype/Structure definitions for device-node management
+ *
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Module Author: David L. Paktor dlpaktor(a)us.ibm.com
+ *
+ **************************************************************************** */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "types.h"
+#include "ticvocab.h"
+
+/* **************************************************************************
+ * Structure Name: device_node_t
+ * Data for managing a device node; pointers
+ * to vocabs, data for messaging.
+ *
+ * Fields:
+ * parent_node Pointer to similar data for parent node
+ * line_no Copy of Line Number where "new-device" was invoked
+ * ifile_name Name of Input File where "new-device" was invoked
+ * tokens_vocab Pointer to vocab for this device's tokens
+ *
+ **************************************************************************** */
+
+typedef struct device_node {
+ struct device_node *parent_node ;
+ char *ifile_name ;
+ unsigned int line_no ;
+ tic_hdr_t *tokens_vocab ;
+} device_node_t;
+
+
+/* ************************************************************************** *
+ *
+ * Global Variables Exported
+ *
+ **************************************************************************** */
+
+extern char default_top_dev_ifile_name[];
+extern device_node_t *current_device_node;
+extern tic_hdr_t **current_definitions;
+
+/* ************************************************************************** *
+ *
+ * Function Prototypes / Functions Exported:
+ *
+ **************************************************************************** */
+void new_device_vocab( void );
+void delete_device_vocab( void );
+void finish_device_vocab( void );
+char *in_what_node(device_node_t *the_node);
+void show_node_start( void);
+bool exists_in_ancestor( char *m_name);
+
+#endif /* _TOKE_DEVNODE_H */
Modified: fcode-utils/toke/dictionary.c
===================================================================
--- fcode-utils/toke/dictionary.c 2006-08-18 09:45:11 UTC (rev 75)
+++ fcode-utils/toke/dictionary.c 2006-08-18 12:47:12 UTC (rev 76)
@@ -24,6 +24,12 @@
*
*/
+/* **************************************************************************
+ * Modifications made in 2005 by IBM Corporation
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Modifications Author: David L. Paktor dlpaktor(a)us.ibm.com
+ **************************************************************************** */
+
#include <stdio.h>
#include <stdlib.h>
#if defined(__linux__) && ! defined(__USE_BSD)
@@ -32,543 +38,2008 @@
#include <string.h>
#include <errno.h>
-#include "toke.h"
+#include "emit.h"
+#include "macros.h"
+#include "scanner.h"
+#include "ticvocab.h"
#include "dictionary.h"
+#include "vocabfuncts.h"
+#include "devnode.h"
+#include "clflags.h"
+#include "parselocals.h"
+#include "errhandler.h"
+#include "tokzesc.h"
+#include "conditl.h"
-typedef struct token {
- u8 *name;
- u16 fcode;
- struct token *next;
-} token_t;
+/* **************************************************************************
+ *
+ * Revision History:
+ * Updated Fri, 29 Jul 2005 by David L. Paktor
+ * Retrofit to handle "Current Device" as a separate vocabulary;
+ * if one is in effect, searches through it occur first, as
+ * do definitions to it, ahead of the general vocabulary. This
+ * is to support managing device-node vocabularies correctly.
+ * Updated Mon, 12 Dec 2005 by David L. Paktor
+ * Allow the user to specify a group of exceptions, words whose
+ * scope will be "global" within the tokenization. Under "global"
+ * scope, definitions will be made to the "core" vocabulary.
+ *
+ * Wed, 14 Dec 2005 by David L. Paktor
+ * Found a problem with the current approach. Need to be able to
+ * temporarily suspend meaning of "instance". Define: (1) an
+ * alias for INSTANCE called GENERIC_INSTANCE (2) a macro
+ * called INSTANCE that effectively no-ops it out; and, when
+ * it is time to restore "INSTANCE" to normal functionality,
+ * (3) an alias for GENERIC_INSTANCE called INSTANCE .
+ * Problem is that macros are treated as a separate vocabulary
+ * from FWords (and their aliases) and searching one before the
+ * other (either way) renders the second one searched unable to
+ * supercede the first one: If macros are searched first, (2)
+ * will be found ahead of the built-in FWord (which is what we
+ * want) but later, when we search for (3) among the FWords, it
+ * will not be found ahead of (2). If, on the other hand, we
+ * search FWords first, the macro defined in (2) will never be
+ * found.
+ * We need a way to define both (all?) types of definitions in a
+ * single vocabulary that will honor the LIFO order of def'ns.
+ *
+ * Mon, 19 Dec 2005 by David L. Paktor
+ * Begin development of implementation of a way to define both (all?)
+ * types of definitions in a single tic_hdr_t type vocabulary.
+ *
+ **************************************************************************** */
-static token_t *dictionary=NULL;
-static token_t *forthwords=NULL;
-static u16 lookup_token_dict(char *name, token_t *dict)
+
+/* **************************************************************************
+ *
+ * We will be creating several different lists of initial built-in
+ * definitions; together, they constitute the Global Vocabulary.
+ * (We will avoid the term "dictionary", since, in classical
+ * Forth terminology, it refers to the complete collection of
+ * vocabularies in an application.) The usage of the pointer
+ * to the Global Vocabulary is central to the operation of this
+ * program and the maintenance programmer needs to understand it.
+ * We may also refer to the Global Vocabulary as the "core" vocab.
+ *
+ * Each initial list will be created as an array of TIC-header entries.
+ * Because the global vocabulary is expandable by the user,
+ * we will not be searching the lists as arrays but rather as
+ * linked-lists; the run-time initialization routine will fill
+ * in their link-fields and also will link the various lists
+ * together, so we can group their initial declarations according
+ * to our convenience.
+ *
+ * A single pointer, called the "Global Vocabulary Dictionary Pointer"
+ * (okay, so classical Forth terminology isn't completely rigorous...)
+ * and abbreviated GV_DP, will point to the "tail" of the "thread".
+ * Similar vocabularies will be created for the device-nodes; look
+ * in the file devnode.fth for a more detailed discussion of those.
+ *
+ * The "FC-Tokens" list contains the names and FCode numeric tokens
+ * of the straightforward FORTH words that simply write a token
+ * directly to the tokenized output. We need to access these
+ * without being confused by aliases or other distractions, so
+ * we will keep a pointer to them especially for that purpose.
+ * Therefore it is IMPORTANT: that the "FC-Tokens" list MUST be the
+ * first table linked by the initialization routine, so that its
+ * last-searched entry's link-field is NULL.
+ *
+ * The "FWords" list contains FORTH words that require additional
+ * special action at tokenization-time. Their numeric values
+ * are derived from the fword_token enumeration declaration,
+ * and are used as the control-expression for a SWITCH statement
+ * with a large number of CASE labels in the handle_internal()
+ * function.
+ *
+ * The "Shared Words" list contains FORTH words that can be executed
+ * similarly both during "Tokenizer Escape" mode (i.e., the scope
+ * of the special brackets: tokenizer[ ... ]tokenizer ) and
+ * also within "Normal Tokenization" mode. Their numeric values
+ * are derived and used the same way as the "FWords". Since we
+ * will be needing to do a separate search through them at times,
+ * we will also need a lower-bracket pointer for them. (An upper
+ * bracket is irrelevant for these, because aliases can be added.
+ * This is not the case for the "FC-Tokens" list, because searches
+ * through those will be conducted from within this program.)
+ *
+ * The "definer" field in the TIC-header structure is primarily used to
+ * detect attempts to apply the TO directive to an inappropriate
+ * target. Its numeric values are a subset of the "FWord tokens".
+ * Certain "FC-Token" names are specified to be valid TO targets;
+ * their entries' "definer" fields will be initialized accordingly.
+ * Entries in FWord Token lists that are "shared" between "Normal
+ * Tokenization" and "Tokenizer Escape" modes will have their
+ * "definer" fields initialized to COMMON_FWORD . All other
+ * entries' "definer" fields will be initialized to UNSPECIFIED .
+ *
+ * Other files maintain and support additional lists with the same
+ * structure, which need to be linked together with the lists
+ * declared here. We prefer to keep the GV_DP private to this
+ * file, so it will be passed as a parameter where needed. (I'm
+ * not pleased to note, however, that it can't be kept completely
+ * private; it's needed for add_user_macro() and possibly other
+ * functions outside this file.)
+ *
+ * The words that can only be used during "Tokenizer Escape" mode and
+ * the IBM-style "Locals", as well as the device-node vocabularies,
+ * will need to be separate and will not be linked together with
+ * the Global Vocabulary.
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * We'll be initializing the lists later, but will be referencing
+ * the pointers sooner, so we need to declare the pointers here.
+ *
+ * We will keep all of these pointers private to this file.
+ *
+ **************************************************************************** */
+
+static tic_hdr_t *global_voc_dict_ptr = NULL; /* The Global Vocabulary */
+static tic_hdr_t *fc_tokens_list_ender = NULL; /* Tokens search ends here */
+static tic_hdr_t *fc_tokens_list_start = NULL; /* Start the search here */
+static tic_hdr_t *shared_fwords_ender = NULL; /* Shared FWords search end */
+static tic_hdr_t *global_voc_reset_ptr = NULL; /* Reset-point for G.V. */
+
+
+/* **************************************************************************
+ *
+ * Function name: lookup_core_word
+ * Synopsis: Return a pointer to the data-structure of the named
+ * word in the "Global" Vocabulary
+ *
+ * Inputs:
+ * Parameters:
+ * tname The name to look up
+ * Local Static Variables:
+ * global_voc_dict_ptr "Tail" of Global Vocabulary
+ *
+ * Outputs:
+ * Returned Value: Pointer to the data-structure, or
+ * NULL if not found.
+ *
+ **************************************************************************** */
+
+tic_hdr_t *lookup_core_word( char *tname)
{
- token_t *curr;
-
- for (curr=dict; curr!=NULL; curr=curr->next)
- if (!strcasecmp(name,(char *)curr->name))
- break;
+ tic_hdr_t *found ;
- if (curr)
- return curr->fcode;
-#ifdef DEBUG_TOKE
- printf("warning: token '%s' does not exist.\n", name);
-#endif
- return 0xffff;
+ found = lookup_tic_entry( tname, global_voc_dict_ptr);
+ return ( found ) ;
}
-u16 lookup_token(char *name)
+/* **************************************************************************
+ *
+ * Function name: exists_in_core
+ * Synopsis: Confirm whether the given name exists in the
+ * Global (aka "core") Vocabulary. Search the
+ * Global Vocabulary exclusively.
+ *
+ * Inputs:
+ * Parameters:
+ * name The name for which to look
+ * Local Static Variables:
+ * global_voc_dict_ptr "Tail" of Global Vocabulary
+ *
+ * Outputs:
+ * Returned Value: TRUE if name is found.
+ *
+ **************************************************************************** */
+
+bool exists_in_core( char *name)
{
- return lookup_token_dict(name, dictionary);
+ return exists_in_tic_vocab( name, global_voc_dict_ptr );
}
-u16 lookup_fword(char *name)
+/* **************************************************************************
+ *
+ * Function name: handle_core_word
+ * Synopsis: Perform a function in the "Global" Vocabulary and
+ * indicate whether the name is valid.
+ *
+ * Inputs:
+ * Parameters:
+ * tname The name to handle
+ * Local Static Variables:
+ * global_voc_dict_ptr "Tail" of Global Vocabulary
+ *
+ * Outputs:
+ * Returned Value: TRUE if the given name is valid in Global Vocab
+ *
+ * Error Detection:
+ * If the name is not in the "Global" Vocabulary, let the calling
+ * routine determine whether to print an error message or to
+ * try it out as a number.
+ *
+ **************************************************************************** */
+
+bool handle_core_word( char *tname )
{
- return lookup_token_dict(name, forthwords);
+ bool retval;
+
+ retval = handle_tic_vocab( tname, global_voc_dict_ptr );
+
+ return ( retval ) ;
}
-static int add_token_dict(u16 number, char *name, token_t **dict)
+
+/* **************************************************************************
+ *
+ * Function name: create_core_alias
+ * Synopsis: Create, in the "Global" ("core") Vocabulary, an entry
+ * for NEW_NAME that behaves the same as the latest
+ * definition of OLD_NAME, and whose behavior will
+ * not change even if a new definition of OLD_NAME
+ * is overlaid. Indicate if successful.
+ *
+ * Inputs:
+ * Parameters:
+ * new_name The name for the new alias to be created
+ * old_name The name of the old function to be duplicated
+ * Local Static Variables:
+ * global_voc_dict_ptr "Tail" of Global Vocabulary
+ *
+ * Outputs:
+ * Returned Value: TRUE if OLD_NAME was found.
+ * Local Static Variables:
+ * global_voc_dict_ptr Updated with the new entry
+ * Memory Allocated
+ * By support routine.
+ *
+ * Process Explanation:
+ * Both the "old" and "new" names are presumed to already point to
+ * stable, freshly allocated memory-spaces.
+ *
+ **************************************************************************** */
+
+bool create_core_alias( char *new_name, char *old_name)
{
- token_t *curr;
+ bool retval = create_tic_alias( new_name, old_name, &global_voc_dict_ptr);
+ return ( retval );
+}
- curr=malloc(sizeof(token_t));
- if(!curr) {
- printf("Out of memory while adding token.\n");
- exit(-ENOMEM);
+/* **************************************************************************
+ *
+ * The functions that go into the various lists' FUNCT field may be
+ * defined below, or might be defined externally.
+ *
+ * Often, we will need a function that merely recasts the type of the
+ * parameter field before passing it to the function that does
+ * the actual work.
+ *
+ * Prologs will be brief or even non-existent.
+ *
+ * Initialization macro definitions will accompany the functions.
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * For the "FCode-Tokens" list, simply generate the token directly.
+ * We need this layer for param type conversion.
+ * In case we're ever able to eliminate it, (or just on General
+ * Principles) we'll invoke it via a macro...
+ *
+ **************************************************************************** */
+
+static void emit_fc_token( tic_param_t pfield)
+{
+ u16 fc_tok = (u16)pfield.deflt_elem;
+ emit_fcode( fc_tok);
+}
+
+#define FC_TOKEN_FUNC emit_fc_token
+
+#define BUILTIN_FCODE( tok, nam) \
+ VALPARAM_TIC(nam, FC_TOKEN_FUNC, tok , UNSPECIFIED )
+
+/* Built-in FCodes with known definers: */
+#define BI_FCODE_VALUE( tok, nam) \
+ VALPARAM_TIC(nam, FC_TOKEN_FUNC, tok , VALUE )
+
+#define BI_FCODE_VRBLE( tok, nam) \
+ VALPARAM_TIC(nam, FC_TOKEN_FUNC, tok , VARIABLE )
+
+#define BI_FCODE_DEFER( tok, nam) \
+ VALPARAM_TIC(nam, FC_TOKEN_FUNC, tok , DEFER )
+
+#define BI_FCODE_CONST( tok, nam) \
+ VALPARAM_TIC(nam, FC_TOKEN_FUNC, tok , CONST )
+
+/* **************************************************************************
+ *
+ * The "FCode-Tokens" list includes tokens that are identified
+ * in the Standard as Obsolete. We will define a function
+ * that issues a WARNING before generating the token, and
+ * assign it to those elements of the list.
+ *
+ * Control the message via a command-line flag.
+ *
+ **************************************************************************** */
+
+static void obsolete_warning( void)
+{
+ if ( obso_fcode_warning )
+ {
+ tokenization_error( WARNING, "%s is an Obsolete FCode.\n",
+ strupr(statbuf) );
+ }
+}
+
+static void obsolete_fc_token( tic_param_t pfield)
+{
+ obsolete_warning();
+ emit_fc_token( pfield);
+}
+
+#define OBSO_FC_FUNC obsolete_fc_token
+
+#define OBSOLETE_FCODE( tok, nam) \
+ VALPARAM_TIC(nam, OBSO_FC_FUNC, tok , UNSPECIFIED )
+
+#define OBSOLETE_VALUE( tok, nam) \
+ VALPARAM_TIC(nam, OBSO_FC_FUNC, tok , VALUE )
+
+
+/* **************************************************************************
+ *
+ * The function for most of the "FWords" list, handle_internal() ,
+ * is defined externally, but not exported in a .h file,
+ * because we want to keep it as private as possible.
+ * We will declare its prototype here.
+ *
+ * Initialization macros for both "Normal Mode"-only and
+ * "Shared" entries are also defined here.
+ *
+ * Arguments:
+ * fwt (fword_token) Value of the FWord Token (from Enum list)
+ * nam (string) Name of the entry as seen in the source
+ *
+ **************************************************************************** */
+
+void handle_internal( tic_param_t pfield);
+/* "Skip-a-string when Ignoring" function. Same args and limited-proto ... */
+void skip_string( tic_param_t pfield);
+
+#define FWORD_EXEC_FUNC handle_internal
+
+#define BUILTIN_FWORD( fwt, nam) \
+ FWORD_TKN_TIC(nam, FWORD_EXEC_FUNC, fwt, BI_FWRD_DEFN )
+
+#define SHARED_FWORD( fwt, nam) \
+ FWORD_TKN_TIC(nam, FWORD_EXEC_FUNC, fwt, COMMON_FWORD )
+
+/* Variants: When Ignoring, SKip One Word */
+#define SHR_FWD_SKOW( fwt, nam) \
+ DUALFUNC_FWT_TIC(nam, FWORD_EXEC_FUNC, fwt, skip_a_word, COMMON_FWORD )
+
+/* Variants: When Ignoring, SKip one Word in line */
+#define SH_FW_SK_WIL( fwt, nam) \
+ DUALFUNC_FWT_TIC(nam, FWORD_EXEC_FUNC, fwt, \
+ skip_a_word_in_line, COMMON_FWORD )
+
+/* When Ignoring, SKip Two Words in line */
+#define SH_FW_SK2WIL( fwt, nam) \
+ DUALFUNC_FWT_TIC(nam, FWORD_EXEC_FUNC, fwt, \
+ skip_two_words_in_line, COMMON_FWORD )
+
+/* **************************************************************************
+ *
+ * Some of the entries in the "FWords" list -- both "Normal" (Built-in)
+ * and "Shared" also act as an "Ignore-handler".
+ *
+ * Arguments:
+ * nam (string) Name of the entry as seen in the source
+ * afunc (routine-name) Name of internal "active" function
+ * pval (integer) The "param field" item
+ * ifunc (routine-name) Name of "ignore-handling" function
+ *
+ **************************************************************************** */
+
+#define SHARED_IG_HDLR(nam, afunc, pval, ifunc) \
+ DUFNC_FWT_PARM(nam, afunc, pval, ifunc, COMMON_FWORD )
+
+/* A "Shared" entry that uses the same routine for both of its functions */
+#define SHR_SAMIG_FWRD( fwt, nam) \
+ DUFNC_FWT_PARM(nam, FWORD_EXEC_FUNC, fwt, FWORD_EXEC_FUNC, COMMON_FWORD )
+
+/* **************************************************************************
+ *
+ * But the "Normal" (Built-in) FWord Ignore-handler uses the same
+ * routine as the BUILTIN_FWORD for both of its functions.
+ *
+ * Arguments:
+ * fwt (fword_token) Value of the FWord Token (from Enum list)
+ * nam (string) Name of the entry as seen in the source
+ *
+ **************************************************************************** */
+#define BI_IG_FW_HDLR( fwt, nam) \
+ DUALFUNC_FWT_TIC(nam, FWORD_EXEC_FUNC, fwt, FWORD_EXEC_FUNC, BI_FWRD_DEFN )
+
+/* A variant: A "Built-In FWorD that SKiPs One Word", when Ignoring */
+#define BI_FWD_SKP_OW( fwt, nam) \
+ DUALFUNC_FWT_TIC(nam, FWORD_EXEC_FUNC, fwt, skip_a_word, BI_FWRD_DEFN )
+
+/* Another variant: A "Built-In FWorD String". skip_string when Ignoring */
+#define BI_FWD_STRING( fwt, nam) \
+ DUALFUNC_FWT_TIC(nam, FWORD_EXEC_FUNC, fwt, skip_string, BI_FWRD_DEFN )
+
+/* **************************************************************************
+ *
+ * In order to protect device-nodes' methods from being accessed
+ * by other device-nodes (with the attendant potential for
+ * disastrous consequences), we must establish a few rules:
+ *
+ * Each device-node has a separate vocabulary for its methods.
+ * New definitions are made to the "current" device's vocabulary.
+ * Searches for names go through the "current" device-node's
+ * vocabulary first, then through the core dictionary.
+ *
+ * A new-device (in interpretation-mode) creates a new device-node
+ * vocabulary. The node that had been current (presumably its
+ * parent) remains in memory but inactive.
+ *
+ * A finish-device (again, only in interpretation-mode) removes the
+ * current device-node's vocabulary from memory; its presumed
+ * parent once again becomes current.
+ *
+ * Tokenization starts with an implicit "new-device" in effect.
+ * The top-level device-node is never removed.
+ *
+ * The Global Variable current_definitions points to the vocabulary
+ * to which we will add and through which we will search first.
+ *
+ * If "global" scope is in effect, then current_definitions will
+ * point to the "Global" (also called "core") vocabulary.
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Support for operations in "current" -- i.e., "global" vis-a-vis
+ * "device" -- scope.
+ * "Global" scope will not recognize words defined in "device" scope,
+ * but "device" scope will recognize "global" words.
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Functions to enter "global" scope and resume "device" scope.
+ *
+ **************************************************************************** */
+
+static tic_hdr_t **save_device_definitions;
+/* Export the indication that "global" scope is in effect */
+bool scope_is_global = FALSE;
+
+
+void enter_global_scope( void )
+{
+ if ( scope_is_global )
+{
+ tokenization_error( WARNING,
+ "%s -- Global Scope already in effect; ignoring.\n",
+ strupr(statbuf) );
+ }else{
+ tokenization_error( INFO,
+ "Initiating Global Scope definitions.\n" );
+ scope_is_global = TRUE;
+ save_device_definitions = current_definitions;
+ current_definitions = &global_voc_dict_ptr;
+ }
+}
+
+void resume_device_scope( void )
+{
+ if ( scope_is_global )
+ {
+ tokenization_error( INFO,
+ "Terminating Global Scope definitions; "
+ "resuming Device-node definitions.\n" );
+ current_definitions = save_device_definitions;
+ scope_is_global = FALSE;
+ }else{
+ tokenization_error( WARNING,
+ "%s -- Device-node Scope already in effect; ignoring.\n",
+ strupr(statbuf) );
+ }
+
+}
+
+/* **************************************************************************
+ *
+ * Function name: lookup_current
+ * Synopsis: Return a pointer to the data-structure of the named
+ * word, either in the Current Device-Node vocab,
+ * or in the Global ("core") Vocabulary.
+ *
+ * Inputs:
+ * Parameters:
+ * tname The name to look for
+ * Global Variables:
+ * current_definitions Current vocabulary: Device-Node, or
+ * "core" if "global" scope in effect.
+ * scope_is_global TRUE if "global" scope is in effect
+ * Local Static Variables:
+ * global_voc_dict_ptr "Tail" of Global Vocabulary
+ *
+ * Outputs:
+ * Returned Value: Pointer to the data-structure, or
+ * NULL if not found.
+ *
+ * Process Explanation:
+ * If a current Device-Node Vocabulary in effect, search through it.
+ * If the given name was not found, and "global" scope is not in
+ * effect (i.e., "core" was not already searched), make a
+ * separate search through the Global ("core") Vocabulary
+ *
+ * Extraneous Remarks:
+ * This is the central routine for doing general word-searches that
+ * make use of the "normal"-mode search-list.
+ *
+ **************************************************************************** */
+
+tic_hdr_t *lookup_current( char *tname)
+{
+ /* Search Current Device Vocabulary ahead of global (core) vocabulary */
+ tic_hdr_t *retval;
+ retval = lookup_tic_entry( tname, *current_definitions);
+ if ( (retval == NULL) && INVERSE(scope_is_global) )
+{
+ retval = lookup_core_word( tname);
+ }
+ return ( retval );
+}
+
+/* **************************************************************************
+ *
+ * Function name: exists_in_current
+ * Synopsis: Confirm whether the given name exists either
+ * in the Current Device-Node vocab,
+ * or in the Global ("core") Vocabulary,
+ * or in Tokenizer Escape Mode, if that's current.
+ *
+ * Inputs:
+ * Parameters:
+ * tname The name to look for
+ *
+ * Outputs:
+ * Returned Value: TRUE if name is found
+ *
+ **************************************************************************** */
+
+bool exists_in_current( char *tname)
+{
+ tic_hdr_t *found = lookup_word( tname, NULL, NULL);
+ bool retval = BOOLVAL ( found != NULL);
+ return( retval);
}
- curr->next=*dict;
- curr->fcode=number;
- curr->name=(u8 *)name;
- *dict=curr;
- return 0;
+/* **************************************************************************
+ *
+ * Function name: handle_current
+ * Synopsis: Perform a function in the current device-node vocab,
+ * if one is in effect, or in the "Global" Vocabulary.
+ * Indicate whether the name is valid.
+ *
+ * Inputs:
+ * Parameters:
+ * tname The name to handle
+ * Global Variables:
+ * current_definitions Device-Node (or Global) Vocabulary
+ * currently in effect.
+ * scope_is_global TRUE if "global" scope is in effect
+ * Local Static Variables:
+ *
+ * Outputs:
+ * Returned Value: TRUE if the given name is valid
+ *
+ **************************************************************************** */
+
+bool handle_current( char *tname )
+{
+ bool retval = handle_tic_vocab( tname, *current_definitions );
+
+ if ( INVERSE(retval) && INVERSE(scope_is_global) )
+ {
+ retval = handle_core_word( tname );
+ }
+ return ( retval );
+
}
-int add_token(u16 number, char *name)
+
+/* **************************************************************************
+ *
+ * Function name: lookup_in_dev_node
+ * Synopsis: Return a pointer to the data-structure of the
+ * named word in the Current device node, if
+ * in "Device" scope. Used for error-reporting.
+ *
+ * Inputs:
+ * Parameters:
+ * tname The name to look for
+ * Global Variables:
+ * current_definitions Device-Node (or Global) Vocabulary
+ * currently in effect.
+ * scope_is_global FALSE if "Device" scope is in effect
+ *
+ * Outputs:
+ * Returned Value: Pointer to the data-structure, or
+ * NULL if not found.
+ *
+ **************************************************************************** */
+
+tic_hdr_t *lookup_in_dev_node( char *tname)
{
- return add_token_dict(number, name, &dictionary);
+ tic_hdr_t *retval = NULL;
+
+ if ( INVERSE(scope_is_global) )
+{
+ retval = lookup_tic_entry( tname, *current_definitions);
}
+ return ( retval );
+}
-static int add_special(u16 number, char *name)
+
+/* **************************************************************************
+ *
+ * In order to avoid unintentional "recursive"-ness, we need a way
+ * to render a newly created colon-definition non-findable
+ * until it's completed.
+ *
+ * We will accomplish this by saving and reverting the pointer to
+ * the newest entry, when we call the hide_last_colon() , and
+ * by restoring the pointer when we call reveal_last_colon()
+ *
+ * We need, therefore, to save the pointer to the last entry before
+ * we create the new entry.
+ *
+ **************************************************************************** */
+
+/* Update this each time a new definition is entered */
+static tic_hdr_t *save_current = NULL;
+
+/* **************************************************************************
+ *
+ * Function name: add_to_current
+ * Synopsis: Add a new entry to the "current" scope of definitions,
+ * which may be either the Global Vocabulary or the
+ * current Device-Node Vocabulary.
+ *
+ * Inputs:
+ * Parameters:
+ * name The name of the new entry
+ * fc_token The new entry's assigned FCode-number
+ * fw_definer The new entry's definer
+ * define_token If FALSE, suppress adding the entry,
+ * but preserve the side-effect of
+ * setting save_current
+ * Global Variables:
+ * current_definitions Pointer to pointer to "tail" of the
+ * Vocabulary currently in effect;
+ * either Device-node or Global.
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global Variables:
+ * *current_definitions Updated with the new entry
+ * Local Static Variables:
+ * save_current Pointer to previous entry
+ * Memory Allocated
+ * For the new entry's copy of the name.
+ * When Freed?
+ * When the Device-Node is "finish"ed or the Global Vocabulary
+ * is reset, or when the program exits.
+ *
+ * Process Explanation:
+ * Because current_definitions points to the Global Vocabulary
+ * pointer during "global" scope, this routine is extremely
+ * straightforward.
+ * All user-defined words have the same action, i.e., emitting
+ * the assigned FCode-number. The new entry's "parameter
+ * field" size is, of course, zero; the "ignore-function"
+ * is NULL.
+ *
+ * Extraneous Remarks:
+ * The define_token parameter is a late addition, necessitated
+ * by the decision to continue processing after an erroneous
+ * attempt to create a definition inside a control-structure,
+ * in order to catch other errors.
+ *
+ *
+ **************************************************************************** */
+
+void add_to_current( char *name,
+ TIC_P_DEFLT_TYPE fc_token,
+ fwtoken definer,
+ bool define_token)
{
- return add_token_dict(number, name, &forthwords);
+ save_current = *current_definitions;
+ if ( define_token )
+{
+ char *nu_name = strdup( name);
+ add_tic_entry( nu_name, FC_TOKEN_FUNC, fc_token,
+ definer, 0 , NULL, current_definitions );
+ }
}
-void init_dictionary(void)
+
+void hide_last_colon ( void )
{
- add_token( 0x000, "end0" );
- add_token( 0x010, "b(lit)" );
- add_token( 0x011, "b(')" );
- add_token( 0x012, "b(\")" );
- add_token( 0x013, "bbranch" );
- add_token( 0x014, "b?branch" );
- add_token( 0x015, "b(loop)" );
- add_token( 0x016, "b(+loop)" );
- add_token( 0x017, "b(do)" );
- add_token( 0x018, "b(?do)" );
- add_token( 0x019, "i" );
- add_token( 0x01a, "j" );
- add_token( 0x01b, "b(leave)" );
- add_token( 0x01c, "b(of)" );
- add_token( 0x01d, "execute" );
- add_token( 0x01e, "+" );
- add_token( 0x01f, "-" );
- add_token( 0x020, "*" );
- add_token( 0x021, "/" );
- add_token( 0x022, "mod" );
- add_token( 0x023, "and" );
- add_token( 0x024, "or" );
- add_token( 0x025, "xor" );
- add_token( 0x026, "invert" );
- add_token( 0x027, "lshift" );
- add_token( 0x028, "rshift" );
- add_token( 0x029, ">>a" );
- add_token( 0x02a, "/mod" );
- add_token( 0x02b, "u/mod" );
- add_token( 0x02c, "negate" );
- add_token( 0x02d, "abs" );
- add_token( 0x02e, "min" );
- add_token( 0x02f, "max" );
- add_token( 0x030, ">r" );
- add_token( 0x031, "r>" );
- add_token( 0x032, "r@" );
- add_token( 0x033, "exit" );
- add_token( 0x034, "0=" );
- add_token( 0x035, "0<>" );
- add_token( 0x036, "0<" );
- add_token( 0x037, "0<=" );
- add_token( 0x038, "0>" );
- add_token( 0x039, "0>=" );
- add_token( 0x03a, "<" );
- add_token( 0x03b, ">" );
- add_token( 0x03c, "=" );
- add_token( 0x03d, "<>" );
- add_token( 0x03e, "u>" );
- add_token( 0x03f, "u<=" );
- add_token( 0x040, "u<" );
- add_token( 0x041, "u>=" );
- add_token( 0x042, ">=" );
- add_token( 0x043, "<=" );
- add_token( 0x044, "between" );
- add_token( 0x045, "within" );
- add_token( 0x046, "drop" );
- add_token( 0x047, "dup" );
- add_token( 0x048, "over" );
- add_token( 0x049, "swap" );
- add_token( 0x04A, "rot" );
- add_token( 0x04b, "-rot" );
- add_token( 0x04c, "tuck" );
- add_token( 0x04d, "nip" );
- add_token( 0x04e, "pick" );
- add_token( 0x04f, "roll" );
- add_token( 0x050, "?dup" );
- add_token( 0x051, "depth" );
- add_token( 0x052, "2drop" );
- add_token( 0x053, "2dup" );
- add_token( 0x054, "2over" );
- add_token( 0x055, "2swap" );
- add_token( 0x056, "2rot" );
- add_token( 0x057, "2/" );
- add_token( 0x058, "u2/" );
- add_token( 0x059, "2*" );
- add_token( 0x05a, "/c" );
- add_token( 0x05b, "/w" );
- add_token( 0x05c, "/l" );
- add_token( 0x05d, "/n" );
- add_token( 0x05e, "ca+" );
- add_token( 0x05f, "wa+" );
- add_token( 0x060, "la+" );
- add_token( 0x061, "na+" );
- add_token( 0x062, "char+" );
- add_token( 0x063, "wa1+" );
- add_token( 0x064, "la1+" );
- add_token( 0x065, "cell+" );
- add_token( 0x066, "chars" );
- add_token( 0x067, "/w*" );
- add_token( 0x068, "/l*" );
- add_token( 0x069, "cells" );
- add_token( 0x06a, "on" );
- add_token( 0x06b, "off" );
- add_token( 0x06c, "+!" );
- add_token( 0x06d, "@" );
- add_token( 0x06e, "l@" );
- add_token( 0x06f, "w@" );
- add_token( 0x070, "<w@" );
- add_token( 0x071, "c@" );
- add_token( 0x072, "!" );
- add_token( 0x073, "l!" );
- add_token( 0x074, "w!" );
- add_token( 0x075, "c!" );
- add_token( 0x076, "2@" );
- add_token( 0x077, "2!" );
- add_token( 0x078, "move" );
- add_token( 0x079, "fill" );
- add_token( 0x07a, "comp" );
- add_token( 0x07b, "noop" );
- add_token( 0x07c, "lwsplit" );
- add_token( 0x07d, "wljoin" );
- add_token( 0x07e, "lbsplit" );
- add_token( 0x07f, "bljoin" );
- add_token( 0x080, "wbflip" );
- add_token( 0x081, "upc" );
- add_token( 0x082, "lcc" );
- add_token( 0x083, "pack" );
- add_token( 0x084, "count" );
- add_token( 0x085, "body>" );
- add_token( 0x086, ">body" );
- add_token( 0x087, "fcode-revision" );
- add_token( 0x088, "span" );
- add_token( 0x089, "unloop" );
- add_token( 0x08a, "expect" );
- add_token( 0x08b, "alloc-mem" );
- add_token( 0x08c, "free-mem" );
- add_token( 0x08d, "key?" );
- add_token( 0x08e, "key" );
- add_token( 0x08f, "emit" );
- add_token( 0x090, "type" );
- add_token( 0x091, "(cr" );
- add_token( 0x092, "cr" );
- add_token( 0x093, "#out" );
- add_token( 0x094, "#line" );
- add_token( 0x095, "hold" );
- add_token( 0x096, "<#" );
- add_token( 0x097, "u#>" );
- add_token( 0x098, "sign" );
- add_token( 0x099, "u#" );
- add_token( 0x09a, "u#s" );
- add_token( 0x09b, "u." );
- add_token( 0x09c, "u.r" );
- add_token( 0x09d, "." );
- add_token( 0x09e, ".r" );
- add_token( 0x09f, ".s" );
- add_token( 0x0a0, "base" );
- add_token( 0x0a1, "convert" );
- add_token( 0x0a2, "$number" );
- add_token( 0x0a3, "digit" );
- add_token( 0x0a4, "-1" );
- add_token( 0x0a5, "0" );
- add_token( 0x0a6, "1" );
- add_token( 0x0a7, "2" );
- add_token( 0x0a8, "3" );
- add_token( 0x0a9, "bl" );
- add_token( 0x0aa, "bs" );
- add_token( 0x0ab, "bell" );
- add_token( 0x0ac, "bounds" );
- add_token( 0x0ad, "here" );
- add_token( 0x0ae, "aligned" );
- add_token( 0x0af, "wbsplit" );
- add_token( 0x0b0, "bwjoin" );
- add_token( 0x0b1, "b(<mark)" );
- add_token( 0x0b2, "b(>resolve)" );
- add_token( 0x0b3, "set-token-table" );
- add_token( 0x0b4, "set-table" );
- add_token( 0x0b5, "new-token" );
- add_token( 0x0b6, "named-token" );
- add_token( 0x0b7, "b(:)" );
- add_token( 0x0b8, "b(value)" );
- add_token( 0x0b9, "b(variable)" );
- add_token( 0x0ba, "b(constant)" );
- add_token( 0x0bb, "b(create)" );
- add_token( 0x0bc, "b(defer)" );
- add_token( 0x0bd, "b(buffer:)" );
- add_token( 0x0be, "b(field)" );
- add_token( 0x0bf, "b(code)" );
- add_token( 0x0c0, "instance" );
- add_token( 0x0c2, "b(;)" );
- add_token( 0x0c3, "b(to)" );
- add_token( 0x0c4, "b(case)" );
- add_token( 0x0c5, "b(endcase)" );
- add_token( 0x0c6, "b(endof)" );
- add_token( 0x0c7, "#" );
- add_token( 0x0c8, "#s" );
- add_token( 0x0c9, "#>" );
- add_token( 0x0ca, "external-token" );
- add_token( 0x0cb, "$find" );
- add_token( 0x0cc, "offset16" );
- add_token( 0x0cd, "evaluate" );
- add_token( 0x0d0, "c," );
- add_token( 0x0d1, "w," );
- add_token( 0x0d2, "l," );
- add_token( 0x0d3, "," );
- add_token( 0x0d4, "um*" );
- add_token( 0x0d5, "um/mod" );
- add_token( 0x0d8, "d+" );
- add_token( 0x0d9, "d-" );
- add_token( 0x0da, "get-token" );
- add_token( 0x0db, "set-token" );
- add_token( 0x0dc, "state" );
- add_token( 0x0dd, "compile" );
- add_token( 0x0de, "behavior" );
- add_token( 0x0f0, "start0" );
- add_token( 0x0f1, "start1" );
- add_token( 0x0f2, "start2" );
- add_token( 0x0f3, "start4" );
- add_token( 0x0fc, "ferror" );
- add_token( 0x0fd, "version1" );
- add_token( 0x0fe, "4-byte-id" );
- add_token( 0x0ff, "end1" );
- add_token( 0x101, "dma-alloc" );
- add_token( 0x102, "my-address" );
- add_token( 0x103, "my-space" );
- add_token( 0x104, "memmap" );
- add_token( 0x105, "free-virtual" );
- add_token( 0x106, ">physical" );
- add_token( 0x10f, "my-params" );
- add_token( 0x110, "property" );
- add_token( 0x111, "encode-int" );
- add_token( 0x112, "encode+" );
- add_token( 0x113, "encode-phys" );
- add_token( 0x114, "encode-string" );
- add_token( 0x115, "encode-bytes" );
- add_token( 0x116, "reg" );
- add_token( 0x117, "intr" );
- add_token( 0x118, "driver" );
- add_token( 0x119, "model" );
- add_token( 0x11a, "device-type" );
- add_token( 0x11b, "parse-2int" );
- add_token( 0x11c, "is-install" );
- add_token( 0x11d, "is-remove" );
- add_token( 0x11e, "is-selftest" );
- add_token( 0x11f, "new-device" );
- add_token( 0x120, "diagnostic-mode?" );
- add_token( 0x121, "display-status" );
- add_token( 0x122, "memory-test-issue" );
- add_token( 0x123, "group-code" );
- add_token( 0x124, "mask" );
- add_token( 0x125, "get-msecs" );
- add_token( 0x126, "ms" );
- add_token( 0x127, "finish-device" );
- add_token( 0x128, "decode-phys" );
- add_token( 0x12b, "interpose" );
- add_token( 0x130, "map-low" );
- add_token( 0x131, "sbus-intr>cpu" );
- add_token( 0x150, "#lines" );
- add_token( 0x151, "#columns" );
- add_token( 0x152, "line#" );
- add_token( 0x153, "column#" );
- add_token( 0x154, "inverse?" );
- add_token( 0x155, "inverse-screen?" );
- add_token( 0x156, "frame-buffer-busy?" );
- add_token( 0x157, "draw-character" );
- add_token( 0x158, "reset-screen" );
- add_token( 0x159, "toggle-cursor" );
- add_token( 0x15a, "erase-screen" );
- add_token( 0x15b, "blink-screen" );
- add_token( 0x15c, "invert-screen" );
- add_token( 0x15d, "insert-characters" );
- add_token( 0x15e, "delete-characters" );
- add_token( 0x15f, "insert-lines" );
- add_token( 0x160, "delete-lines" );
- add_token( 0x161, "draw-logo" );
- add_token( 0x162, "frame-buffer-adr" );
- add_token( 0x163, "screen-height" );
- add_token( 0x164, "screen-width" );
- add_token( 0x165, "window-top" );
- add_token( 0x166, "window-left" );
- add_token( 0x16a, "default-font" );
- add_token( 0x16b, "set-font" );
- add_token( 0x16c, "char-height" );
- add_token( 0x16d, "char-width" );
- add_token( 0x16e, ">font" );
- add_token( 0x16f, "fontbytes" );
- add_token( 0x170, "fb1-draw-character" );
- add_token( 0x171, "fb1-reset-screen" );
- add_token( 0x172, "fb1-toggle-cursor" );
- add_token( 0x173, "fb1-erase-screen" );
- add_token( 0x174, "fb1-blink-screen" );
- add_token( 0x175, "fb1-invert-screen" );
- add_token( 0x176, "fb1-insert-characters" );
- add_token( 0x177, "fb1-delete-characters" );
- add_token( 0x178, "fb1-insert-lines" );
- add_token( 0x179, "fb1-delete-lines" );
- add_token( 0x17a, "fb1-draw-logo" );
- add_token( 0x17b, "fb1-install" );
- add_token( 0x17c, "fb1-slide-up" );
- add_token( 0x180, "fb8-draw-character" );
- add_token( 0x181, "fb8-reset-screen" );
- add_token( 0x182, "fb8-toggle-cursor" );
- add_token( 0x183, "fb8-erase-screen" );
- add_token( 0x184, "fb8-blink-screen" );
- add_token( 0x185, "fb8-invert-screen" );
- add_token( 0x186, "fb8-insert-characters" );
- add_token( 0x187, "fb8-delete-characters" );
- add_token( 0x188, "fb8-insert-lines" );
- add_token( 0x189, "fb8-delete-lines" );
- add_token( 0x18a, "fb8-draw-logo" );
- add_token( 0x18b, "fb8-install" );
- add_token( 0x1a0, "return-buffer" );
- add_token( 0x1a1, "xmit-packet" );
- add_token( 0x1a2, "poll-packet" );
- add_token( 0x1a4, "mac-address" );
- add_token( 0x201, "device-name" );
- add_token( 0x202, "my-args" );
- add_token( 0x203, "my-self" );
- add_token( 0x204, "find-package" );
- add_token( 0x205, "open-package" );
- add_token( 0x206, "close-package" );
- add_token( 0x207, "find-method" );
- add_token( 0x208, "call-package" );
- add_token( 0x209, "$call-parent" );
- add_token( 0x20a, "my-package" );
- add_token( 0x20b, "ihandle>phandle" );
- add_token( 0x20d, "my-unit" );
- add_token( 0x20e, "$call-method" );
- add_token( 0x20f, "$open-package" );
- add_token( 0x210, "processor-type" );
- add_token( 0x211, "firmware-version" );
- add_token( 0x212, "fcode-version" );
- add_token( 0x213, "alarm" );
- add_token( 0x214, "(is-user-word)" );
- add_token( 0x215, "suspend-fcode" );
- add_token( 0x216, "abort" );
- add_token( 0x217, "catch" );
- add_token( 0x218, "throw" );
- add_token( 0x219, "user-abort" );
- add_token( 0x21a, "get-my-property" );
- add_token( 0x21b, "decode-int" );
- add_token( 0x21c, "decode-string" );
- add_token( 0x21d, "get-inherited-property" );
- add_token( 0x21e, "delete-property" );
- add_token( 0x21f, "get-package-property" );
- add_token( 0x220, "cpeek" );
- add_token( 0x221, "wpeek" );
- add_token( 0x222, "lpeek" );
- add_token( 0x223, "cpoke" );
- add_token( 0x224, "wpoke" );
- add_token( 0x225, "lpoke" );
- add_token( 0x226, "lwflip" );
- add_token( 0x227, "lbflip" );
- add_token( 0x228, "lbflips" );
- add_token( 0x229, "adr-mask" );
- add_token( 0x230, "rb@" );
- add_token( 0x231, "rb!" );
- add_token( 0x232, "rw@" );
- add_token( 0x233, "rw!" );
- add_token( 0x234, "rl@" );
- add_token( 0x235, "rl!" );
- add_token( 0x236, "wbflips" );
- add_token( 0x237, "lwflips" );
- add_token( 0x238, "probe" );
- add_token( 0x239, "probe-virtual" );
- add_token( 0x23b, "child" );
- add_token( 0x23c, "peer" );
- add_token( 0x23d, "next-property" );
- add_token( 0x23e, "byte-load" );
- add_token( 0x23f, "set-args" );
- add_token( 0x240, "left-parse-string" );
+ tic_hdr_t *temp_vocab;
+ /* The add_to_current() function will have been called before this
+ * one when a new colon-definition is created, so save_current
+ * will have been set to point to the entry that had been made
+ * just before the newest one, which we are hiding here.
+ */
+
+ temp_vocab = save_current ;
+ save_current = *current_definitions;
+ *current_definitions = temp_vocab;
+
+}
+
+void reveal_last_colon ( void )
+{
+ /* We call this function either when the colon-definition is
+ * completed, or when "recursive"-ness is intentional.
+ */
+ *current_definitions = save_current ;
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: create_current_alias
+ * Synopsis: Create an alias for OLD_NAME, called NEW_NAME, in
+ * the "current" scope of definitions, which may
+ * be either the Global ("core") Vocabulary or the
+ * current Device-Node Vocabulary. Indicate if
+ * successful (i.e., OLD_NAME was valid).
+ * This is actually a little trickier than it may at
+ * first appear; read the Rules in the Process
+ * Explanation for full details...
+ *
+ * Inputs:
+ * Parameters:
+ * new_name The name for the new alias to be created
+ * old_name The name of the old function to be duplicated
+ * Global Variables:
+ * current_definitions Device-node vocabulary currently
+ * in effect.
+ * scope_is_global TRUE if "global" scope is in effect
+ * Local Static Variables:
+ * global_voc_dict_ptr "Tail" of Global Vocabulary
+ *
+ * Outputs:
+ * Returned Value: TRUE if OLD_NAME was found.
+ * Global Variables:
+ * *current_definitions Updated with the new entry
+ * Memory Allocated
+ * By support routine.
+ * When Freed?
+ * When RESET-SYMBOLS is issued (if "global" scope is in effect)
+ * or when the device-node is "finish"ed.
+ * Printout:
+ * Advisory message if Rule 3 (see below) is invoked.
+ *
+ * Process Explanation:
+ * Both the "old" and "new" names are presumed to already point to
+ * stable, freshly allocated memory-spaces.
+ * Rules:
+ * (1)
+ * If "global" scope is in effect, and the "old" name is found in
+ * the Global Vocabulary, then the "new" name will be created
+ * in the Global Vocabulary.
+ * (2)
+ * Similarly, if "device" scope is in effect, and the "old" name is
+ * found in the current device-node's vocabulary, the "new" name
+ * will be created in the current device-node's vocabulary.
+ * (3)
+ * BUT!: If "device" scope is in effect, and the "old" name is found
+ * in the Global Vocabulary, then the "new" name will be created
+ * in the current device-node's vocabulary. It will only be
+ * recognized in the scope of that device-node, and will be
+ * removed from memory when the device-node is "finish"ed.
+ * And, yes, it *is* supposed to work that way... ;-)
+ *
+ * Again, because current_definitions points to the Global Vocab
+ * pointer during "global" scope, the first two rules of this
+ * routine are extremely straightforward; it's Rule 3 that you
+ * have to watch out for... ;-)
+ *
+ * And one other thing:
+ * We will always make the alias's pfld_size zero. See the
+ * prolog for create_tic_alias() in ticvocab.c for details...
+ *
+ * Extraneous Remarks:
+ * I will stretch the rules of well-structured code here, too.
+ *
+ **************************************************************************** */
+
+bool create_current_alias( char *new_name, char *old_name )
+{
+ bool retval = FALSE;
+
+ if ( create_tic_alias( new_name, old_name, current_definitions) )
+ {
+ return ( TRUE );
+ }
+
+ if ( INVERSE(scope_is_global) )
+ {
+ tic_hdr_t *found = lookup_core_word( old_name );
+ if ( found != NULL )
+ {
+ add_tic_entry( new_name, found->funct,
+ found->pfield.deflt_elem,
+ found->fword_defr,
+ 0, found->ign_func,
+ current_definitions );
+ retval = TRUE;
+ {
+ tokenization_error( INFO,
+ "%s is a Global definition, but its alias, %s, "
+ "will only be defined %s",
+ strupr( old_name), new_name,
+ in_what_node( current_device_node) );
+ show_node_start();
+ }
+ }
+ }
+
+ return ( retval );
+}
+
+/* **************************************************************************
+ *
+ * Support functions specific to the lists will be defined
+ * after the lists are created.
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Create the initial list (or "Table") of FCode-Tokens.
+ *
+ * Most Standard FCode tokens are not specified as to their definition
+ * type, but a few have a definer specified as either a VALUE, a
+ * VARIABLE or a DEFER; we will enter them with the appropriate macro.
+ *
+ **************************************************************************** */
+
+static tic_hdr_t tokens_table[] =
+{
+ BUILTIN_FCODE( 0x000, "end0" ) ,
+ BUILTIN_FCODE( 0x010, "b(lit)" ) ,
+ BUILTIN_FCODE( 0x011, "b(')" ) ,
+ BUILTIN_FCODE( 0x012, "b(\")" ) ,
+ BUILTIN_FCODE( 0x013, "bbranch" ) ,
+ BUILTIN_FCODE( 0x014, "b?branch" ) ,
+ BUILTIN_FCODE( 0x015, "b(loop)" ) ,
+ BUILTIN_FCODE( 0x016, "b(+loop)" ) ,
+ BUILTIN_FCODE( 0x017, "b(do)" ) ,
+ BUILTIN_FCODE( 0x018, "b(?do)" ) ,
+ BUILTIN_FCODE( 0x019, "i" ) ,
+ BUILTIN_FCODE( 0x01a, "j" ) ,
+ BUILTIN_FCODE( 0x01b, "b(leave)" ) ,
+ BUILTIN_FCODE( 0x01c, "b(of)" ) ,
+ BUILTIN_FCODE( 0x01d, "execute" ) ,
+ BUILTIN_FCODE( 0x01e, "+" ) ,
+ BUILTIN_FCODE( 0x01f, "-" ) ,
+ BUILTIN_FCODE( 0x020, "*" ) ,
+ BUILTIN_FCODE( 0x021, "/" ) ,
+ BUILTIN_FCODE( 0x022, "mod" ) ,
+ BUILTIN_FCODE( 0x023, "and" ) ,
+ BUILTIN_FCODE( 0x024, "or" ) ,
+ BUILTIN_FCODE( 0x025, "xor" ) ,
+ BUILTIN_FCODE( 0x026, "invert" ) ,
+ BUILTIN_FCODE( 0x026, "not" ) , /* Synonym for "invert" */
+ BUILTIN_FCODE( 0x027, "lshift" ) ,
+ BUILTIN_FCODE( 0x027, "<<" ) , /* Synonym for "lshift" */
+ BUILTIN_FCODE( 0x028, "rshift" ) ,
+ BUILTIN_FCODE( 0x028, ">>" ) , /* Synonym for "rshift" */
+ BUILTIN_FCODE( 0x029, ">>a" ) ,
+ BUILTIN_FCODE( 0x02a, "/mod" ) ,
+ BUILTIN_FCODE( 0x02b, "u/mod" ) ,
+ BUILTIN_FCODE( 0x02c, "negate" ) ,
+ BUILTIN_FCODE( 0x02d, "abs" ) ,
+ BUILTIN_FCODE( 0x02e, "min" ) ,
+ BUILTIN_FCODE( 0x02f, "max" ) ,
+ BUILTIN_FCODE( 0x030, ">r" ) ,
+ BUILTIN_FCODE( 0x031, "r>" ) ,
+ BUILTIN_FCODE( 0x032, "r@" ) ,
+ BUILTIN_FCODE( 0x033, "exit" ) ,
+ BUILTIN_FCODE( 0x034, "0=" ) ,
+ BUILTIN_FCODE( 0x035, "0<>" ) ,
+ BUILTIN_FCODE( 0x036, "0<" ) ,
+ BUILTIN_FCODE( 0x037, "0<=" ) ,
+ BUILTIN_FCODE( 0x038, "0>" ) ,
+ BUILTIN_FCODE( 0x039, "0>=" ) ,
+ BUILTIN_FCODE( 0x03a, "<" ) ,
+ BUILTIN_FCODE( 0x03b, ">" ) ,
+ BUILTIN_FCODE( 0x03c, "=" ) ,
+ BUILTIN_FCODE( 0x03d, "<>" ) ,
+ BUILTIN_FCODE( 0x03e, "u>" ) ,
+ BUILTIN_FCODE( 0x03f, "u<=" ) ,
+ BUILTIN_FCODE( 0x040, "u<" ) ,
+ BUILTIN_FCODE( 0x041, "u>=" ) ,
+ BUILTIN_FCODE( 0x042, ">=" ) ,
+ BUILTIN_FCODE( 0x043, "<=" ) ,
+ BUILTIN_FCODE( 0x044, "between" ) ,
+ BUILTIN_FCODE( 0x045, "within" ) ,
+ BUILTIN_FCODE( 0x046, "drop" ) ,
+ BUILTIN_FCODE( 0x047, "dup" ) ,
+ BUILTIN_FCODE( 0x048, "over" ) ,
+ BUILTIN_FCODE( 0x049, "swap" ) ,
+ BUILTIN_FCODE( 0x04A, "rot" ) ,
+ BUILTIN_FCODE( 0x04b, "-rot" ) ,
+ BUILTIN_FCODE( 0x04c, "tuck" ) ,
+ BUILTIN_FCODE( 0x04d, "nip" ) ,
+ BUILTIN_FCODE( 0x04e, "pick" ) ,
+ BUILTIN_FCODE( 0x04f, "roll" ) ,
+ BUILTIN_FCODE( 0x050, "?dup" ) ,
+ BUILTIN_FCODE( 0x051, "depth" ) ,
+ BUILTIN_FCODE( 0x052, "2drop" ) ,
+ BUILTIN_FCODE( 0x053, "2dup" ) ,
+ BUILTIN_FCODE( 0x054, "2over" ) ,
+ BUILTIN_FCODE( 0x055, "2swap" ) ,
+ BUILTIN_FCODE( 0x056, "2rot" ) ,
+ BUILTIN_FCODE( 0x057, "2/" ) ,
+ BUILTIN_FCODE( 0x058, "u2/" ) ,
+ BUILTIN_FCODE( 0x059, "2*" ) ,
+ BUILTIN_FCODE( 0x05a, "/c" ) ,
+ BUILTIN_FCODE( 0x05b, "/w" ) ,
+ BUILTIN_FCODE( 0x05c, "/l" ) ,
+ BUILTIN_FCODE( 0x05d, "/n" ) ,
+ BUILTIN_FCODE( 0x05e, "ca+" ) ,
+ BUILTIN_FCODE( 0x05f, "wa+" ) ,
+ BUILTIN_FCODE( 0x060, "la+" ) ,
+ BUILTIN_FCODE( 0x061, "na+" ) ,
+ BUILTIN_FCODE( 0x062, "char+" ) ,
+ BUILTIN_FCODE( 0x062, "ca1+" ) , /* Synonym for char+" */
+ BUILTIN_FCODE( 0x063, "wa1+" ) ,
+ BUILTIN_FCODE( 0x064, "la1+" ) ,
+ BUILTIN_FCODE( 0x065, "cell+" ) ,
+ BUILTIN_FCODE( 0x065, "na1+" ) , /* Synonym for "cell+" */
+ BUILTIN_FCODE( 0x066, "chars" ) ,
+ BUILTIN_FCODE( 0x066, "/c*" ) , /* Synonym for "chars" */
+ BUILTIN_FCODE( 0x067, "/w*" ) ,
+ BUILTIN_FCODE( 0x068, "/l*" ) ,
+ BUILTIN_FCODE( 0x069, "cells" ) ,
+ BUILTIN_FCODE( 0x069, "/n*" ) , /* Synonym for "cells" */
+ BUILTIN_FCODE( 0x06a, "on" ) ,
+ BUILTIN_FCODE( 0x06b, "off" ) ,
+ BUILTIN_FCODE( 0x06c, "+!" ) ,
+ BUILTIN_FCODE( 0x06d, "@" ) ,
+ BUILTIN_FCODE( 0x06e, "l@" ) ,
+ BUILTIN_FCODE( 0x06f, "w@" ) ,
+ BUILTIN_FCODE( 0x070, "<w@" ) ,
+ BUILTIN_FCODE( 0x071, "c@" ) ,
+ BUILTIN_FCODE( 0x072, "!" ) ,
+ BUILTIN_FCODE( 0x073, "l!" ) ,
+ BUILTIN_FCODE( 0x074, "w!" ) ,
+ BUILTIN_FCODE( 0x075, "c!" ) ,
+ BUILTIN_FCODE( 0x076, "2@" ) ,
+ BUILTIN_FCODE( 0x077, "2!" ) ,
+ BUILTIN_FCODE( 0x078, "move" ) ,
+ BUILTIN_FCODE( 0x079, "fill" ) ,
+ BUILTIN_FCODE( 0x07a, "comp" ) ,
+ BUILTIN_FCODE( 0x07b, "noop" ) ,
+ BUILTIN_FCODE( 0x07c, "lwsplit" ) ,
+ BUILTIN_FCODE( 0x07d, "wljoin" ) ,
+ BUILTIN_FCODE( 0x07e, "lbsplit" ) ,
+ BUILTIN_FCODE( 0x07f, "bljoin" ) ,
+ BUILTIN_FCODE( 0x080, "wbflip" ) ,
+ BUILTIN_FCODE( 0x080, "flip" ) , /* Synonym for "wbflip" */
+ BUILTIN_FCODE( 0x081, "upc" ) ,
+ BUILTIN_FCODE( 0x082, "lcc" ) ,
+ BUILTIN_FCODE( 0x083, "pack" ) ,
+ BUILTIN_FCODE( 0x084, "count" ) ,
+ BUILTIN_FCODE( 0x085, "body>" ) ,
+ BUILTIN_FCODE( 0x086, ">body" ) ,
+ BUILTIN_FCODE( 0x087, "fcode-revision" ) ,
+ BUILTIN_FCODE( 0x087, "version" ) , /* Synonym for "fcode-revision" */
+ BI_FCODE_VRBLE( 0x088, "span" ) ,
+ BUILTIN_FCODE( 0x089, "unloop" ) ,
+ BUILTIN_FCODE( 0x08a, "expect" ) ,
+ BUILTIN_FCODE( 0x08b, "alloc-mem" ) ,
+ BUILTIN_FCODE( 0x08c, "free-mem" ) ,
+ BUILTIN_FCODE( 0x08d, "key?" ) ,
+ BUILTIN_FCODE( 0x08e, "key" ) ,
+ BUILTIN_FCODE( 0x08f, "emit" ) ,
+ BUILTIN_FCODE( 0x090, "type" ) ,
+ BUILTIN_FCODE( 0x091, "(cr" ) ,
+ BUILTIN_FCODE( 0x092, "cr" ) ,
+ BI_FCODE_VRBLE( 0x093, "#out" ) ,
+ BI_FCODE_VRBLE( 0x094, "#line" ) ,
+ BUILTIN_FCODE( 0x095, "hold" ) ,
+ BUILTIN_FCODE( 0x096, "<#" ) ,
+ BUILTIN_FCODE( 0x097, "u#>" ) ,
+ BUILTIN_FCODE( 0x098, "sign" ) ,
+ BUILTIN_FCODE( 0x099, "u#" ) ,
+ BUILTIN_FCODE( 0x09a, "u#s" ) ,
+ BUILTIN_FCODE( 0x09b, "u." ) ,
+ BUILTIN_FCODE( 0x09c, "u.r" ) ,
+ BUILTIN_FCODE( 0x09d, "." ) ,
+ BUILTIN_FCODE( 0x09e, ".r" ) ,
+ BUILTIN_FCODE( 0x09f, ".s" ) ,
+ BI_FCODE_VRBLE( 0x0a0, "base" ) ,
+ OBSOLETE_FCODE( 0x0a1, "convert" ) ,
+ BUILTIN_FCODE( 0x0a2, "$number" ) ,
+ BUILTIN_FCODE( 0x0a3, "digit" ) ,
+ BI_FCODE_CONST( 0x0a4, "-1" ) ,
+ BI_FCODE_CONST( 0x0a4, "true" ) , /* Synonym for "-1" */
+ BI_FCODE_CONST( 0x0a5, "0" ) ,
+ BI_FCODE_CONST( 0x0a5, "false" ) , /* Synonym for "0" */
+ BI_FCODE_CONST( 0x0a5, "struct" ) , /* Synonym for "0" */
+ BI_FCODE_CONST( 0x0a6, "1" ) ,
+ BI_FCODE_CONST( 0x0a7, "2" ) ,
+ BI_FCODE_CONST( 0x0a8, "3" ) ,
+ BI_FCODE_CONST( 0x0a9, "bl" ) ,
+ BI_FCODE_CONST( 0x0aa, "bs" ) ,
+ BI_FCODE_CONST( 0x0ab, "bell" ) ,
+ BUILTIN_FCODE( 0x0ac, "bounds" ) ,
+ BUILTIN_FCODE( 0x0ad, "here" ) ,
+ BUILTIN_FCODE( 0x0ae, "aligned" ) ,
+ BUILTIN_FCODE( 0x0af, "wbsplit" ) ,
+ BUILTIN_FCODE( 0x0b0, "bwjoin" ) ,
+ BUILTIN_FCODE( 0x0b1, "b(<mark)" ) ,
+ BUILTIN_FCODE( 0x0b2, "b(>resolve)" ) ,
+ OBSOLETE_FCODE( 0x0b3, "set-token-table" ) ,
+ OBSOLETE_FCODE( 0x0b4, "set-table" ) ,
+ BUILTIN_FCODE( 0x0b5, "new-token" ) ,
+ BUILTIN_FCODE( 0x0b6, "named-token" ) ,
+ BUILTIN_FCODE( 0x0b7, "b(:)" ) ,
+ BUILTIN_FCODE( 0x0b8, "b(value)" ) ,
+ BUILTIN_FCODE( 0x0b9, "b(variable)" ) ,
+ BUILTIN_FCODE( 0x0ba, "b(constant)" ) ,
+ BUILTIN_FCODE( 0x0bb, "b(create)" ) ,
+ BUILTIN_FCODE( 0x0bc, "b(defer)" ) ,
+ BUILTIN_FCODE( 0x0bd, "b(buffer:)" ) ,
+ BUILTIN_FCODE( 0x0be, "b(field)" ) ,
+ OBSOLETE_FCODE( 0x0bf, "b(code)" ) ,
+ BUILTIN_FCODE( 0x0c0, "instance" ) ,
+ BUILTIN_FCODE( 0x0c2, "b(;)" ) ,
+ BUILTIN_FCODE( 0x0c3, "b(to)" ) ,
+ BUILTIN_FCODE( 0x0c4, "b(case)" ) ,
+ BUILTIN_FCODE( 0x0c5, "b(endcase)" ) ,
+ BUILTIN_FCODE( 0x0c6, "b(endof)" ) ,
+ BUILTIN_FCODE( 0x0c7, "#" ) ,
+ BUILTIN_FCODE( 0x0c8, "#s" ) ,
+ BUILTIN_FCODE( 0x0c9, "#>" ) ,
+ BUILTIN_FCODE( 0x0ca, "external-token" ) ,
+ BUILTIN_FCODE( 0x0cb, "$find" ) ,
+ BUILTIN_FCODE( 0x0cc, "offset16" ) ,
+ BUILTIN_FCODE( 0x0cd, "evaluate" ) ,
+ BUILTIN_FCODE( 0x0cd, "eval" ) , /* Synonym for "evaluate" */
+ BUILTIN_FCODE( 0x0d0, "c," ) ,
+ BUILTIN_FCODE( 0x0d1, "w," ) ,
+ BUILTIN_FCODE( 0x0d2, "l," ) ,
+ BUILTIN_FCODE( 0x0d3, "," ) ,
+ BUILTIN_FCODE( 0x0d4, "um*" ) ,
+ BUILTIN_FCODE( 0x0d4, "u*x" ) , /* Synonym for "um*" */
+ BUILTIN_FCODE( 0x0d5, "um/mod" ) ,
+ BUILTIN_FCODE( 0x0d5, "xu/mod" ) , /* Synonym for "um/mod" */
+ BUILTIN_FCODE( 0x0d8, "d+" ) ,
+ BUILTIN_FCODE( 0x0d8, "x+" ) , /* Synonym for "d+" */
+ BUILTIN_FCODE( 0x0d9, "d-" ) ,
+ BUILTIN_FCODE( 0x0d9, "x-" ) , /* Synonym for "d-" */
+ BUILTIN_FCODE( 0x0da, "get-token" ) ,
+ BUILTIN_FCODE( 0x0db, "set-token" ) ,
+ BI_FCODE_VRBLE( 0x0dc, "state" ) ,
+ BUILTIN_FCODE( 0x0dd, "compile" ) ,
+ BUILTIN_FCODE( 0x0de, "behavior" ) ,
+ BUILTIN_FCODE( 0x0f0, "start0" ) ,
+ BUILTIN_FCODE( 0x0f1, "start1" ) ,
+ BUILTIN_FCODE( 0x0f2, "start2" ) ,
+ BUILTIN_FCODE( 0x0f3, "start4" ) ,
+ BUILTIN_FCODE( 0x0fc, "ferror" ) ,
+ BUILTIN_FCODE( 0x0fd, "version1" ) ,
+ OBSOLETE_FCODE( 0x0fe, "4-byte-id" ) ,
+ BUILTIN_FCODE( 0x0ff, "end1" ) ,
+ OBSOLETE_FCODE( 0x101, "dma-alloc" ) ,
+ BUILTIN_FCODE( 0x102, "my-address" ) ,
+ BUILTIN_FCODE( 0x103, "my-space" ) ,
+ OBSOLETE_FCODE( 0x104, "memmap" ) ,
+ BUILTIN_FCODE( 0x105, "free-virtual" ) ,
+ OBSOLETE_FCODE( 0x106, ">physical" ) ,
+ OBSOLETE_FCODE( 0x10f, "my-params" ) ,
+ BUILTIN_FCODE( 0x110, "property" ) ,
+ BUILTIN_FCODE( 0x110, "attribute" ) , /* Synonym for "property" */
+ BUILTIN_FCODE( 0x111, "encode-int" ) ,
+ BUILTIN_FCODE( 0x111, "xdrint" ) , /* Synonym for "encode-int" */
+ BUILTIN_FCODE( 0x112, "encode+" ) ,
+ BUILTIN_FCODE( 0x112, "xdr+" ) , /* Synonym for "encode+" */
+ BUILTIN_FCODE( 0x113, "encode-phys" ) ,
+ BUILTIN_FCODE( 0x113, "xdrphys" ) , /* Synonym for "encode-phys" */
+ BUILTIN_FCODE( 0x114, "encode-string" ) ,
+ BUILTIN_FCODE( 0x114, "xdrstring" ) , /* Synonym for "encode-string" */
+ BUILTIN_FCODE( 0x115, "encode-bytes" ) ,
+ BUILTIN_FCODE( 0x115, "xdrbytes" ) , /* Synonym for "encode-bytes" */
+ BUILTIN_FCODE( 0x116, "reg" ) ,
+ OBSOLETE_FCODE( 0x117, "intr" ) ,
+ OBSOLETE_FCODE( 0x118, "driver" ) ,
+ BUILTIN_FCODE( 0x119, "model" ) ,
+ BUILTIN_FCODE( 0x11a, "device-type" ) ,
+ BUILTIN_FCODE( 0x11b, "parse-2int" ) ,
+ BUILTIN_FCODE( 0x11b, "decode-2int" ) , /* Synonym for "parse-2int" */
+ BUILTIN_FCODE( 0x11c, "is-install" ) ,
+ BUILTIN_FCODE( 0x11d, "is-remove" ) ,
+ BUILTIN_FCODE( 0x11e, "is-selftest" ) ,
+ BUILTIN_FCODE( 0x11f, "new-device" ) ,
+ BUILTIN_FCODE( 0x120, "diagnostic-mode?" ) ,
+ BUILTIN_FCODE( 0x121, "display-status" ) ,
+ BUILTIN_FCODE( 0x122, "memory-test-issue" ) ,
+ OBSOLETE_FCODE( 0x123, "group-code" ) ,
+ BI_FCODE_VRBLE( 0x124, "mask" ) ,
+ BUILTIN_FCODE( 0x125, "get-msecs" ) ,
+ BUILTIN_FCODE( 0x126, "ms" ) ,
+ BUILTIN_FCODE( 0x127, "finish-device" ) ,
+ BUILTIN_FCODE( 0x128, "decode-phys" ) ,
+ BUILTIN_FCODE( 0x12b, "interpose" ) ,
+ BUILTIN_FCODE( 0x130, "map-low" ) ,
+ BUILTIN_FCODE( 0x130, "map-sbus" ) , /* Synonym for "map-low" */
+ BUILTIN_FCODE( 0x131, "sbus-intr>cpu" ) ,
+ BI_FCODE_VALUE( 0x150, "#lines" ) ,
+ BI_FCODE_VALUE( 0x151, "#columns" ) ,
+ BI_FCODE_VALUE( 0x152, "line#" ) ,
+ BI_FCODE_VALUE( 0x153, "column#" ) ,
+ BI_FCODE_VALUE( 0x154, "inverse?" ) ,
+ BI_FCODE_VALUE( 0x155, "inverse-screen?" ) ,
+ OBSOLETE_VALUE( 0x156, "frame-buffer-busy?" ) ,
+ BI_FCODE_DEFER( 0x157, "draw-character" ) ,
+ BI_FCODE_DEFER( 0x158, "reset-screen" ) ,
+ BI_FCODE_DEFER( 0x159, "toggle-cursor" ) ,
+ BI_FCODE_DEFER( 0x15a, "erase-screen" ) ,
+ BI_FCODE_DEFER( 0x15b, "blink-screen" ) ,
+ BI_FCODE_DEFER( 0x15c, "invert-screen" ) ,
+ BI_FCODE_DEFER( 0x15d, "insert-characters" ) ,
+ BI_FCODE_DEFER( 0x15e, "delete-characters" ) ,
+ BI_FCODE_DEFER( 0x15f, "insert-lines" ) ,
+ BI_FCODE_DEFER( 0x160, "delete-lines" ) ,
+ BI_FCODE_DEFER( 0x161, "draw-logo" ) ,
+ BI_FCODE_VALUE( 0x162, "frame-buffer-adr" ) ,
+ BI_FCODE_VALUE( 0x163, "screen-height" ) ,
+ BI_FCODE_VALUE( 0x164, "screen-width" ) ,
+ BI_FCODE_VALUE( 0x165, "window-top" ) ,
+ BI_FCODE_VALUE( 0x166, "window-left" ) ,
+ BUILTIN_FCODE( 0x16a, "default-font" ) ,
+ BUILTIN_FCODE( 0x16b, "set-font" ) ,
+ BI_FCODE_VALUE( 0x16c, "char-height" ) ,
+ BI_FCODE_VALUE( 0x16d, "char-width" ) ,
+ BUILTIN_FCODE( 0x16e, ">font" ) ,
+ BI_FCODE_VALUE( 0x16f, "fontbytes" ) ,
+ OBSOLETE_FCODE( 0x170, "fb1-draw-character" ) ,
+ OBSOLETE_FCODE( 0x171, "fb1-reset-screen" ) ,
+ OBSOLETE_FCODE( 0x172, "fb1-toggle-cursor" ) ,
+ OBSOLETE_FCODE( 0x173, "fb1-erase-screen" ) ,
+ OBSOLETE_FCODE( 0x174, "fb1-blink-screen" ) ,
+ OBSOLETE_FCODE( 0x175, "fb1-invert-screen" ) ,
+ OBSOLETE_FCODE( 0x176, "fb1-insert-characters" ) ,
+ OBSOLETE_FCODE( 0x177, "fb1-delete-characters" ) ,
+ OBSOLETE_FCODE( 0x178, "fb1-insert-lines" ) ,
+ OBSOLETE_FCODE( 0x179, "fb1-delete-lines" ) ,
+ OBSOLETE_FCODE( 0x17a, "fb1-draw-logo" ) ,
+ OBSOLETE_FCODE( 0x17b, "fb1-install" ) ,
+ OBSOLETE_FCODE( 0x17c, "fb1-slide-up" ) ,
+ BUILTIN_FCODE( 0x180, "fb8-draw-character" ) ,
+ BUILTIN_FCODE( 0x181, "fb8-reset-screen" ) ,
+ BUILTIN_FCODE( 0x182, "fb8-toggle-cursor" ) ,
+ BUILTIN_FCODE( 0x183, "fb8-erase-screen" ) ,
+ BUILTIN_FCODE( 0x184, "fb8-blink-screen" ) ,
+ BUILTIN_FCODE( 0x185, "fb8-invert-screen" ) ,
+ BUILTIN_FCODE( 0x186, "fb8-insert-characters" ) ,
+ BUILTIN_FCODE( 0x187, "fb8-delete-characters" ) ,
+ BUILTIN_FCODE( 0x188, "fb8-insert-lines" ) ,
+ BUILTIN_FCODE( 0x189, "fb8-delete-lines" ) ,
+ BUILTIN_FCODE( 0x18a, "fb8-draw-logo" ) ,
+ BUILTIN_FCODE( 0x18b, "fb8-install" ) ,
+ OBSOLETE_FCODE( 0x1a0, "return-buffer" ) ,
+ OBSOLETE_FCODE( 0x1a1, "xmit-packet" ) ,
+ OBSOLETE_FCODE( 0x1a2, "poll-packet" ) ,
+ BUILTIN_FCODE( 0x1a4, "mac-address" ) ,
+ BUILTIN_FCODE( 0x201, "device-name" ) ,
+ BUILTIN_FCODE( 0x201, "name" ) , /* Synonym for "device-name" */
+ BUILTIN_FCODE( 0x202, "my-args" ) ,
+ BI_FCODE_VALUE( 0x203, "my-self" ) ,
+ BUILTIN_FCODE( 0x204, "find-package" ) ,
+ BUILTIN_FCODE( 0x205, "open-package" ) ,
+ BUILTIN_FCODE( 0x206, "close-package" ) ,
+ BUILTIN_FCODE( 0x207, "find-method" ) ,
+ BUILTIN_FCODE( 0x208, "call-package" ) ,
+ BUILTIN_FCODE( 0x209, "$call-parent" ) ,
+ BUILTIN_FCODE( 0x20a, "my-parent" ) ,
+ BUILTIN_FCODE( 0x20b, "ihandle>phandle" ) ,
+ BUILTIN_FCODE( 0x20d, "my-unit" ) ,
+ BUILTIN_FCODE( 0x20e, "$call-method" ) ,
+ BUILTIN_FCODE( 0x20f, "$open-package" ) ,
+ OBSOLETE_FCODE( 0x210, "processor-type" ) ,
+ OBSOLETE_FCODE( 0x211, "firmware-version" ) ,
+ OBSOLETE_FCODE( 0x212, "fcode-version" ) ,
+ BUILTIN_FCODE( 0x213, "alarm" ) ,
+ BUILTIN_FCODE( 0x214, "(is-user-word)" ) ,
+ BUILTIN_FCODE( 0x215, "suspend-fcode" ) ,
+ BUILTIN_FCODE( 0x216, "abort" ) ,
+ BUILTIN_FCODE( 0x217, "catch" ) ,
+ BUILTIN_FCODE( 0x218, "throw" ) ,
+ BUILTIN_FCODE( 0x219, "user-abort" ) ,
+ BUILTIN_FCODE( 0x21a, "get-my-property" ) ,
+ BUILTIN_FCODE( 0x21a, "get-my-attribute" ) , /* Synonym for "get-my-property" */
+ BUILTIN_FCODE( 0x21b, "decode-int" ) ,
+ BUILTIN_FCODE( 0x21b, "xdrtoint" ) , /* Synonym for "decode-int" */
+ BUILTIN_FCODE( 0x21c, "decode-string" ) ,
+ BUILTIN_FCODE( 0x21c, "xdrtostring" ), /* Synonym for "decode-string" */
+ BUILTIN_FCODE( 0x21d, "get-inherited-property" ) ,
+ BUILTIN_FCODE( 0x21d, "get-inherited-attribute" ) , /* Synonym for "get-inherited-property" */
+ BUILTIN_FCODE( 0x21e, "delete-property" ) ,
+ BUILTIN_FCODE( 0x21e, "delete-attribute" ) , /* Synonym for "delete-property" */
+ BUILTIN_FCODE( 0x21f, "get-package-property" ) ,
+ BUILTIN_FCODE( 0x21f, "get-package-attribute" ) , /* Synonym for "get-package-property" */
+ BUILTIN_FCODE( 0x220, "cpeek" ) ,
+ BUILTIN_FCODE( 0x221, "wpeek" ) ,
+ BUILTIN_FCODE( 0x222, "lpeek" ) ,
+ BUILTIN_FCODE( 0x223, "cpoke" ) ,
+ BUILTIN_FCODE( 0x224, "wpoke" ) ,
+ BUILTIN_FCODE( 0x225, "lpoke" ) ,
+ BUILTIN_FCODE( 0x226, "lwflip" ) ,
+ BUILTIN_FCODE( 0x227, "lbflip" ) ,
+ BUILTIN_FCODE( 0x228, "lbflips" ) ,
+ OBSOLETE_FCODE( 0x229, "adr-mask" ) ,
+ BUILTIN_FCODE( 0x230, "rb@" ) ,
+ BUILTIN_FCODE( 0x231, "rb!" ) ,
+ BUILTIN_FCODE( 0x232, "rw@" ) ,
+ BUILTIN_FCODE( 0x233, "rw!" ) ,
+ BUILTIN_FCODE( 0x234, "rl@" ) ,
+ BUILTIN_FCODE( 0x235, "rl!" ) ,
+ BUILTIN_FCODE( 0x236, "wbflips" ) ,
+ BUILTIN_FCODE( 0x236, "wflips" ) , /* Synonym for "wbflips" */
+ BUILTIN_FCODE( 0x237, "lwflips" ) ,
+ BUILTIN_FCODE( 0x237, "lflips" ) , /* Synonym for "lwflips" */
+ OBSOLETE_FCODE( 0x238, "probe" ) ,
+ OBSOLETE_FCODE( 0x239, "probe-virtual" ) ,
+ BUILTIN_FCODE( 0x23b, "child" ) ,
+ BUILTIN_FCODE( 0x23c, "peer" ) ,
+ BUILTIN_FCODE( 0x23d, "next-property" ) ,
+ BUILTIN_FCODE( 0x23e, "byte-load" ) ,
+ BUILTIN_FCODE( 0x23f, "set-args" ) ,
+ BUILTIN_FCODE( 0x240, "left-parse-string" ) ,
+
/* FCodes from 64bit extension addendum */
- add_token( 0x22e, "rx@" );
- add_token( 0x22f, "rx!" );
- add_token( 0x241, "bxjoin" );
- add_token( 0x242, "<l@" );
- add_token( 0x243, "lxjoin" );
- add_token( 0x244, "wxjoin" );
- add_token( 0x245, "x," );
- add_token( 0x246, "x@" );
- add_token( 0x247, "x!" );
- add_token( 0x248, "/x" );
- add_token( 0x249, "/x*" );
- add_token( 0x24a, "xa+" );
- add_token( 0x24b, "xa1+" );
- add_token( 0x24c, "xbflip" );
- add_token( 0x24d, "xbflips" );
- add_token( 0x24e, "xbsplit" );
- add_token( 0x24f, "xlflip" );
- add_token( 0x250, "xlflips" );
- add_token( 0x251, "xlsplit" );
- add_token( 0x252, "xwflip" );
- add_token( 0x253, "xwflips" );
- add_token( 0x254, "xwsplit" );
+ BUILTIN_FCODE( 0x22e, "rx@" ) ,
+ BUILTIN_FCODE( 0x22f, "rx!" ) ,
+ BUILTIN_FCODE( 0x241, "bxjoin" ) ,
+ BUILTIN_FCODE( 0x242, "<l@" ) ,
+ BUILTIN_FCODE( 0x243, "lxjoin" ) ,
+ BUILTIN_FCODE( 0x244, "wxjoin" ) ,
+ BUILTIN_FCODE( 0x245, "x," ) ,
+ BUILTIN_FCODE( 0x246, "x@" ) ,
+ BUILTIN_FCODE( 0x247, "x!" ) ,
+ BUILTIN_FCODE( 0x248, "/x" ) ,
+ BUILTIN_FCODE( 0x249, "/x*" ) ,
+ BUILTIN_FCODE( 0x24a, "xa+" ) ,
+ BUILTIN_FCODE( 0x24b, "xa1+" ) ,
+ BUILTIN_FCODE( 0x24c, "xbflip" ) ,
+ BUILTIN_FCODE( 0x24d, "xbflips" ) ,
+ BUILTIN_FCODE( 0x24e, "xbsplit" ) ,
+ BUILTIN_FCODE( 0x24f, "xlflip" ) ,
+ BUILTIN_FCODE( 0x250, "xlflips" ) ,
+ BUILTIN_FCODE( 0x251, "xlsplit" ) ,
+ BUILTIN_FCODE( 0x252, "xwflip" ) ,
+ BUILTIN_FCODE( 0x253, "xwflips" ) ,
+ BUILTIN_FCODE( 0x254, "xwsplit" )
+};
- add_special(COLON, ":");
- add_special(SEMICOLON, ";");
- add_special(TOKENIZE, "'");
- add_special(AGAIN, "again");
- add_special(ALIAS, "alias");
- add_special(GETTOKEN, "[']");
- add_special(ASCII, "ascii");
- add_special(BEGIN, "begin");
- add_special(BUFFER, "buffer:");
- add_special(CASE, "case");
- add_special(CONST, "constant");
- add_special(CONTROL, "control");
- add_special(CREATE, "create");
- add_special(DECIMAL, "decimal");
- add_special(DEFER, "defer");
- add_special(CDO, "?do");
- add_special(DO, "do");
- add_special(ELSE, "else");
- add_special(ENDCASE, "endcase");
- add_special(ENDOF, "endof");
- add_special(EXTERNAL, "external");
- add_special(FIELD, "field");
- add_special(HEADERLESS, "headerless");
- add_special(HEADERS, "headers");
- add_special(HEX, "hex");
- add_special(IF, "if");
- add_special(CLEAVE, "?leave");
- add_special(LEAVE, "leave");
- add_special(CLOOP, "+loop");
- add_special(LOOP, "loop");
- add_special(OCTAL, "octal");
- add_special(OF, "of");
- add_special(REPEAT, "repeat");
- add_special(THEN, "then");
- add_special(TO, "to");
- add_special(UNTIL, "until");
- add_special(VALUE, "value");
- add_special(VARIABLE, "variable");
- add_special(WHILE, "while");
- add_special(OFFSET16, "offset16");
- add_special(BEGINTOK, "tokenizer[");
- add_special(EMITBYTE, "emit-byte");
- add_special(ENDTOK, "]tokenizer");
- add_special(FLOAD, "fload");
- add_special(STRING, "\"");
- add_special(PSTRING, ".\"");
- add_special(PBSTRING, ".(");
- add_special(SSTRING, "s\"");
- add_special(RECURSIVE, "recursive");
- add_special(NEXTFCODE, "next-fcode");
+static const int number_of_builtin_tokens =
+ sizeof(tokens_table)/sizeof(tic_hdr_t);
+
+/* **************************************************************************
+ *
+ * Support functions specific to the FCode-Tokens list.
+ *
+ **************************************************************************** */
+
+
+/* **************************************************************************
+ *
+ * Function name: emit_token
+ * Synopsis: Emit the FCode token for the given FCode name.
+ *
+ * Inputs:
+ * Parameters:
+ * fc_name The name of the FCode
+ * Local Static Variables:
+ * fc_tokens_list_start "Tail" of the "FC-Tokens" list
+ *
+ * Outputs:
+ * Returned Value: NONE
+ *
+ * Error Detection:
+ * This routine should only be called with hard-coded names from
+ * within the program. If the given name is not found in
+ * the Built-in Tokens Table, that is a FATAL error.
+ *
+ * Process Explanation:
+ * Because the "FCode-Tokens" table was linked first, and the
+ * pointer kept for this purpose, the "FC-Tokens" list can
+ * be a subset of the "core" list, yet, when necessary, can
+ * be searched with the same routines.
+ *
+ * Extraneous Remarks:
+ * I will bend the strict rules of well-structured code;
+ * the exception case should never occur.
+ *
+ **************************************************************************** */
+
+void emit_token( const char *fc_name)
+{
+
+ if ( handle_tic_vocab( (char *)fc_name, fc_tokens_list_start) )
+ {
+ return;
+ }
+
+ tokenization_error( FATAL, "Did not recognize FCode name %s", fc_name);
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: lookup_token
+ * Synopsis: Return a pointer to the data-structure of the named
+ * word in the "FC-Tokens" list
+ *
+ * Inputs:
+ * Parameters:
+ * tname The name to look up
+ * Local Static Variables:
+ * fc_tokens_list_start "Tail" of the "FC-Tokens" list
+ *
+ * Outputs:
+ * Returned Value: Pointer to the data-structure, or
+ * NULL if not found.
+ *
+ **************************************************************************** */
+
+tic_hdr_t *lookup_token( char *tname)
+{
+ tic_hdr_t *found ;
+
+ found = lookup_tic_entry( tname, fc_tokens_list_start);
+ return ( found ) ;
+}
+
+/* **************************************************************************
+ *
+ * Function name: entry_is_token
+ * Synopsis: Indicate whether the supplied pointer to a tic_hdr_t
+ * data-structure is one for which a single-token FCode
+ * number is assigned.
+ *
+ * Inputs:
+ * Parameters:
+ * test_entry The entry to test; may be NULL
+ * Local macros:
+ * FC_TOKEN_FUNC The function associated with
+ * most single-token entries.
+ * OBSO_FC_FUNC The function associated with
+ * "obsolete" FCode tokens.
+ *
+ * Outputs:
+ * Returned Value: TRUE if the data-structure is
+ * a single-token entry.
+ *
+ * Process Explanation:
+ * We cannot rely on the "definer" field to indicate whether
+ * it is a single-token entry; instead, we will look at
+ * the associated function.
+ * Keep this routine here to avoid needing to export the names
+ * of the permitted functions or their synonymous macros.
+ * If we ever need to change it, we can do so at a single
+ * point of maintenance.
+ * Because the entry might have been found in the initial list
+ * of entries to the "FCode-Tokens" list, we need to check
+ * whether the associated function is either the general
+ * single-token emitting function, FC_TOKEN_FUNC , or the
+ * function OBSO_FC_FUNC , which presents a message before
+ * emitting, but is still a valid single-token function.
+ *
+ **************************************************************************** */
+
+bool entry_is_token( tic_hdr_t *test_entry )
+{
+ bool retval = FALSE;
+ if ( test_entry != NULL )
+ {
+ if ( ( test_entry->funct == FC_TOKEN_FUNC ) ||
+ ( test_entry->funct == OBSO_FC_FUNC ) )
+ {
+ retval = TRUE;
+ }
+ }
+ return ( retval );
+}
+
+/* **************************************************************************
+ *
+ * Function name: token_entry_warning
+ * Synopsis: Issue whatever warnings the given token_entry
+ * requires. F['] needs this.
+ * Inputs:
+ * Parameters:
+ * test_entry The entry to test; may be NULL
+ * Local macro:
+ * OBSO_FC_FUNC The function associated with
+ * "obsolete" entries.
+ * Outputs:
+ * Returned Value: NONE
+ *
+ * Error Detection:
+ * Warnings required by the given token_entry.
+ *
+ * Extraneous Remarks:
+ * At present, it's only the "Obsolete" warning.
+ * But this is the place to add others,
+ * should they become necessary.
+ *
+ **************************************************************************** */
+
+void token_entry_warning( tic_hdr_t *t_entry)
+{
+ if ( t_entry->funct == OBSO_FC_FUNC )
+ {
+ obsolete_warning();
+ }
+}
+
+
+/* **************************************************************************
+ *
+ * Create the initial "FWords" list.
+ *
+ **************************************************************************** */
+
+static tic_fwt_hdr_t fwords_list[] = {
+
+ BI_FWD_SKP_OW(COLON, ":") ,
+ BUILTIN_FWORD(SEMICOLON, ";") ,
+ BI_FWD_SKP_OW(TICK, "'") ,
+ BUILTIN_FWORD(AGAIN, "again") ,
+ BI_FWD_SKP_OW(BRACK_TICK, "[']") ,
+ BI_FWD_SKP_OW(ASCII, "ascii") ,
+ BUILTIN_FWORD(BEGIN, "begin") ,
+ BI_FWD_SKP_OW(BUFFER, "buffer:") ,
+ BUILTIN_FWORD(CASE, "case") ,
+ BI_FWD_SKP_OW(CONST, "constant") ,
+ BI_FWD_SKP_OW(CONTROL, "control") ,
+ BI_FWD_SKP_OW(CREATE, "create") ,
+
+ BI_FWD_SKP_OW(DEFER, "defer") ,
+ BUILTIN_FWORD(CDO, "?do") ,
+ BUILTIN_FWORD(DO, "do") ,
+ BUILTIN_FWORD(ELSE, "else") ,
+ BUILTIN_FWORD(ENDCASE, "endcase") ,
+ BUILTIN_FWORD(ENDOF, "endof") ,
+ BUILTIN_FWORD(EXTERNAL, "external") ,
+ BI_FWD_SKP_OW(FIELD, "field") ,
+ BUILTIN_FWORD(FINISH_DEVICE, "finish-device" ) ,
+ BUILTIN_FWORD(HEADERLESS, "headerless") ,
+ BUILTIN_FWORD(HEADERS, "headers") ,
+
+ BUILTIN_FWORD(INSTANCE , "instance") ,
+
+ BUILTIN_FWORD(IF, "if") ,
+ BUILTIN_FWORD(UNLOOP, "unloop") ,
+ BUILTIN_FWORD(LEAVE, "leave") ,
+ BUILTIN_FWORD(PLUS_LOOP, "+loop") ,
+ BUILTIN_FWORD(LOOP, "loop") ,
+
+ BUILTIN_FWORD(OF, "of") ,
+ BUILTIN_FWORD(REPEAT, "repeat") ,
+ BUILTIN_FWORD(THEN, "then") ,
+ BI_FWD_SKP_OW(TO, "to") ,
+ BI_FWD_SKP_OW(IS, "is") , /* Deprecated synonym to TO */
+ BUILTIN_FWORD(UNTIL, "until") ,
+ BI_FWD_SKP_OW(VALUE, "value") ,
+ BI_FWD_SKP_OW(VARIABLE, "variable") ,
+ BUILTIN_FWORD(WHILE, "while") ,
+ BUILTIN_FWORD(OFFSET16, "offset16") ,
+
+ BI_FWD_STRING(STRING, "\"") , /* XXXXX */
+ BI_FWD_STRING(PSTRING, ".\"") , /* XXXXX */
+ BI_FWD_STRING(PBSTRING, ".(") , /* XXXXX */
+ BI_FWD_STRING(SSTRING, "s\"") , /* XXXXX */
+ BUILTIN_FWORD(IFILE_NAME, "[input-file-name]"),
+ BUILTIN_FWORD(ILINE_NUM, "[line-number]"),
+ BUILTIN_FWORD(RECURSE, "recurse") ,
+ BUILTIN_FWORD(RECURSIVE, "recursive") ,
+ BUILTIN_FWORD(RET_STK_FETCH, "r@") ,
+ BUILTIN_FWORD(RET_STK_FROM, "r>") ,
+ BUILTIN_FWORD(RET_STK_TO, ">r") ,
+ BUILTIN_FWORD(THEN, "endif" ) , /* Synonym for "then" */
+ BUILTIN_FWORD(NEW_DEVICE, "new-device" ) ,
+ BUILTIN_FWORD(LOOP_I, "i") ,
+ BUILTIN_FWORD(LOOP_J, "j") ,
/* version1 is also an fcode word, but it
* needs to trigger some tokenizer internals */
- add_special(VERSION1, "version1");
- add_special(START0, "start0");
- add_special(START1, "start1");
- add_special(START2, "start2");
- add_special(START4, "start4");
- add_special(END0, "end0");
- add_special(END1, "end1");
- add_special(FCODE_V1, "fcode-version1");
- add_special(FCODE_V2, "fcode-version2");
- add_special(FCODE_V3, "fcode-version3");
- add_special(FCODE_END, "fcode-end");
- add_special(FCODE_DATE, "fcode-date");
- add_special(FCODE_TIME, "fcode-time");
-
- add_special(HEXVAL, "h#");
- add_special(DECVAL, "d#");
- add_special(OCTVAL, "o#");
- add_special(CHAR, "char");
- add_special(CCHAR, "[char]");
- add_special(ABORTTXT, "abort\"");
+ BUILTIN_FWORD(VERSION1, "version1") ,
+ BUILTIN_FWORD(START0, "start0") ,
+ BUILTIN_FWORD(START1, "start1") ,
+ BUILTIN_FWORD(START2, "start2") ,
+ BUILTIN_FWORD(START4, "start4") ,
+ BUILTIN_FWORD(END0, "end0") ,
+ BUILTIN_FWORD(END1, "end1") ,
+ BUILTIN_FWORD(FCODE_V1, "fcode-version1") ,
+ BUILTIN_FWORD(FCODE_V2, "fcode-version2") ,
+ BUILTIN_FWORD(FCODE_V3, "fcode-version3") ,
+ BUILTIN_FWORD(FCODE_END, "fcode-end") ,
- add_special(ENCODEFILE, "encode-file");
+ /* Support for IBM-style Locals */
+ BI_FWD_STRING(CURLY_BRACE, "{") ,
+ BI_FWD_STRING(DASH_ARROW, "->") ,
+ BUILTIN_FWORD(EXIT, "exit") ,
+
+ BUILTIN_FWORD(CHAR, "char") ,
+ BUILTIN_FWORD(CCHAR, "[char]") ,
+ BI_FWD_STRING(ABORTTXT, "abort\"") ,
+
+ BUILTIN_FWORD(ENCODEFILE, "encode-file") ,
+
+ BI_IG_FW_HDLR(ESCAPETOK, "tokenizer[") ,
+ BI_IG_FW_HDLR(ESCAPETOK, "f[") , /* An IBM-ish synonym */
+};
+
+static const int number_of_builtin_fwords =
+ sizeof(fwords_list)/sizeof(tic_hdr_t);
+
+/* **************************************************************************
+ *
+ * Create the initial list of "Shared_Words" (words that can
+ * be executed similarly both during normal tokenization,
+ * and also within "Tokenizer Escape Mode").
+ *
+ **************************************************************************** */
+
+static tic_fwt_hdr_t shared_words_list[] = {
+ SHARED_FWORD(FLOAD, "fload") ,
+ /* As does the "Allow Multi-Line" directive */
+ SHR_SAMIG_FWRD(ALLOW_MULTI_LINE, "multi-line") ,
+
+ SHR_FWD_SKOW( F_BRACK_TICK, "f[']") ,
+
+ SH_FW_SK2WIL(ALIAS, "alias") ,
+ SHARED_FWORD(DECIMAL, "decimal") ,
+ SHARED_FWORD(HEX, "hex") ,
+ SHARED_FWORD(OCTAL, "octal") ,
+ SH_FW_SK_WIL(HEXVAL, "h#") ,
+ SH_FW_SK_WIL(DECVAL, "d#") ,
+ SH_FW_SK_WIL(OCTVAL, "o#") ,
+
+ SH_FW_SK_WIL(ASC_NUM, "a#") ,
+ SH_FW_SK_WIL(ASC_LEFT_NUM, "al#") ,
+
+ /* IBM-style extension. Might be generalizable... */
+ SHARED_FWORD(FLITERAL, "fliteral") ,
+
+ /* Directives to extract the value of a Command-Line symbol */
+ SH_FW_SK_WIL(DEFINED, "[defined]") ,
+ SH_FW_SK_WIL(DEFINED, "#defined") ,
+ SH_FW_SK_WIL(DEFINED, "[#defined]") ,
+
+ /* Present the current date or time, either as an */
+ /* in-line string or as a user-generated message. */
+ SHARED_FWORD(FCODE_DATE, "[fcode-date]") ,
+ SHARED_FWORD(FCODE_TIME, "[fcode-time]") ,
+
+ /* Current definition under construction, similarly */
+ SHARED_FWORD(FUNC_NAME, "[function-name]"),
+
+ /* Synonymous forms of the #ELSE and #THEN operators,
+ * associated with Conditional-Compilation,
+ * allowing for various syntax-styles, and for
+ * expansion by alias.
+ */
+
+ /* #ELSE operators */
+ SHARED_FWORD(CONDL_ELSE, "#else") ,
+ SHARED_FWORD(CONDL_ELSE, "[else]") ,
+ SHARED_FWORD(CONDL_ELSE, "[#else]") ,
+
+ /* #THEN operators */
+ SHARED_FWORD(CONDL_ENDER, "#then") ,
+ SHARED_FWORD(CONDL_ENDER, "[then]") ,
+ SHARED_FWORD(CONDL_ENDER, "[#then]") ,
+ /* #ENDIF variants for users who favor C-style notation */
+ SHARED_FWORD(CONDL_ENDER, "#endif") ,
+ SHARED_FWORD(CONDL_ENDER, "[endif]") ,
+ SHARED_FWORD(CONDL_ENDER, "[#endif]") ,
+
+
+ SHARED_FWORD(OVERLOAD, "overload" ) ,
+
+ SHARED_FWORD(GLOB_SCOPE , "global-definitions" ) ,
+ SHARED_FWORD(DEV_SCOPE , "device-definitions" ) ,
+
+ /* Directives to change a command-line flag value from source */
+ SH_FW_SK_WIL(CL_FLAG, "[FLAG]") ,
+ SH_FW_SK_WIL(CL_FLAG, "#FLAG") ,
+ SH_FW_SK_WIL(CL_FLAG, "[#FLAG]") ,
+
+ /* Directives to force display of a command-line flags' values */
+ SHARED_FWORD(SHOW_CL_FLAGS, "[FLAGS]") ,
+ SHARED_FWORD(SHOW_CL_FLAGS, "#FLAGS") ,
+ SHARED_FWORD(SHOW_CL_FLAGS, "[#FLAGS]") ,
+ SHARED_FWORD(SHOW_CL_FLAGS, "SHOW-FLAGS") ,
+
+ /* Directives to save and retrieve the FCode Assignment number */
+ SHARED_FWORD(PUSH_FCODE, "FCODE-PUSH") ,
+ SHARED_FWORD(POP_FCODE, "FCODE-POP") ,
+
+ /* Directive to reset the FCode Assignment number and
+ * re-initialize FCode Range overlap checking.
+ */
+ SHARED_FWORD(RESET_FCODE, "FCODE-RESET") ,
+
/* pci header generation is done differently
* across the available tokenizers. We try to
* be compatible to all of them
*/
- add_special(PCIHDR, "pci-header");
- add_special(PCIEND, "pci-end"); /* SUN syntax */
- add_special(PCIEND, "pci-header-end"); /* Firmworks syntax */
- add_special(PCIREV, "pci-revision"); /* SUN syntax */
- add_special(PCIREV, "pci-code-revision"); /* SUN syntax */
- add_special(PCIREV, "set-rev-level"); /* Firmworks syntax */
- add_special(NOTLAST, "not-last-image");
+ SHARED_FWORD(PCIHDR, "pci-header") ,
+ SHARED_FWORD(PCIEND, "pci-end") , /* SUN syntax */
+ SHARED_FWORD(PCIEND, "pci-header-end") , /* Firmworks syntax */
+ SHARED_FWORD(PCIREV, "pci-revision") , /* SUN syntax */
+ SHARED_FWORD(PCIREV, "pci-code-revision") , /* SUN syntax */
+ SHARED_FWORD(PCIREV, "set-rev-level") , /* Firmworks syntax */
+ SHARED_FWORD(NOTLAST, "not-last-image") ,
+ SHARED_FWORD(NOTLAST, "not-last-img") , /* Shorthand form */
+ SHARED_FWORD(ISLAST, "last-image") ,
+ SHARED_FWORD(ISLAST, "last-img") , /* Shorthand form */
+ SHARED_FWORD(SETLAST, "set-last-image") ,
+ SHARED_FWORD(SETLAST, "set-last-img") , /* Shorthand form */
+
+ SH_FW_SK_WIL(SAVEIMG, "save-image") ,
+ SH_FW_SK_WIL(SAVEIMG, "save-img") , /* Shorthand form */
+
+ SHARED_FWORD(RESETSYMBS, "reset-symbols") ,
+
+ /* User-Macro definers */
+ SHARED_IG_HDLR("[MACRO]", add_user_macro, 0 , skip_user_macro) ,
+
+ /* Comments and Remarks */
+ SHARED_IG_HDLR("\\", process_remark, '\n', process_remark) ,
+ SHARED_IG_HDLR("(", process_remark, ')', process_remark) ,
+
+ /* Directives to print or discard a user-generated message */
+ SHARED_IG_HDLR("[MESSAGE]", user_message, '\n', skip_user_message) ,
+ SHARED_IG_HDLR("#MESSAGE", user_message, '\n', skip_user_message) ,
+ SHARED_IG_HDLR("[#MESSAGE]", user_message, '\n', skip_user_message) ,
+ SHARED_IG_HDLR("#MESSAGE\"", user_message, '"' , skip_user_message) ,
+};
+
+static const int number_of_shared_words =
+ sizeof(shared_words_list)/sizeof(tic_hdr_t);
+
+/* **************************************************************************
+ *
+ * Function name: lookup_shared_word
+ * Synopsis: Return a pointer to the data-structure of the named
+ * word, only if it is a "Shared Word"
+ *
+ * Inputs:
+ * Parameters:
+ * tname The name to look for
+ * Local Static Variables:
+ * global_voc_dict_ptr "Tail" of Global Vocabulary
+ *
+ * Outputs:
+ * Returned Value: Pointer to the data-structure, or
+ * NULL if not found.
+ *
+ * Process Explanation:
+ * The "Shared Words" are scattered among the Global Vocabulary;
+ * the user is allowed to create aliases, which may be in the
+ * Current-Device. We will search through the "current" scope
+ * and decide whether the name we found is a "Shared Word" by
+ * looking for COMMON_FWORD in the "definer" field.
+ *
+ * Extraneous Remarks:
+ * This is the only place where an additional check of the
+ * "definer" field is required to identify a desired entry.
+ * Should another "definer"-type be required, I recommend
+ * defining a general-purpose function in ticvocab.c and
+ * applying it here and in the other place(s).
+ *
+ **************************************************************************** */
+
+tic_hdr_t *lookup_shared_word( char *tname)
+{
+ tic_hdr_t *found ;
+ tic_hdr_t *retval = NULL ;
+
+ found = lookup_current( tname );
+ if ( found != NULL )
+ {
+ if ( found->fword_defr == COMMON_FWORD )
+ {
+ retval = found ;
+ }
+ }
+
+ return ( retval );
+
}
+
+/* **************************************************************************
+ *
+ * Function name: handle_shared_word
+ * Synopsis: Perform the function associated with the given name
+ * only if it is a "Shared Word". Indicate if it was.
+ *
+ * Inputs:
+ * Parameters:
+ * tname The "target" name for which to look
+ *
+ * Outputs:
+ * Returned Value: TRUE if the name is a valid "Shared Word"
+ *
+ * Extraneous Remarks:
+ * This is very similar to a call to handle_tic_vocab() except
+ * for the additional filtering for a "Shared Word" definer.
+ *
+ **************************************************************************** */
+
+bool handle_shared_word( char *tname )
+{
+ tic_hdr_t *found ;
+ bool retval = FALSE;
+
+ found = lookup_shared_word( tname );
+ if ( found != NULL )
+ {
+ found->funct(found->pfield);
+ retval = TRUE;
+ }
+
+ return ( retval ) ;
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: lookup_shared_f_exec_word
+ * Synopsis: Return a pointer to the data-structure of the named
+ * word, only if it is a "Shared F-Exec Word"
+ *
+ * Inputs:
+ * Parameters:
+ * tname The name to look for
+ * Local Static Variables:
+ * global_voc_dict_ptr "Tail" of Global Vocabulary
+ * Macro Definitions:
+ * FWORD_EXEC_FUNC The "Active" function of the
+ * sub-class of "Shared Word"s
+ * that is the object of this
+ * routine's search
+ *
+ * Outputs:
+ * Returned Value: Pointer to the data-structure, or
+ * NULL if not found.
+ *
+ * Process Explanation:
+ * The "Shared F-Exec Words" are the subset of "Shared Words" that
+ * have the FWORD_EXEC_FUNC as their "Active" function.
+ *
+ * Extraneous Remarks:
+ * This is the only routine that requires a check of two fields;
+ * it seems unlikely that there will be any need to generalize
+ * the core of this routine...
+ *
+ **************************************************************************** */
+
+tic_hdr_t *lookup_shared_f_exec_word( char *tname)
+{
+ tic_hdr_t *found ;
+ tic_hdr_t *retval = NULL ;
+
+ found = lookup_shared_word( tname );
+ if ( found != NULL )
+ {
+ if ( found->funct == FWORD_EXEC_FUNC )
+ {
+ retval = found ;
+ }
+ }
+
+ return ( retval );
+
+}
+
+/* **************************************************************************
+ *
+ * Function name: init_dictionary
+ * Synopsis: Initialize all the vocabularies. For the Global
+ * Vocabulary, fill in the link fields in each of the
+ * otherwise pre-initialized built-in lists, link the
+ * lists together, and set the relevant pointers. For
+ * other lists, call their initialization routines.
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global Variables:
+ * Local Static Variables:
+ * tokens_table Base of the "FC-Tokens" list
+ * number_of_builtin_tokens Number of "FC-Token" entries
+ * fwords_list Base of the "FWords" list
+ * number_of_builtin_fwords Number of "FWord" entries
+ * shared_words_list Base of the "Shared Words" list
+ * number_of_shared_words Number of "Shared Words" entries
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Local Static Variables:
+ * global_voc_dict_ptr "Tail" of Global Vocabulary
+ * fc_tokens_list_start "Tail" of "FC-Tokens" list
+ * fc_tokens_list_ender End of "FC-Tokens" search
+ * shared_fwords_ender End of Shared Words" search
+ * global_voc_reset_ptr Reset-point for Global Vocab
+ *
+ * Process Explanation:
+ * The first linked will be the last searched.
+ * Link the "FC-Tokens" first, and mark their limits
+ * Link the "FWords" next,
+ * Mark the end-limit of the "Shared Words", and link them
+ * The "Conditionals", defined in another file, are also "Shared";
+ * link them next.
+ * Then link the Built-In Macros, also defined in another file.
+ * These constitute the Global Vocabulary.
+ * Mark the reset-point for the Global Vocabulary.
+ * The "Tokenizer Escape" mode vocabulary is not linked to the Global
+ * Vocabulary; call its initialization routine.
+ *
+ * Extraneous Remarks:
+ * I only wish I had done this sooner...
+ *
+ **************************************************************************** */
+
+void init_dictionary( void )
+{
+
+ global_voc_dict_ptr = NULL; /* Belt-and-suspenders... */
+
+ /* The "FC-Tokens" list must be linked first. */
+ fc_tokens_list_ender = global_voc_dict_ptr;
+ init_tic_vocab( tokens_table,
+ number_of_builtin_tokens,
+ &global_voc_dict_ptr ) ;
+ fc_tokens_list_start = global_voc_dict_ptr;
+
+ /* Link the "FWords" next */
+ init_tic_vocab( (tic_hdr_t *)fwords_list,
+ number_of_builtin_fwords,
+ &global_voc_dict_ptr ) ;
+
+ /* Mark the end-limit of the "Shared Words", and link them. */
+ shared_fwords_ender = global_voc_dict_ptr;
+ init_tic_vocab( (tic_hdr_t *)shared_words_list,
+ number_of_shared_words,
+ &global_voc_dict_ptr ) ;
+
+ /* Link the "Conditionals" to the Global Vocabulary. */
+ init_conditionals_vocab( &global_voc_dict_ptr ) ;
+
+ /* Link the Built-In Macros */
+ init_macros( &global_voc_dict_ptr ) ;
+
+ /* Mark the reset-point for the Global Vocabulary. */
+ global_voc_reset_ptr = global_voc_dict_ptr;
+
+ /* Initialize the "Tokenizer Escape" mode vocabulary */
+ init_tokz_esc_vocab();
+
+ /* Locals and Device-Node vocabularies are initially empty */
+
+}
+
+/* **************************************************************************
+ *
+ * Function name: reset_normal_vocabs
+ * Synopsis: Reset the vocabularies that were created in "Normal"
+ * (as distinguished from "Tokenizer Escape") mode
+ * to the proper state for a fresh tokenization.
+ *
+ * Associated FORTH words: END0 END1
+ * Associated Tokenizer directives: RESET-SYMBOLS (in "Normal" mode)
+ * FCODE-END
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global Variables:
+ * global_voc_reset_ptr Position to which to reset
+ * the "Global" Vocabulary
+ * current_device_node Vocab struct of current dev-node
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global Variables:
+ * global_voc_dict_ptr Reset to "Built-In" position
+ * current_device_node Reset to point at "root" dev-node
+ * Memory Freed
+ * All memory allocated by user-definitions in "normal" mode
+ * -- Macros, Conditionals and Device-node Vocabularies -- are
+ * reset via function call.
+ *
+ * Error Detection:
+ * Presence of extra device-node data structure(s) indicates that
+ * there were more "new-device" calls than "finish-device";
+ * report each as an ERROR
+ *
+ * Process Explanation:
+ * Vocabularies created in other files, that have different
+ * data-structures, will have "reset" routines of their
+ * own associated with them in the files in which they
+ * are created. Those routines will be called from here.
+ * Definitions in the "Tokenizer Escape Vocabulary", i.e.,
+ * the one in effect in "Tokenizer Escape" mode, are
+ * specifically not touched by this routine.
+ *
+ **************************************************************************** */
+
+void reset_normal_vocabs( void )
+{
+ reset_tic_vocab( &global_voc_dict_ptr, global_voc_reset_ptr );
+
+ /* Delete the top-level device-node vocab.
+ * If there are extra device-nodes,
+ * delete their data structures and show errors
+ */
+ do
+ {
+ if ( current_device_node->parent_node != NULL )
+ {
+ tokenization_error( TKERROR,
+ "Missing FINISH-DEVICE for new device");
+ started_at( current_device_node->ifile_name,
+ current_device_node->line_no );
+ }
+ delete_device_vocab();
+ } while ( current_device_node->parent_node != NULL );
+
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: reset_vocabs
+ * Synopsis: Reset all the vocabularies to the proper state
+ * for beginning a fresh tokenization, particularly
+ * when multiple files are named on the command-line
+ *
+ * Inputs:
+ * Parameters: NONE
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Memory Freed
+ * All memory allocated by user-definitions will be freed
+ *
+ * Process Explanation:
+ * Call the reset_normal_vocabs() routine to get the vocabularies
+ * that apply to "Normal" mode, then call the "reset" routine
+ * for the "Tokenizer Escape Vocabulary", which is supposed
+ * to persist across device-nodes but not across input-files
+ * named on the command-line.
+ *
+ **************************************************************************** */
+
+void reset_vocabs( void )
+{
+ reset_normal_vocabs();
+ reset_tokz_esc();
+}
Modified: fcode-utils/toke/dictionary.h
===================================================================
--- fcode-utils/toke/dictionary.h 2006-08-18 09:45:11 UTC (rev 75)
+++ fcode-utils/toke/dictionary.h 2006-08-18 12:47:12 UTC (rev 76)
@@ -1,3 +1,6 @@
+#ifndef _TOKE_DICTIONARY_H
+#define _TOKE_DICTIONARY_H
+
/*
* OpenBIOS - free your system!
* ( FCode tokenizer )
@@ -24,81 +27,152 @@
*
*/
-#define COLON 0x01
-#define SEMICOLON 0x02
-#define TOKENIZE 0x03
-#define AGAIN 0x04
-#define ALIAS 0x05
-#define GETTOKEN 0x06
-#define ASCII 0x07
-#define BEGIN 0x08
-#define BUFFER 0x09
-#define CASE 0x0a
-#define CONST 0x0b
-#define CONTROL 0x0c
-#define CREATE 0x0d
-#define DECIMAL 0x0e
-#define DEFER 0x0f
-#define CDO 0x10
-#define DO 0x11
-#define ELSE 0x12
-#define ENDCASE 0x13
-#define ENDOF 0x14
-#define EXTERNAL 0x15
-#define FIELD 0x16
-#define HEADERLESS 0x17
-#define HEADERS 0x18
-#define HEX 0x19
-#define IF 0x1a
-#define CLEAVE 0x1b
-#define LEAVE 0x1c
-#define CLOOP 0x1d
-#define LOOP 0x1e
-#define OCTAL 0x1f
-#define OF 0x20
-#define REPEAT 0x21
-#define THEN 0x22
-#define TO 0x23
-#define UNTIL 0x24
-#define VALUE 0x25
-#define VARIABLE 0x26
-#define WHILE 0x27
-#define OFFSET16 0x28
-#define BEGINTOK 0x29
-#define EMITBYTE 0x2a
-#define ENDTOK 0x2b
-#define FLOAD 0x2c
-#define STRING 0x2d
-#define PSTRING 0x2e
-#define PBSTRING 0x2f
-#define SSTRING 0x30
-#define RECURSIVE 0x31
-#define HEXVAL 0x32
-#define DECVAL 0x33
-#define OCTVAL 0x34
+/* **************************************************************************
+ * Modifications made in 2005 by IBM Corporation
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Modifications Author: David L. Paktor dlpaktor(a)us.ibm.com
+ **************************************************************************** */
-#define END0 0xdb
-#define END1 0xdc
-#define CHAR 0xdd
-#define CCHAR 0xde
-#define ABORTTXT 0xdf
+/* **************************************************************************
+ *
+ * Numeric values for FWord-type vocabulary entries. Used by the
+ * big "switch" statement in handle_internal(); a subset are
+ * also used as "definer-type" values associated with various
+ * types of definitions.
+ *
+ **************************************************************************** */
-#define NEXTFCODE 0xef
+typedef enum fword_token {
+ UNSPECIFIED = 0xBAADD00D , /* Default (absence-of) "definer" */
+ COMMON_FWORD = 0xC0EDC0DE , /* Definer indicating a "shared" FWord */
+ BI_FWRD_DEFN = 0xB1F4409D , /* Definer indicating a "built-in FWord" */
+ COLON = 1 ,
+ SEMICOLON ,
+ TICK ,
+ AGAIN ,
+ ALIAS ,
+ BRACK_TICK ,
+ F_BRACK_TICK ,
+ ASCII ,
+ BEGIN ,
+ BUFFER ,
+ CASE ,
+ CONST ,
+ CONTROL ,
+ CREATE ,
+ DECIMAL ,
+ DEFER ,
+ DEFINED ,
+ CDO ,
+ DO ,
+ ELSE ,
+ ENDCASE ,
+ ENDOF ,
+ EXTERNAL ,
+ INSTANCE ,
+ FIELD ,
+ NEW_DEVICE ,
+ FINISH_DEVICE ,
+ FLITERAL ,
+ HEADERLESS ,
+ HEADERS ,
+ HEX ,
+ IF ,
+ UNLOOP ,
+ LEAVE ,
+ LOOP_I ,
+ LOOP_J ,
+ LOOP ,
+ PLUS_LOOP ,
+ OCTAL ,
+ OF ,
+ REPEAT ,
+ THEN ,
+ TO ,
+ IS ,
+ UNTIL ,
+ VALUE ,
+ VARIABLE ,
+ WHILE ,
+ OFFSET16 ,
+ ESCAPETOK ,
+ EMITBYTE ,
+ FLOAD ,
+ STRING ,
+ PSTRING ,
+ PBSTRING ,
+ SSTRING ,
+ RECURSIVE ,
+ RECURSE ,
+ RET_STK_FETCH ,
+ RET_STK_FROM ,
+ RET_STK_TO ,
+ HEXVAL ,
+ DECVAL ,
+ OCTVAL ,
-#define ENCODEFILE 0xf0
+ ret_stk_from ,
+ ASC_NUM , /* Convert char seq to number */
+ ASC_LEFT_NUM , /* same, only left-justified. */
-#define FCODE_V1 0xf1
-#define FCODE_V3 0xf2
-#define NOTLAST 0xf3
-#define PCIREV 0xf4
-#define PCIHDR 0xf5
-#define PCIEND 0xf6
-#define START0 0xf7
-#define START1 0xf8
-#define START2 0xf9
-#define START4 0xfa
-#define VERSION1 0xfb
-#define FCODE_TIME 0xfc
-#define FCODE_DATE 0xfd
-#define FCODE_V2 0xfe
-#define FCODE_END 0xff
+ CONDL_ENDER , /* Conditional "[THEN] / [ENDIF]" variants */
+ CONDL_ELSE , /* Conditional "[ELSE]" directive variants */
+
+ PUSH_FCODE , /* Save the FCode Assignment number */
+ POP_FCODE , /* Retrieve the FCode Assignment number */
+ RESET_FCODE , /* Reset FCode Ass't nr and overlap checking */
+
+ CURLY_BRACE , /* Support for IBM-style Locals */
+ DASH_ARROW ,
+ LOCAL_VAL ,
+ EXIT ,
+
+ FUNC_NAME ,
+ IFILE_NAME ,
+ ILINE_NUM ,
+
+ CL_FLAG ,
+ SHOW_CL_FLAGS ,
+
+ OVERLOAD ,
+ ALLOW_MULTI_LINE ,
+ MACRO_DEF ,
+ GLOB_SCOPE ,
+ DEV_SCOPE ,
+
+ /* This value has to be adjusted
+ * so that FCODE_END comes
+ * out to be 0xff
+ */
+ END0 = 0xd7 , /* 0xd7 */
+ END1 , /* 0xd8 */
+ CHAR , /* 0xd9 */
+ CCHAR , /* 0xda */
+ ABORTTXT , /* 0xdb */
+
+ NEXTFCODE , /* 0xdc */
+
+ ENCODEFILE , /* 0xdd */
+
+ FCODE_V1 , /* 0xde */
+ FCODE_V3 , /* 0xdf */
+ NOTLAST , /* 0xef */
+ ISLAST , /* 0xf0 */
+ SETLAST , /* 0xf1 */
+ PCIREV , /* 0xf2 */
+ PCIHDR , /* 0xf3 */
+ PCIEND , /* 0xf4 */
+ RESETSYMBS , /* 0xf5 */
+ SAVEIMG , /* 0xf6 */
+ START0 , /* 0xf7 */
+ START1 , /* 0xf8 */
+ START2 , /* 0xf9 */
+ START4 , /* 0xfa */
+ VERSION1 , /* 0xfb */
+ FCODE_TIME , /* 0xfc */
+ FCODE_DATE , /* 0xfd */
+ FCODE_V2 , /* 0xfe */
+ FCODE_END = 0xff /* 0xff */
+} fwtoken ;
+
+#endif /* _TOKE_DICTIONARY_H */
Modified: fcode-utils/toke/emit.c
===================================================================
--- fcode-utils/toke/emit.c 2006-08-18 09:45:11 UTC (rev 75)
+++ fcode-utils/toke/emit.c 2006-08-18 12:47:12 UTC (rev 76)
@@ -24,283 +24,548 @@
*
*/
+/* **************************************************************************
+ * Modifications made in 2005 by IBM Corporation
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Modifications Author: David L. Paktor dlpaktor(a)us.ibm.com
+ **************************************************************************** */
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+
+#include "pcihdr.h"
+
#include "toke.h"
+#include "vocabfuncts.h"
#include "stack.h"
+#include "scanner.h"
#include "emit.h"
+#include "clflags.h"
+#include "errhandler.h"
+#include "stream.h"
+#include "nextfcode.h"
-extern bool offs16;
-extern int verbose;
-extern u8 *ostart, *opc, *oend;
+/* **************************************************************************
+ *
+ * Global Variables Imported
+ * verbose Enable optional messages, set by "-v" switch
+ * noerrors "Ignore Errors" flag, set by "-i" switch
+ *
+ **************************************************************************** */
-/* PCI data */
-extern u16 pci_vpd, pci_revision;
-extern bool pci_is_last_image;
-/* header pointers */
-extern u8 *fcode_hdr;
-extern u8 *pci_hdr;
+/* **************************************************************************
+ *
+ * Macro to zero-fill a field of the size of the given structure
+ * into the Output Buffer using the emit_byte() routine.
+ *
+ **************************************************************************** */
-extern bool haveend;
+#define EMIT_STRUCT(x) {int j; for (j=0; j < sizeof(x) ; j++ ) emit_byte(0); }
-u16 lookup_token(char *name);
-static bool little_endian(void)
+/* **************************************************************************
+ *
+ * Local Static Variables, offsets into Output Buffer of ...:
+ * fcode_start_ob_off First FCode-Start byte
+ * fcode_hdr_ob_off FCode Header (Format byte)
+ * fcode_body_ob_off First functional FCode after FCode Header.
+ * pci_hdr_ob_off Start of PCI ROM Header Block structure
+ * pci_data_blk_ob_off Start of PCI Data Header Block structure
+ *
+ * For all of these, -1 means "Not initialized"
+ *
+ *************************************************************************** */
+
+static int fcode_start_ob_off = -1;
+static int fcode_hdr_ob_off = -1;
+static int fcode_body_ob_off = -1;
+static int pci_hdr_ob_off = -1;
+static int pci_data_blk_ob_off = -1;
+
+/* **************************************************************************
+ *
+ * These are to detect a particular error: If FCode has
+ * been written, before an Fcode-start<n> or before
+ * a PCI-header
+ *
+ **************************************************************************** */
+
+static bool fcode_written = FALSE;
+
+/* **************************************************************************
+ *
+ * Variables and Functions Imported, with
+ * Exposure as Limited as possible:
+ * ostart
+ * olen
+ * increase_output_buffer
+ *
+ **************************************************************************** */
+
+extern u8 *ostart;
+extern int olen;
+extern void increase_output_buffer( void);
+
+
+/* **************************************************************************
+ *
+ * Function name: init_emit
+ * Synopsis: Initialize Local Static Variables before starting
+ * Output.
+ * Exposure as Limited as possible.
+ *
+ **************************************************************************** */
+void init_emit( void); /* Prototype. Limit Exposure. */
+void init_emit( void)
{
- static short one=1;
- return *(char *)&one==1;
+ fcode_start_ob_off = -1;
+ fcode_hdr_ob_off = -1;
+ fcode_body_ob_off = -1;
+ pci_hdr_ob_off = -1;
+ pci_data_blk_ob_off = -1;
+ fcode_written = FALSE;
+ haveend = FALSE; /* Get this one too... */
}
-int emit_byte(u8 data)
-{
- u8 *newout;
- int newsize;
- if(opc==oend) {
- /* need more output space */
- newsize = (oend - ostart) * 2;
- printf("Increasing output buffer to %d bytes.\n", newsize);
- if ((newout=realloc(ostart, newsize)) == NULL) {
- printf("toke: could not allocate %d bytes for output buffer\n", newsize);
- exit(-1);
- }
+/* **************************************************************************
+ *
+ * Function name: emit_byte
+ * Synopsis: Fundamental routine for placing a byte
+ * into the Output Buffer. Also, check
+ * whether the buffer needs to be expanded.
+ * For internal use only.
+ *
+ **************************************************************************** */
- /* move pointers */
- opc=newout+(opc-ostart);
- ostart=newout;
- oend=ostart+newsize;
+static void emit_byte(u8 data)
+{
+ if ( opc == olen)
+ {
+ increase_output_buffer();
}
- *opc=data;
+
+ *(ostart+opc) = data ;
opc++;
-
- return 0;
}
-int emit_fcode(u16 tok)
+void emit_fcode(u16 tok)
{
if ((tok>>8))
emit_byte(tok>>8);
emit_byte(tok&0xff);
-
- return 0;
+ fcode_written = TRUE;
}
-int emit_token(const char *name)
+static void emit_num32(u32 num)
{
- return emit_fcode(lookup_token((char *)name));
-}
-
-int emit_num32(u32 num)
-{
emit_byte(num>>24);
emit_byte((num>>16)&0xff);
emit_byte((num>>8)&0xff);
emit_byte(num&0xff);
- return 0;
}
-int emit_num16(u16 num)
+/* **************************************************************************
+ *
+ * Function name: user_emit_byte
+ * Synopsis: Action of user-mandated call to emit-byte.
+ * Covers the corner-case where this is the
+ * first command issued in the source input.
+ *
+ **************************************************************************** */
+
+void user_emit_byte(u8 data)
{
- emit_byte(num>>8);
- emit_byte(num&0xff);
-
- return 0;
+ emit_byte( data);
+ fcode_written = TRUE;
}
-int emit_offset(s16 offs)
+void emit_offset(s16 offs)
{
+ /* Calling routine will test for out-of-range FCode-Offset */
if (offs16)
- emit_num16(offs);
- else
- emit_byte(offs);
-
- return 0;
+ emit_byte(offs>>8);
+ emit_byte(offs&0xff);
}
-s16 receive_offset(void)
+void emit_literal(u32 num)
{
- s16 offs=0;
-
- if (offs16) {
- offs=((*opc)<<8)|(*(opc+1));
- } else
- offs=(*opc);
-
- return offs;
+ emit_token("b(lit)");
+ emit_num32(num);
}
-int emit_string(u8 *string, unsigned int cnt)
+void emit_string(u8 *string, signed int cnt)
{
- unsigned int i=0;
+ signed int i=0;
+ signed int cnt_cpy = cnt;
- if (cnt>255) {
- printf("string too long.");
- exit(1);
+ if ( cnt_cpy > STRING_LEN_MAX )
+ {
+ tokenization_error( TKERROR,
+ "String too long: %d characters. Truncating.\n",cnt);
+ cnt_cpy = STRING_LEN_MAX ;
}
- emit_byte(cnt);
- for (i=0; i<cnt; i++)
+ emit_byte(cnt_cpy);
+ for (i=0; i<cnt_cpy; i++)
emit_byte(string[i]);
-
- return 0;
}
-int emit_fcodehdr(void)
+void emit_fcodehdr(const char *starter_name)
{
- /* We comply with IEEE 1275-1994 */
- emit_byte(0x08);
- /* checksum */
- emit_num16(0);
+ /* Check for error conditions */
+ if ( fcode_written )
+ {
+ tokenization_error( TKERROR ,
+ "Cannot create FCode header after FCode output has begun.\n");
+ if ( ! noerrors ) return ;
+ }
- /* len */
- emit_num32(0);
+ fcode_header_t *fcode_hdr;
- return 0;
+ fcode_start_ob_off = opc;
+ emit_token( starter_name );
+
+ fcode_hdr_ob_off = opc;
+ fcode_hdr = (fcode_header_t *)(ostart+fcode_hdr_ob_off);
+
+ EMIT_STRUCT(fcode_header_t);
+
+ fcode_body_ob_off = opc;
+
+ /* Format = 8 means we comply with IEEE 1275-1994 */
+ fcode_hdr->format = 0x08;
+
}
-int finish_fcodehdr(void)
+/* **************************************************************************
+ *
+ * Function name: finish_fcodehdr
+ * Fill in the FCode header's checksum and length fields, and
+ * reset the FCode-header pointer for the next image.
+ *
+ * If haveend is true then the end0 has already been written
+ * and fcode_ender() has been called.
+ *
+ * Print a WARNING message if the end-of-file was encountered
+ * without an end0 or an fcode-end
+ *
+ * Print an informative message to standard-output giving the
+ * checksum. Call list_fcode_ranges() to print the
+ * value of the last FCode-token that was assigned or
+ * the Ranges of assigned FCode-token values if so be...
+ * The final FCode-binary file-length will be printed
+ * when the binary file is being closed.
+ *
+ **************************************************************************** */
+
+void finish_fcodehdr(void)
{
- u16 checksum=0;
- u32 len,i;
- if(!fcode_hdr)
+ if( fcode_hdr_ob_off == -1 )
{
- printf("warning: trying to fix up unknown fcode header\n");
- return -1;
+ tokenization_error( TKERROR,
+ "Missing FCode header.\n");
+ return ;
}
- /* If the program does not do this, we do */
+ /* If the program did not end cleanly, we'll handle it */
if (!haveend)
+ {
+ tokenization_error ( WARNING,
+ "End-of-file encountered without END0 or FCODE-END. "
+ "Supplying END0\n");
emit_token("end0");
+ fcode_ender();
+ }
- len=(unsigned long)opc-(unsigned long)(fcode_hdr-1);
+ /* Calculate and place checksum and length, if haven't already */
+ if ( fcode_start_ob_off != -1 )
+ {
+ u16 checksum;
+ int length;
+
+ u8 *fcode_body = ostart+fcode_body_ob_off;
+ u8 *ob_end = ostart+opc;
+ fcode_header_t *fcode_hdr =
+ (fcode_header_t *)(ostart+fcode_hdr_ob_off);
- for (i=8;i<len;i++)
- checksum+=fcode_hdr[i-1];
+ length = opc - fcode_start_ob_off;
- dpush((unsigned long)opc);
- opc=fcode_hdr+1;
- emit_num16(checksum);
- emit_num32(len);
- opc=(u8 *)dpop();
+ for ( checksum = 0;
+ fcode_body < ob_end ;
+ checksum += *(fcode_body++) ) ;
+
+ BIG_ENDIAN_WORD_STORE(fcode_hdr->checksum , checksum);
+ BIG_ENDIAN_LONG_STORE(fcode_hdr->length , length);
+
if (verbose)
- printf("toke: checksum is 0x%04x (%d bytes)\n",
- checksum, len);
+ {
+ printf( "toke: checksum is 0x%04x (%d bytes). ",
+ checksum, length);
+ list_fcode_ranges( TRUE);
+ }
+ }
- fcode_hdr=NULL;
+ /* Reset things for the next image... */
+ fcode_start_ob_off = -1;
+ fcode_hdr_ob_off = -1;
+ fcode_body_ob_off = -1;
+ fcode_written = FALSE;
haveend=FALSE;
- return 0;
}
-int emit_pcihdr(u16 vid, u16 did, u32 classid)
+/* **************************************************************************
+ *
+ * Function name: emit_pci_rom_hdr
+ * Synopsis: Write the PCI ROM Header Block into the Output Buffer
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global Variables:
+ * opc Output Buffer Position Counter
+ * ostart Start of Output Buffer
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global Variables:
+ * pci_hdr_ob_off PCI ROM Header Block Position
+ * (Offset) in Output Buffer
+ * FCode Output buffer:
+ * Write the part of the PCI ROM Header Block we know:
+ * Fill in the signature and the field reserved for
+ * "processor architecture unique data".
+ * Fill in the "Pointer to PCI Data Structure" with the
+ * size of the data structure, because the first PCI
+ * Data Structure will follow immediately.
+ *
+ * Error Detection: (Handled by calling routine)
+ *
+ **************************************************************************** */
+
+static void emit_pci_rom_hdr(void)
{
- int i;
+ rom_header_t *pci_hdr;
+ pci_hdr_ob_off = opc;
+ pci_hdr = (rom_header_t *)(ostart + pci_hdr_ob_off);
+
+ EMIT_STRUCT(rom_header_t);
/* PCI start signature */
- emit_byte(0x55); emit_byte(0xaa);
+ LITTLE_ENDIAN_WORD_STORE(pci_hdr->signature,0xaa55);
/* Processor architecture */
- emit_byte(0x34); emit_byte(0x00);
+ /* Note:
+ * The legacy code used to read:
+ *
+ * pci_hdr->reserved[0] = 0x34;
+ *
+ * I don't know what significance the literal 34 had, but
+ * by what might just be an odd coincidence, it is equal
+ * to the combined lengths of the PCI-ROM- and PCI-Data-
+ * headers.
+ *
+ * I suspect that it is more than merely an odd coincidence,
+ * and that the following would be preferable:
+ */
- /* 20 bytes of padding */
- for (i=0; i<20; i++) emit_byte(0x00);
+ LITTLE_ENDIAN_WORD_STORE( pci_hdr->reserved ,
+ (sizeof(rom_header_t) + sizeof(pci_data_t)) ) ;
+ /* already handled padding */
+
/* pointer to start of PCI data structure */
- emit_byte(0x1c); emit_byte(0x00);
+ LITTLE_ENDIAN_WORD_STORE(pci_hdr->data_ptr, sizeof(rom_header_t) );
- /* 2 bytes of zero padding */
- emit_byte(0x00); emit_byte(0x00);
+}
- /* PCI Data structure */
- emit_byte('P'); emit_byte('C'); emit_byte('I'); emit_byte('R');
- /* vendor id */
- emit_byte(vid&0xff); emit_byte(vid>>8);
- /* device id */
- emit_byte(did&0xff); emit_byte(did>>8);
- /* vital product data */
- emit_byte(0x00); emit_byte(0x00);
- /* length of pci data structure */
- emit_byte(0x18); emit_byte(0x00);
- /* PCI data structure revision */
- emit_byte(0x00);
-
- if (little_endian()) {
- /* reg level programming */
- emit_byte(classid & 0xff);
- /* class code */
- emit_byte((classid>>8)&0xff);
- emit_byte((classid>>16)&0xff);
- } else {
- /* class code */
- emit_byte((classid>>8)&0xff);
- emit_byte((classid>>16)&0xff);
- /* reg level programming */
- emit_byte(classid & 0xff);
+/* **************************************************************************
+ *
+ * Function name: emit_pci_data_block
+ * Synopsis: Write the PCI Data Block into the Output Buffer
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global Variables:
+ * opc Output Buffer Position Counter
+ * Data-Stack Items:
+ * Top: Class Code
+ * Next: Device ID
+ * 3rd: Vendor ID
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global Variables:
+ * pci_data_blk_ob_off PCI Data Header Block Position
+ * (Offset) in Output Buffer
+ * Data-Stack, # of Items Popped: 3
+ * FCode Output buffer:
+ * Write the PCI Data Header Block: Fill in the signature,
+ * Vendor ID, Device ID and Class Code, and everything
+ * else whose value we know. (Size and Checksum will
+ * have to wait until we finish the image...)
+ * Printout:
+ * Advisory of Vendor, Device and Class
+ *
+ * Error Detection: (Handled by calling routine)
+ *
+ **************************************************************************** */
+
+static void emit_pci_data_block(void)
+{
+ pci_data_t *pci_data_blk;
+ u32 class_id = dpop();
+ u16 dev_id = dpop();
+ u16 vend_id = dpop();
+
+ pci_data_blk_ob_off = opc;
+ pci_data_blk = (pci_data_t *)(ostart + pci_data_blk_ob_off);
+
+ EMIT_STRUCT(pci_data_t);
+
+ BIG_ENDIAN_LONG_STORE(pci_data_blk->signature , PCI_DATA_HDR );
+
+ LITTLE_ENDIAN_WORD_STORE(pci_data_blk->vendor , vend_id );
+ LITTLE_ENDIAN_WORD_STORE(pci_data_blk->device , dev_id );
+ LITTLE_ENDIAN_TRIPLET_STORE(pci_data_blk->class_code , class_id );
+
+ LITTLE_ENDIAN_WORD_STORE(pci_data_blk->dlen , sizeof(pci_data_t) );
+
+ pci_data_blk->drevision = PCI_DATA_STRUCT_REV ;
+
+ /* code type = open firmware = 1 */
+ pci_data_blk->code_type = 1;
+
+ /* last image flag */
+ pci_data_blk->last_image_flag = pci_is_last_image ? 0x80 : 0 ;
+
+ tokenization_error(INFO ,
+ "PCI header vendor id=0x%04x, "
+ "device id=0x%04x, class=%06x\n",
+ vend_id, dev_id, class_id );
+
+}
+
+/* **************************************************************************
+ *
+ * Function name: emit_pcihdr
+ * Synopsis: Supervise the writing of PCI Header information
+ * into the Output Buffer, when the PCI-HEADER
+ * tokenizer directive has been encountered.
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global Variables:
+ * fcode_start_ob_off Initted if FCode output has begun
+ * noerrors The "Ignore Errors" flag
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global Variables:
+ * FCode Output buffer:
+ *
+ * Error Detection:
+ * An attempt to write a PCI Header after FCode output -- either an
+ * Fcode-start<n> or ordinary FCode -- has begun is an ERROR.
+ * Report it; do nothing further, unless "Ignore Errors" is set.
+ *
+ **************************************************************************** */
+
+void emit_pcihdr(void)
+{
+
+ /* Check for error conditions */
+ if (
+ /* FCODE-START<n> has already been issued */
+ ( fcode_start_ob_off != -1 )
+ /* Other FCode has been written */
+ || fcode_written
+ )
+ {
+ tokenization_error( TKERROR ,
+ "Cannot create PCI header after FCode output has begun.\n");
+ if ( ! noerrors ) return ;
}
- /* size of image - to be filled later */
- emit_byte(0x00); emit_byte(0x00);
- /* revision level */
- emit_byte(0x00); emit_byte(0x00);
- /* code type = open firmware */
- emit_byte(0x01);
- emit_byte(0x80);
- /* 2 bytes of padding */
- emit_byte(0x00); emit_byte(0x00);
+ emit_pci_rom_hdr();
- return 0;
+ emit_pci_data_block();
}
+/* **************************************************************************
+ *
+ * Function name: finish_pcihdr
+ * Synopsis: Fill-in the fields of the PCI Header that could
+ * not be determined until the end of the PCI-block.
+ *
+ *************************************************************************** */
-int finish_pcihdr(void)
+void finish_pcihdr(void)
{
- u8 *tpc;
- u32 imgsize=opc-ostart, imgblocks;
+
+ u32 imagesize ;
+ u32 imageblocks;
int padding;
- if(!pci_hdr)
+ rom_header_t *pci_hdr;
+ pci_data_t *pci_data_blk;
+
+ if( pci_data_blk_ob_off == -1 )
{
- printf("error: trying to fix up unknown pci header\n");
- return -1;
+ tokenization_error( TKERROR,
+ "%s without PCI-HEADER\n", strupr(statbuf) );
+ return ;
}
+ pci_hdr = (rom_header_t *)(ostart + pci_hdr_ob_off);
+ pci_data_blk = (pci_data_t *)(ostart + pci_data_blk_ob_off);
+
/* fix up vpd */
- tpc=opc;
- opc=pci_hdr+36;
- emit_byte(pci_vpd&0xff); emit_byte(pci_vpd>>8);
+ LITTLE_ENDIAN_WORD_STORE(pci_data_blk->vpd, pci_vpd);
- /* fix up image size */
- opc=pci_hdr+44;
- imgblocks=(imgsize+511)>>9; /* size is in 512byte blocks */
- emit_byte(imgblocks&0xff); emit_byte(imgblocks>>8);
+ /* Calculate image size and padding */
+ imagesize = opc - pci_hdr_ob_off; /* Padding includes PCI hdr */
+ imageblocks = (imagesize + 511) >> 9; /* Size in 512-byte blocks */
+ padding = (imageblocks << 9) - imagesize;
+
+ /* fix up image size. */
+ LITTLE_ENDIAN_WORD_STORE(pci_data_blk->ilen, imageblocks);
/* fix up revision */
- emit_byte(pci_revision&0xff); emit_byte(pci_revision>>8);
+ if ( big_end_pci_image_rev )
+ {
+ BIG_ENDIAN_WORD_STORE(pci_data_blk->irevision, pci_image_rev);
+ }else{
+ LITTLE_ENDIAN_WORD_STORE(pci_data_blk->irevision, pci_image_rev);
+ }
/* fix up last image flag */
- opc++;
- emit_byte(pci_is_last_image?0x80:0x00);
- opc=tpc;
+ pci_data_blk->last_image_flag = pci_is_last_image ? 0x80 : 0 ;
/* align to 512bytes */
- padding=((imgsize+511)&0xfffffe00)-imgsize;
+
printf("Adding %d bytes of zero padding to PCI image.\n",padding);
while (padding--)
emit_byte(0);
+ if ( ! pci_is_last_image )
+ {
+ printf("Note: PCI header is not last image.\n");
+ }
+ printf("\n");
- pci_hdr=NULL;
- return 0;
+ pci_hdr_ob_off = -1;
+ pci_data_blk_ob_off = -1;
}
void finish_headers(void)
{
- if (fcode_hdr) finish_fcodehdr();
- if (pci_hdr) finish_pcihdr();
+ if (fcode_hdr_ob_off != -1) finish_fcodehdr();
+ if (pci_hdr_ob_off != -1) finish_pcihdr();
}
Modified: fcode-utils/toke/emit.h
===================================================================
--- fcode-utils/toke/emit.h 2006-08-18 09:45:11 UTC (rev 75)
+++ fcode-utils/toke/emit.h 2006-08-18 12:47:12 UTC (rev 76)
@@ -1,3 +1,6 @@
+#ifndef _TOKE_EMIT_H
+#define _TOKE_EMIT_H
+
/*
* OpenBIOS - free your system!
* ( FCode tokenizer )
@@ -24,21 +27,90 @@
*
*/
-#ifndef _H_EMIT
-#define _H_EMIT
+/* **************************************************************************
+ * Modifications made in 2005 by IBM Corporation
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Modifications Author: David L. Paktor dlpaktor(a)us.ibm.com
+ **************************************************************************** */
+
+#include "types.h"
-int emit_byte(u8 data);
-int emit_fcode(u16 tok);
-int emit_token(const char *name);
-int emit_num32(u32 num);
-int emit_num16(u16 num);
-int emit_offset(s16 offs);
-s16 receive_offset(void);
-int emit_string(u8 *string, unsigned int cnt);
-int emit_fcodehdr(void);
-int finish_fcodehdr(void);
-int emit_pcihdr(u16 vid, u16 did, u32 classid);
-int finish_pcihdr(void);
+/* **************************************************************************
+ * Structure Name: fcode_header_t
+ * Synopsis: FCode Header within the Output Buffer
+ *
+ * Fields:
+ * format, checksum and length All as prescribed in P1275, Sec 5.2.2.5
+ *
+ * Note that the Checksum and Length fields are stated as byte-arrays
+ * rather than as integers. This is intended to guarantee that
+ * their endian-ness will remain independent of the endian-ness
+ * of the host-platform on which this Tokenizer is running.
+ * Note also that, as integers, both are BIG-Endian.
+ *
+ **************************************************************************** */
+
+typedef struct {
+ u8 format;
+ u8 checksum[2]; /* [0] = Hi byte, [1] = Lo */
+ u8 length[4]; /* [0] = Hi, [1] = Hi-mid, [2] = Lo-mid, [3] = Lo */
+} fcode_header_t;
+
+
+/* **************************************************************************
+ * Macro Name: STRING_LEN_MAX
+ * Max number of bytes allowable in an output string
+ *
+ * Arguments: NONE
+ *
+ * This value must remail hard-coded and immutable. It represents the
+ * maximum number allowed in a FORTH counted-string's count-byte
+ * (which is, of course, the maximum number that can be expressed
+ * in an unsigned byte).
+ * It should not be used for anything else (e.g., buffer sizes), and
+ * most especially not for anything that might be changed!
+ *
+ **************************************************************************** */
+
+#define STRING_LEN_MAX 255
+
+
+/* **************************************************************************
+ * Macro Name: GET_BUF_MAX
+ * Size alloted to input-string buffer
+ *
+ * Arguments: NONE
+ *
+ * This is a generous allotment for the buffer into which
+ * input strings are gathered. Overflow calculations are
+ * also based on it. It may be changed safely.
+ * We like to keep it a nice power-of-two to make the memory-
+ * allocation routine run efficiently and happily (Okay, so
+ * that's anthropormism: It's efficient and *we*'re happy.
+ * Better? I thought so... ;-)
+ *
+ **************************************************************************** */
+
+#define GET_BUF_MAX 1024
+
+
+/* ************************************************************************** *
+ *
+ * Function Prototypes / Functions Exported:
+ *
+ **************************************************************************** */
+
+void emit_fcode(u16 tok);
+void user_emit_byte(u8 data);
+
+void emit_offset(s16 offs);
+void emit_string(u8 *string, signed int cnt);
+void emit_fcodehdr(const char *starter_name);
+void finish_fcodehdr(void);
+void emit_pcihdr(void);
+void finish_pcihdr(void);
void finish_headers(void);
+void emit_end0(void);
+void emit_literal(u32 num);
-#endif /* _H_EMIT */
+#endif /* _TOKE_EMIT_H */
Added: fcode-utils/toke/errhandler.c
===================================================================
--- fcode-utils/toke/errhandler.c (rev 0)
+++ fcode-utils/toke/errhandler.c 2006-08-18 12:47:12 UTC (rev 76)
@@ -0,0 +1,956 @@
+/*
+ * OpenBIOS - free your system!
+ * ( FCode tokenizer )
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 2001-2005 Stefan Reinauer, <stepan(a)openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+/* **************************************************************************
+ *
+ * Error-Handler for Tokenizer
+ *
+ * Controls printing of various classes of errors
+ *
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Module Author: David L. Paktor dlpaktor(a)us.ibm.com
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Functions Exported:
+ * init_error_handler Initialize the error-counts,
+ * announce the file names.
+ * tokenization_error Handle an error of the given class,
+ * print the given message in the
+ * standard format.
+ * started_at Supplemental message, giving a back-reference
+ * to the "starting" point of a compound
+ * error, including last-colon identification.
+ * just_started_at Supplemental back-reference to "starting" point
+ * of compound error, but without last-colon
+ * identification.
+ * where_started Supplemental message, giving a more terse back-
+ * -reference to "start" of compound-error.
+ * just_where_started Supplemental message, more terse back-reference,
+ * without last-colon identification.
+ * in_last_colon Supplemental back-reference message,
+ * identifying last Colon-definition.
+ * safe_malloc malloc with built-in failure test.
+ * error_summary Summarize final error-message status
+ * before completing tokenization.
+ *
+ **************************************************************************** */
+
+
+/* **************************************************************************
+ *
+ * We will define a set of bit-valued error-types and a
+ * global bit-mask. Each error-message will be associated
+ * with one of the bit-valued error-types. The bit-mask,
+ * which will be set by a combination of defaults and user
+ * inputs (mainly command-line arguments), will control
+ * whether an error-message of any given type is printed.
+ *
+ * Another bit-mask variable will accumulate the error-
+ * types that occur within any given run; at the end of
+ * the run, it will be examined to determine if the run
+ * failed, i.e., if the output should be suppressed.
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Error-types fall into the following broad categories:
+ * FATAL Cause to immediately stop activity
+ * TKERROR Sufficient to make the run a failure,
+ * but not to stop activity.
+ * WARNING Not necessarily an error, but something
+ * to avoid. E.g., it might rely on
+ * assumptions that are not necessarily
+ * what the user/programmer wants. Or:
+ * It's a deprecated feature, or one
+ * that might be incompatible with
+ * other standard tokenizers.
+ * INFO Nothing is changed in processing, but
+ * an advisory is still in order.
+ * MESSAGE Message generated by the user. (Complete;
+ * new-line will be added by display routine.)
+ * P_MESSAGE Partial Message -- Instigated by user, but
+ * pre-formatted and not complete. New-line
+ * will be added by follow-up routine.
+ *
+ **************************************************************************** */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "types.h"
+#include "toke.h"
+#include "stream.h"
+#include "errhandler.h"
+#include "scanner.h"
+
+/* **************************************************************************
+ *
+ * Global Variables Imported
+ * iname Name of file currently being processed
+ * lineno Current line-number being processed
+ * noerrors "Ignore Errors" flag, set by "-i" switch
+ * opc FCode Output Buffer Position Counter
+ * verbose If true, enable Advisory Messages
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Internal Static Variables
+ * print_msg Whether beginning of a message was printed;
+ * therefore, whether to print the rest.
+ * errs_to_print Error Verbosity Mask. Bits set correspond
+ * to message-types that will be printed
+ * May be altered by Command-Line switches.
+ * err_types_found Accumulated Error-types. Bits
+ * set correspond to error-types
+ * that have occurred.
+ * message_dest Message Dest'n. Usually ERRMSG_DESTINATION
+ * (stdout) except when we need to switch.
+ * err_count Count of Error Messages
+ * warn_count Count of Warning Messages
+ * info_count Count of "Advisory" Messages
+ * user_msg_count Count of User-generated Messages
+ * fatal_err_exit Exit code to be used for "Fatal" error.
+ * This is a special accommodation
+ * for the safe_malloc routine.
+ *
+ **************************************************************************** */
+
+static bool print_msg ;
+static int errs_to_print = ( FATAL | TKERROR | WARNING |
+ MESSAGE | P_MESSAGE | FORCE_MSG ) ;
+static int err_types_found = 0 ;
+static int err_count = 0 ;
+static int warn_count = 0 ;
+static int info_count = 0 ;
+static int user_msg_count = 0 ;
+static int fatal_err_exit = -1 ;
+static FILE *message_dest; /* Would like to init to ERRMSG_DESTINATION
+ * here, but the compiler complains...
+ */
+
+/* **************************************************************************
+ *
+ * Internal Static Constant Structure
+ * err_category Correlate each error-type code with its
+ * Counter-variable and the printable
+ * form of its name.
+ * num_categories Number of entries in the err_category table
+ *
+ **************************************************************************** */
+
+typedef struct {
+ int type_bit ; /* Error-type single-bit code */
+ char *category_name ; /* Printable-name base */
+ char *single ; /* Suffix to print singular of name */
+ char *plural ; /* Suffix to print plural of name */
+ int *counter ; /* Associated Counter-variable */
+ bool new_line ; /* Whether to print new-line at end */
+} err_category ;
+
+static const err_category error_categories[] = {
+ /* FATAL must be the first entry in the table. */
+ /* No plural is needed; only one is allowed.... */
+ { FATAL, "Fatal Error", "", "", &err_count , TRUE },
+
+ { TKERROR, "Error" , "", "s", &err_count , FALSE },
+ { WARNING, "Warning" , "", "s", &warn_count , FALSE },
+ { INFO, "Advisor" , "y", "ies", &info_count , FALSE },
+ { MESSAGE , "Message" , "", "s", &user_msg_count , TRUE },
+ { P_MESSAGE , "Message" , "", "s", &user_msg_count , FALSE }
+};
+
+static const int num_categories =
+ ( sizeof(error_categories) / sizeof(err_category) );
+
+
+#ifdef NEEDS_STRUPR
+
+/* **************************************************************************
+ *
+ * Function name: toup
+ * Synopsis: Support function for strupper
+ * Converts one character
+ *
+ * Inputs:
+ * Parameters:
+ * chr_ptr Pointer to the character
+ *
+ * Outputs:
+ * Returned Value: None
+ * Supplied Pointers:
+ * The character pointed to is changed
+ *
+ * Process Explanation:
+ * Because this fills in a lack in the host system, we cannot
+ * rely on the functions islower or toupper , which are
+ * usually built-in but might be similarly missing.
+ *
+ **************************************************************************** */
+
+static void toup( char *chr_ptr)
+{
+ const unsigned char upcas_diff = ( 'a' - 'A' );
+ if ( ( *chr_ptr >= 'a' ) && ( *chr_ptr <= 'z' ) )
+ {
+ *chr_ptr -= upcas_diff ;
+ }
+}
+
+/* **************************************************************************
+ *
+ * Function name: strupper
+ * Synopsis: Replacement for strupr on systems that don't
+ * seem to have it. A necessary hack.
+ *
+ * Inputs:
+ * Parameters:
+ * strung Pointer to the string to be changed
+ *
+ * Outputs:
+ * Returned Value: Same pointer that was passed in
+ * Supplied Pointers:
+ * The string pointed to will be converted to upper case
+ *
+ * Process Explanation:
+ * Because it fills in a lack in the host system, this routine
+ * does not rely on the functions islower or toupper
+ * which are usually built-in but might be missing.
+ *
+ **************************************************************************** */
+
+char *strupper( char *strung)
+{
+ char *strindx;
+ for (strindx = strung; *strindx != 0; strindx++)
+ {
+ toup( strindx);
+ }
+ return strung;
+}
+
+/* **************************************************************************
+ *
+ * If strupr is missing, it's a good bet that so is strlwr
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Function name: tolow
+ * Synopsis: Support function for strlower
+ * Converts one character
+ *
+ * Inputs:
+ * Parameters:
+ * chr_ptr Pointer to the character
+ *
+ * Outputs:
+ * Returned Value: None
+ * Supplied Pointers:
+ * The character pointed to is changed
+ *
+ * Process Explanation:
+ * Because this fills in a lack in the host system, we cannot
+ * rely on the functions isupper or tolower , which are
+ * usually built-in but might be similarly missing.
+ *
+ **************************************************************************** */
+
+static void tolow( char *chr_ptr)
+{
+ const unsigned char lowcas_diff = ( 'A' - 'a' );
+ if ( ( *chr_ptr >= 'A' ) && ( *chr_ptr <= 'Z' ) )
+ {
+ *chr_ptr -= lowcas_diff ;
+ }
+}
+
+/* **************************************************************************
+ *
+ * Function name: strlower
+ * Synopsis: Replacement for strlwr on systems that don't
+ * seem to have it. A necessary hack.
+ *
+ * Inputs:
+ * Parameters:
+ * strung Pointer to the string to be changed
+ *
+ * Outputs:
+ * Returned Value: Same pointer that was passed in
+ * Supplied Pointers:
+ * The string pointed to will be converted to lower case
+ *
+ * Process Explanation:
+ * Because it fills in a lack in the host system, this routine
+ * does not rely on the functions isupper or tolower
+ * which are usually built-in but might be missing.
+ *
+ **************************************************************************** */
+
+char *strlower( char *strung)
+{
+ char *strindx;
+ for (strindx = strung; *strindx != 0; strindx++)
+ {
+ tolow( strindx);
+ }
+ return strung;
+}
+
+
+#endif /* NEEDS_STRUPR */
+
+/* **************************************************************************
+ *
+ * Function name: init_error_handler
+ * Synopsis: Initialize the error-handler before starting a
+ * new tokenization; both the aspects that will
+ * persist across the entire run and those that
+ * need to be reset, such as error-counts.
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global Variables:
+ * verbose Set by "-v" switch
+ * Macro:
+ * ERRMSG_DESTINATION Error message destination;
+ * (Set by development-time switch)
+ * FFLUSH_STDOUT Flush STDOUT if err-msg-dest is STDERR
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Global Variables:
+ * errs_to_print Add the INFO bit if verbose is set
+ * Local Static Variables:
+ * message_dest Point it at ERRMSG_DESTINATION (stderr)
+ * Reset the following to zero:
+ * err_types_found Accumulated Error-types.
+ * err_count Count of Error Messages
+ * warn_count Count of Warning Messages
+ * info_count Count of "Advisory" Messages
+ * user_msg_count Count of User-generated Messages
+ * Other Exotic Effects:
+ * Flush stdout if Error message destination is not stdout, to
+ * avoid collisions with stderr once Error Messaging begins.
+ *
+ * Extraneous Remarks:
+ * This needs to be done before attempting to read the input file,
+ * so that any Messages that occur there can be properly counted.
+ *
+ **************************************************************************** */
+
+void init_error_handler( void)
+{
+ message_dest = ERRMSG_DESTINATION;
+ if ( verbose ) errs_to_print |= INFO ;
+ err_types_found = 0 ;
+ err_count = 0 ;
+ warn_count = 0 ;
+ info_count = 0 ;
+ user_msg_count = 0 ;
+ FFLUSH_STDOUT
+}
+
+/* **************************************************************************
+ *
+ * Function name: tokenization_error
+ * Synopsis: Handle an error of the given class,
+ * print the given message in the standard format.
+ *
+ * Inputs:
+ * Parameters:
+ * err_type int One of the bit-valued error-types
+ * The remaining parameters are a format string and corresponding
+ * data objects such as would be sent to printf()
+ * Global Variables:
+ * errs_to_print Error Verbosity Mask.
+ * iname Name of file currently being processed
+ * lineno Current line-number being processed
+ * fatal_err_exit Exit code for "Fatal" error, if applicable.
+ * Macro:
+ * ERRMSG_DESTINATION Error message destination;
+ * (Development-time switch)
+ * Note: Whether this routine will or will not supply a new-line
+ * at the end of the printout depends on the category of the
+ * message. The new-line is included for a FATAL or a User-
+ * Generated Message, and excluded for the rest. For those,
+ * the calling routine must be responsible for including a
+ * new-line at the end of the format string or for otherwise
+ * finishing the line, as by calling started_at()
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Local Static Variables:
+ * err_types_found Accumulated Error-types.
+ * print_msg Whether this message was printed;
+ * may be used by started_at()
+ * One of the following Category Counters
+ * will be incremented, as applicable:
+ * err_count
+ * warn_count
+ * info_count
+ * user_msg_count
+ * Printout: Directed to stdout or stderr
+ * (see definition of ERRMSG_DESTINATION)
+ *
+ * Error Detection:
+ * Err_type not in list
+ * Print special message; treat cause as an Error.
+ * Force printout.
+ *
+ * Process Explanation:
+ * Accumulated the Error-type into err_types_found
+ * Identify the Error-Category:
+ * Check the Error-Type against the bit-code.
+ * The Error-type may have more than one bit set,
+ * but if it matches the Category bit-code, it's it.
+ * If it doesn't match any Error-Category bit-code, print
+ * a special message and treat it as an ERROR code.
+ * Check the Error-Type against the Error Verbosity Mask;
+ * If it has a bit set, print the Error-Category, together
+ * with the source-file name and line number, and
+ * the rest of the message as supplied.
+ * The table that translates the Error-type into a printable
+ * Error-Category string also identifies the applicable
+ * Category Counter; increment it.
+ * Of course, there's no return from a FATAL error; it exits.
+ *
+ **************************************************************************** */
+
+void tokenization_error( int err_type, char* msg, ... )
+{
+ int indx ;
+
+ /* Initial settings: treat as an Error. */
+ char *catgy_name = "Error";
+ char *catgy_suffx = "";
+ int *catgy_counter = &err_count;
+ bool print_new_line = FALSE;
+
+ /* Accumulated the Error-type into err_types_found */
+ err_types_found |= err_type;
+
+ /* Identify the Error-Category. */
+ for ( indx = 0 ; indx < num_categories ; indx ++ )
+ {
+ if ( ( error_categories[indx].type_bit & err_type ) != 0 )
+ {
+ catgy_name = error_categories[indx].category_name;
+ catgy_suffx = error_categories[indx].single;
+ catgy_counter = error_categories[indx].counter;
+ print_new_line = error_categories[indx].new_line;
+ break;
+ }
+ }
+
+ /* Special message if err_type not in list; treat as an Error. */
+ if ( catgy_name == NULL )
+ {
+ fprintf(ERRMSG_DESTINATION,
+ "Program error: Unknown Error-Type, 0x%08x. "
+ " Will treat as Error.\n", err_type) ;
+ err_types_found |= TKERROR;
+ print_msg = TRUE ;
+ } else {
+ /* Check the Error-Type against the Error Verbosity Mask */
+ print_msg = BOOLVAL( ( errs_to_print & err_type ) != 0 );
+ }
+
+ if ( print_msg )
+ {
+ va_list argp;
+
+ if ( iname != NULL )
+ {
+ fprintf(ERRMSG_DESTINATION, "%s%s: File %s, Line %d. ",
+ catgy_name, catgy_suffx, iname, lineno);
+ }else{
+ /* Don't print iname or lineno if no file opened. */
+ fprintf(ERRMSG_DESTINATION, "%s%s: ",
+ catgy_name, catgy_suffx);
+ }
+
+ va_start(argp, msg);
+ vfprintf(ERRMSG_DESTINATION, msg, argp);
+ va_end(argp);
+ if ( print_new_line ) fprintf(ERRMSG_DESTINATION, "\n");
+
+ /* Increment the category-counter. */
+ *catgy_counter += 1;
+ }
+ if ( err_type == FATAL )
+ {
+ fprintf(ERRMSG_DESTINATION, "Tokenization terminating.\n");
+ error_summary();
+ exit ( fatal_err_exit );
+ }
+}
+
+/* **************************************************************************
+ *
+ * Function name: print_where_started
+ * Synopsis: Supplemental message, following a tokenization_error,
+ * giving a back-reference to the "start" point of
+ * the compound-error being reported.
+ * This is a retro-fit; it does the heavy lifting for
+ * the routines started_at() , just_started_at() ,
+ * where_started() , just_where_started() and
+ * in_last_colon() .
+ *
+ * Inputs:
+ * Parameters:
+ * show_started Whether to print a phrase about "started"
+ * show_that_st Whether to print "that started" as opposed
+ * to " , which started"
+ * saved_ifile File-name saved for "back-reference"
+ * saved_lineno Line-number saved for "back-reference"
+ * may_show_incolon Whether to allow a call to in_last_colon()
+ * Needed to prevent infinite recursion...
+ * Global Variables:
+ * iname Name of file currently being processed
+ * lineno Current line-number being processed
+ * Local Static Variables:
+ * print_msg Whether the beginning part of the message
+ * was printed by tokenization_error()
+ * message_dest Message Destination. Is ERRMSG_DESTINATION
+ * (stdout) usually, except sometimes...
+ *
+ * Outputs:
+ * Returned Value: None
+ * Printout:
+ * The remainder of a message: the location of a back-reference.
+ * The phrase "that started" is switchable. This routine
+ * will supply the leading space and a new-line; the routines
+ * that call this can be used to finish the line.
+ *
+ * Process Explanation:
+ * This routine is called immediately after tokenization_error()
+ * If tokenization_error() didn't print, neither will we.
+ * The residual state of print_msg will tell us that.
+ * If the preceding message ended with something general about a
+ * "Colon Definition" or "Device-Node" or the like, we want
+ * the message to read: "that started on line ... [in file ...]"
+ * If the end of the preceding message was something more specific,
+ * we just want the message to read: "on line ... [in file ...]"
+ * If the saved input file name doesn't match our current input
+ * file name, we will print it and the saved line-number.
+ * If the file name hasn't changed, we will print only the saved
+ * line-number.
+ * If neither is changed, there's no point in printing any of the
+ * above-mentioned text.
+ * If a Colon-definition is in progress, show its name and the
+ * line on which it started. Protect against infinite loop!
+ * End the line.
+ *
+ * Extraneous Remarks:
+ * This is a retrofit. Earlier, it was just started_at() . Later,
+ * I generated more specific messages, and needed a way to leave
+ * out the "that started". I could, theoretically, have added
+ * the extra parameter to started_at() , but by now there are
+ * so many of calls to it that I'd rather leave them as is, and
+ * just change the name of the routine in the few places that
+ * need the terser form of the message.
+ *
+ **************************************************************************** */
+
+static void print_where_started( bool show_started,
+ bool show_that_st,
+ char * saved_ifile,
+ unsigned int saved_lineno,
+ bool may_show_incolon)
+{
+ if ( print_msg )
+ {
+ bool fil_is_diff;
+ bool lin_is_diff;
+
+ /* File names are case-sensitive */
+ fil_is_diff = BOOLVAL(strcmp(saved_ifile, iname) != 0 );
+ lin_is_diff = BOOLVAL(saved_lineno != lineno );
+ if ( fil_is_diff || lin_is_diff )
+ {
+ if ( show_started )
+ {
+ if ( show_that_st )
+ {
+ fprintf(message_dest, " that");
+ }else{
+ fprintf(message_dest, " , which");
+ }
+ fprintf(message_dest, " started");
+ }
+ fprintf(message_dest, " on line %d", saved_lineno);
+ if ( fil_is_diff )
+ {
+ fprintf(message_dest, " of file %s", saved_ifile);
+ }
+ }
+
+ if ( may_show_incolon )
+ {
+ in_last_colon();
+ }else{
+ fprintf(message_dest, "\n");
+ }
+ }
+}
+
+/* **************************************************************************
+ *
+ * Function name: started_at
+ * Synopsis: Supplemental back-reference message,
+ * with the "that started" phrase,
+ * and with last-colon identification.
+ *
+ * Inputs:
+ * Parameters:
+ * saved_ifile File-name saved for "back-reference"
+ * saved_lineno Line-number saved for "back-reference"
+ *
+ * Outputs:
+ * Returned Value: None
+ * Global Variables:
+ * Printout:
+ * The "...started at..." remainder of a message, giving a back-
+ * -reference to the "start" point supplied in the params,
+ * and the start of the current Colon-definition if one is
+ * in effect.
+ * Will supply a new-line and can be used to finish the line.
+ *
+ **************************************************************************** */
+
+void started_at( char * saved_ifile, unsigned int saved_lineno)
+{
+ print_where_started( TRUE, TRUE, saved_ifile, saved_lineno, TRUE);
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: print_started_at
+ * Synopsis: Same as started_at() except output will be directed
+ * to stdout instead of to ERRMSG_DESTINATION
+ *
+ * Extraneous Remarks:
+ * A retrofit. Can you tell?
+ *
+ **************************************************************************** */
+
+void print_started_at( char * saved_ifile, unsigned int saved_lineno)
+{
+ message_dest = stdout;
+ started_at( saved_ifile, saved_lineno);
+ message_dest = ERRMSG_DESTINATION;
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: just_started_at
+ * Synopsis: Supplemental back-reference message,
+ * with the "that started" phrase,
+ * but without last-colon identification.
+ *
+ * Inputs:
+ * Parameters:
+ * saved_ifile File-name saved for "back-reference"
+ * saved_lineno Line-number saved for "back-reference"
+ *
+ * Outputs:
+ * Returned Value: None
+ * Global Variables:
+ * Printout:
+ * The "...started at..." remainder of a message, giving a back-
+ * -reference to the "start" point supplied in the params,
+ * and no more.
+ * Will supply a new-line and can be used to finish the line.
+ *
+ **************************************************************************** */
+
+void just_started_at( char * saved_ifile, unsigned int saved_lineno)
+{
+ print_where_started( TRUE, TRUE, saved_ifile, saved_lineno, FALSE);
+}
+
+/* **************************************************************************
+ *
+ * Function name: where_started
+ * Synopsis: Supplemental back-reference message,
+ * without the "that started" phrase,
+ * but with last-colon identification.
+ *
+ * Inputs:
+ * Parameters:
+ * saved_ifile File-name saved for "back-reference"
+ * saved_lineno Line-number saved for "back-reference"
+ *
+ * Outputs:
+ * Returned Value: None
+ * Global Variables:
+ * Printout:
+ * The remainder of a message, giving a back-reference to the
+ * "start" point supplied in the parameters, and the start
+ * of the current Colon-definition if one is in effect.
+ * Will supply a new-line and can be used to finish the line.
+ *
+ **************************************************************************** */
+
+void where_started( char * saved_ifile, unsigned int saved_lineno)
+{
+ print_where_started( FALSE, FALSE, saved_ifile, saved_lineno, TRUE);
+}
+
+/* **************************************************************************
+ *
+ * Function name: just_where_started
+ * Synopsis: Supplemental back-reference message,
+ * without the "that started" phrase,
+ * and without last-colon identification.
+ *
+ * Inputs:
+ * Parameters:
+ * saved_ifile File-name saved for "back-reference"
+ * saved_lineno Line-number saved for "back-reference"
+ *
+ * Outputs:
+ * Returned Value: None
+ * Global Variables:
+ * Printout:
+ * The remainder of a message, giving a back-reference to the
+ * "start" point supplied in the parameters, and no more.
+ * Will supply a new-line and can be used to finish the line.
+ *
+ **************************************************************************** */
+
+void just_where_started( char * saved_ifile, unsigned int saved_lineno)
+{
+ print_where_started( FALSE, FALSE, saved_ifile, saved_lineno, FALSE);
+}
+
+/* **************************************************************************
+ *
+ * Function name: in_last_colon
+ * Synopsis: Supplemental back-reference message, identifying
+ * last Colon-definition if one is in effect.
+ * Can be used to finish the line in either case.
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global Variables:
+ * incolon TRUE if Colon-definition is in progress
+ * last_colon_defname Name of last colon-definition
+ * last_colon_filename File where last colon-def'n made
+ * last_colon_lineno Line number of last colon-def'n
+ * Local Static Variables:
+ * print_msg Whether the beginning part of the message
+ * was printed by tokenization_error()
+ * message_dest Message Destination. Is ERRMSG_DESTINATION
+ * (stdout) usually, except sometimes...
+ *
+ * Outputs:
+ * Returned Value: NONE
+ * Printout:
+ * Remainder of a message:
+ * "in definition of ... , which started ..."
+ *
+ * Process Explanation:
+ * Because this routine does some of its own printing, it needs
+ * to check the residual state of print_msg first.
+ * The calling routine does not need to test incolon ; it can
+ * call this to end the line in either case.
+ *
+ **************************************************************************** */
+
+void in_last_colon( void )
+{
+ if ( print_msg )
+ {
+ if ( incolon )
+ {
+ fprintf( message_dest, " in definition of %s ",
+ strupr( last_colon_defname) );
+ print_where_started( TRUE, FALSE,
+ last_colon_filename, last_colon_lineno, FALSE);
+ }else{
+ fprintf(message_dest, "\n");
+ }
+ }
+}
+
+
+/* **************************************************************************
+ *
+ * Function name: safe_malloc
+ * Synopsis: malloc with built-in failure test.
+ *
+ * Inputs:
+ * Parameters:
+ * size size_t Size of memory-chunk to allocate
+ * phrase char * Phrase to print after "... while "
+ * in case of failure.
+ *
+ * Outputs:
+ * Returned Value: Pointer to allocated memory
+ * Global Variables:
+ * fatal_err_exit On memory allocation failure, change
+ * to a special system-defined value
+ *
+ * Error Detection:
+ * On memory allocation failure, declare a FATAL error. Set up
+ * for a special system-defined EXIT value that indicates
+ * insufficient memory.
+ *
+ * Process Explanation:
+ * It is the responsibility of the calling routine to be sure
+ * the "phrase" is unique within the program. It is intended
+ * as a debugging aid, to help localize the point of failure.
+ *
+ **************************************************************************** */
+
+_PTR safe_malloc( size_t size, char *phrase)
+{
+ _PTR retval ;
+ retval = malloc (size);
+ if ( !retval )
+ {
+ fatal_err_exit = -ENOMEM ;
+ tokenization_error( FATAL, "Out of memory while %s.", phrase);
+ }
+ return ( retval );
+}
+
+/* **************************************************************************
+ *
+ * Function name: error_summary
+ * Synopsis: Summarize final error-message status
+ * before completing tokenization.
+ * Indicate if OK to produce output.
+ *
+ * Inputs:
+ * Parameters: NONE
+ * Global Variables:
+ * noerrors "Ignore Errors" flag, set by "-i" switch
+ * err_types_found Accumulated Error-types.
+ * error_categories Table of Error-types, Message-Counters
+ * and their printable names.
+ * opc FCode Output Buffer Position Counter
+ * (zero means there was no output).
+ *
+ * Outputs:
+ * Returned Value: True = OK to produce output (But caller
+ * must still verify non-zero opc)
+ * Printout:
+ * Various messages.
+ *
+ * Process Explanation:
+ * The first entry in the error_categories table is FATAL
+ * We won't need to print a tally of that...
+ *
+ **************************************************************************** */
+
+bool error_summary( void )
+{
+ /* Bit-mask of error-types that require suppressing output */
+ static const int suppress_mask = ( FATAL | TKERROR );
+ bool retval = TRUE;
+ bool suppressing = FALSE;
+
+ /* There's no escaping a FATAL error */
+ if ( ( err_types_found & FATAL ) != 0 )
+ {
+ /* FATAL error. Don't even bother with the tally. */
+ suppressing = TRUE;
+ } else {
+
+ if ( opc == 0 )
+ {
+ printf ( "Nothing Tokenized");
+ }else{
+ printf ( "Tokenization Completed");
+ }
+
+ if ( err_types_found != 0 )
+ {
+ int indx;
+ bool tally_started = FALSE ;
+ printf (". ");
+ /*
+ * Print a tally of the error-types;
+ * handle plurals and punctuation appropriately.
+ */
+ /* Start at indx = 1 to skip examining FATALs */
+ for ( indx = 1; indx < num_categories ; indx ++ )
+ {
+ if ( *(error_categories[indx].counter) > 0 )
+ {
+ printf ("%s %d %s%s",
+ tally_started ? "," : "" ,
+ *(error_categories[indx].counter),
+ error_categories[indx].category_name,
+ *(error_categories[indx].counter) > 1 ?
+ error_categories[indx].plural :
+ error_categories[indx].single );
+ /* Zero out the counter, to prevent displaying the
+ * number of Messages twice, since it's shared
+ * by the "Messages" and "P_Messages" categories.
+ */
+ *(error_categories[indx].counter) = 0;
+ tally_started = TRUE;
+ }
+ }
+ }
+ printf (".\n");
+
+ if ( ( err_types_found & suppress_mask ) != 0 )
+ { /* Errors found. Not OK to produce output */
+ /* Unless "Ignore Errors" flag set... */
+ if ( INVERSE(noerrors) )
+ {
+ suppressing = TRUE;
+ }else{
+ if ( opc > 0 )
+ {
+ printf ("Error-detection over-ridden; "
+ "producing binary output.\n");
+ }
+ }
+ }
+ }
+ if ( suppressing )
+ {
+ retval = FALSE ;
+ printf ("Suppressing binary output.\n");
+ }
+ return ( retval );
+}
+
Added: fcode-utils/toke/errhandler.h
===================================================================
--- fcode-utils/toke/errhandler.h (rev 0)
+++ fcode-utils/toke/errhandler.h 2006-08-18 12:47:12 UTC (rev 76)
@@ -0,0 +1,119 @@
+#ifndef _TOKE_ERRHANDLER_H
+#define _TOKE_ERRHANDLER_H
+
+/*
+ * OpenBIOS - free your system!
+ * ( FCode tokenizer )
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 2001-2005 Stefan Reinauer, <stepan(a)openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+/* **************************************************************************
+ *
+ * Function Prototypes for Tokenizer Error-Handler
+ *
+ * Defines symbols for the various classes of errors
+ * for the Error-Handler and for all its users
+ *
+ *
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Module Author: David L. Paktor dlpaktor(a)us.ibm.com
+ *
+ **************************************************************************** */
+
+#include "types.h"
+
+#define FATAL 0x80000000
+#define TKERROR 0x04000000
+#define WARNING 0x00200000
+#define INFO 0x00010000
+#define MESSAGE 0x00000800
+#define P_MESSAGE 0x00000040
+#define FORCE_MSG 0x00000001
+
+void init_error_handler( void);
+void tokenization_error( int err_type, char* msg, ... );
+void started_at( char * saved_ifile, unsigned int saved_lineno);
+void print_started_at( char * saved_ifile, unsigned int saved_lineno);
+void just_started_at( char * saved_ifile, unsigned int saved_lineno);
+void where_started( char * saved_ifile, unsigned int saved_lineno);
+void just_where_started( char * saved_ifile, unsigned int saved_lineno);
+void in_last_colon( void );
+_PTR safe_malloc( size_t size, char *phrase);
+bool error_summary( void ); /* Return TRUE if OK to produce output. */
+
+
+/* **************************************************************************
+ *
+ * Macros:
+ * ERRMSG_DESTINATION During development, I used this to switch
+ * error message destination between STDOUT and STDERR, until I
+ * settled on which is preferable. Recently, I have proven to
+ * my satisfaction that STDERR is preferable: error-messages
+ * produced by a sub-shell will be correctly synchronized with
+ * the error-messages we produce. When I tested using STDOUT
+ * for error-messages, that error-case looked garbled.
+ * FFLUSH_STDOUT fflush( stdout) if error message destination
+ * is STDERR, No-op if it's STDOUT. A few of these, judiciously
+ * placed, kept our own regular and error messages nicely in sync.
+ *
+ **************************************************************************** */
+
+#define ERRMSG_DESTINATION stderr
+#define FFLUSH_STDOUT fflush( stdout);
+
+/* We're no longer switching the above.
+ * The below is left here to show what had been done formerly.
+ */
+#if -1 /* Switchable error-message destination */
+#else /* Switchable error-message destination */
+#define ERRMSG_DESTINATION stdout
+#define FFLUSH_STDOUT /* Don't need to do anything here */
+#endif /* Switchable error-message destination */
+
+/* Some systems don't seem to have strupr */
+#ifdef SYS_IS_GNU_Linux
+#define NEEDS_STRUPR
+#endif /* SYS_IS_GNU_Linux */
+#ifdef SYS_IS_AIX
+#define NEEDS_STRUPR
+#endif /* SYS_IS_AIX */
+/* ??? Should this instead be tuned to Proc'r is PPC ??? Why? */
+
+#ifdef NEEDS_STRUPR
+
+/* **************************************************************************
+ *
+ * A necessary hack for systems that don't seem
+ * to have strupr and strlwr
+ * Let's avoid a naming conflict, just in case...
+ *
+ **************************************************************************** */
+
+extern char *strupper( char *strung);
+#define strupr strupper
+
+extern char *strlower( char *strung);
+#define strlwr strlower
+
+
+#endif /* NEEDS_STRUPR */
+
+#endif /* _TOKE_ERRHANDLER_H */
Added: fcode-utils/toke/flowcontrol.c
===================================================================
--- fcode-utils/toke/flowcontrol.c (rev 0)
+++ fcode-utils/toke/flowcontrol.c 2006-08-18 12:47:12 UTC (rev 76)
@@ -0,0 +1,2080 @@
+/*
+ * OpenBIOS - free your system!
+ * ( FCode tokenizer )
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 2001-2005 Stefan Reinauer, <stepan(a)openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+/* **************************************************************************
+ *
+ * Support Functions for tokenizing FORTH Flow-Control structures.
+ *
+ * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
+ * Module Author: David L. Paktor dlpaktor(a)us.ibm.com
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Functions Exported:
+ * These first two do their work after the calling routine
+ * has written the token for the required variant:
+ *
+ * mark_do Mark branches for "do" variants
+ * resolve_loop Resolve "loop" variants' branches
+ *
+ * The remaining routines' descriptions are all similar:
+ * Write the token(s), handle the outputs, mark
+ * or resolve the branches, and verify correct
+ * control-structure matching, for tokenizing
+ * the ........................ statement in FORTH
+ * emit_if IF
+ * emit_else ELSE
+ * emit_then THEN
+ * emit_begin BEGIN
+ * emit_again AGAIN
+ * emit_until UNTIL
+ * emit_while WHILE
+ * emit_repeat REPEAT
+ * emit_case CASE
+ * emit_of OF
+ * emit_endof ENDOF
+ * emit_endcase ENDCASE
+ *
+ * Three additional routines deal with matters of overall balance
+ * of the Control-Structures, and identify the start of any that
+ * were not balanced. The first just displays Messages:
+ *
+ * announce_control_structs
+ *
+ * The other two clear and re-balance them:
+ *
+ * clear_control_structs_to_limit
+ * clear_control_structs
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Still to be done:
+ * Correct analysis of Return-Stack usage around Flow-Control
+ * constructs, including within Do-Loops or before Loop
+ * Elements like I and J or UNLOOP or LEAVE.
+ * Similarly, Return-Stack usage around IF ... ELSE ... THEN
+ * statements needs analysis. For instance, the following:
+ *
+ * blablabla >R yadayada IF R> gubble ELSE flubble R> THEN
+ *
+ * is, in fact, correct, while something like:
+ *
+ * blablabla >R yadayada IF R> gubble THEN
+ *
+ * is an error.
+ *
+ * Implementing an analysis that would be sufficiently accurate
+ * to justify reporting an ERROR with certainty (rather than
+ * a mere WARNING speculatively) would probably require full
+ * coordination with management of Flow-Control constructs,
+ * and so is noted here.
+ *
+ **************************************************************************** */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "types.h"
+#include "toke.h"
+#include "emit.h"
+#include "vocabfuncts.h"
+#include "scanner.h"
+#include "stack.h"
+#include "errhandler.h"
+#include "flowcontrol.h"
+#include "stream.h"
+
+/* **************************************************************************
+ *
+ * Global Variables Imported
+ * opc FCode Output Buffer Position Counter
+ * noerrors "Ignore Errors" flag, set by "-i" switch
+ * do_loop_depth How deep we are inside DO ... LOOP variants
+ * incolon State of tokenization; TRUE if inside COLON
+ * statbuf The word just read from the input stream
+ * iname Name of input file currently being processed
+ * lineno Current line-number being processed
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Global Variables Exported
+ * control_stack_depth Number of items on "Control-Stack"
+ *
+ **************************************************************************** */
+
+int control_stack_depth = 0;
+
+
+/* **************************************************************************
+ *
+ * Internal Static Functions:
+ * push_cstag Push an item onto the Control-Stack
+ * pop_cstag Pop one item from the Control-Stack
+ * control_stack_size_test Test C-S depth; report if error
+ * control_structure_mismatch Print error-message
+ * offset_too_large Print error-message
+ * matchup_control_structure Error-check Control-Stack
+ * matchup_two_control_structures Error-check two Control-Stack entries
+ * emit_fc_offset Error-check and output FCode-Offset
+ * control_structure_swap Swap control-struct branch-markers
+ * mark_backward_target Mark target of backward-branch
+ * resolve_backward Resolve backward-target for branch
+ * mark_forward_branch Mark forward-branch
+ * resolve_forward Resolve forward-branch at target
+ *
+ **************************************************************************** */
+
+/* **************************************************************************
+ *
+ * Internal Named Constants
+ * Note: These control-structure identifier tags -- a.k.a. cstags --
+ * are used to identify the matching components of particular
+ * control-structures. They are passed as parameters, and either
+ * "Pushed" onto the "Control-Stack", or compared with what is on
+ * "Top" of the "Control-Stack", as an error-check.
+ *
+ * name used by forth words:
+ * BEGIN_CSTAG BEGIN AGAIN UNTIL REPEAT
+ * IF_CSTAG IF ELSE THEN
+ * WHILE_CSTAG WHILE REPEAT THEN
+ * DO_CSTAG DO ?DO LOOP +LOOP
+ * CASE_CSTAG CASE OF ENDCASE
+ * OF_CSTAG OF ENDOF
+ * ENDOF_CSTAG ENDOF ENDCASE
+ *
+ * The numbers assigned are arbitrary; they were selected for a
+ * high unlikelihood of being encountered in normal usage,
+ * and constructed with a hint of mnemonic value in mind.
+ *
+ **************************************************************************** */
+ /* Mnemonic: */
+#define BEGIN_CSTAG 0xC57be916 /* CST BEGIN */
+#define IF_CSTAG 0xC57A901f /* CSTAG (0) IF */
+#define WHILE_CSTAG 0xC573412e /* CST WHILE */
+#define DO_CSTAG 0xC57A90d0 /* CSTAG (0) DO */
+#define CASE_CSTAG 0xC57Aca5e /* CSTA CASE */
+#define OF_CSTAG 0xC57A90f0 /* CSTAG OF (0) */
+#define ENDOF_CSTAG 0xC57e6d0f /* CST ENDOF */
+
+
+/* **************************************************************************
+ *
+ * Control-Structure identification, matching, completion and error
+ * messaging will be supported by a data structure, which we
+ * will call a CSTAG-Group
+ *
+ * It consists o