[OpenBIOS] Found out why replacing '\r' with '\n' works

Programmingkid programmingkidx at gmail.com
Mon Apr 18 02:45:31 CEST 2016


On Apr 17, 2016, at 11:05 AM, Mark Cave-Ayland wrote:

> On 17/04/16 15:50, Programmingkid wrote:
> 
>> Good news, I found out why replacing '\r' with '\n' works to boot Mac OS 9. It is because there are several words that require that character to be at the end of the line. 
>> 
>> http://www.complang.tuwien.ac.at/forth/1275.ps
>> This is the specifications to Open Firmware. Just do a search for EOL (End of Line a.k.a '\n'). You will see that several words need it in order to work. 
>> 
>> They will look like this:
>> 
>> dev ( "device-specifier<eol>" -- )	
>> 
>> The <eol> text is what specifies that '\n' should be at the end of the line.
> 
> Really? Interesting. Can you provide a self-contained test case that
> demonstrates that it is in fact the line ending that causes this
> independent of the r-stack manipulation? Bear in mind that OpenBIOS may
> deviate from the specification in its behaviour here.

I implemented another stack that two new words use in place of >r and r> when running code in the bootscript. I see this message with and without the '\r' to '\n' patch:

>> Dictionary space overflow: dicthead=000c3fe4 dictlimit=00080000
this image is not for this platform

This means the implementing another stack did not fix the problem. It appears to make it worse. 

Here is the patch:

Index: include/libc/string.h
===================================================================
--- include/libc/string.h	(revision 1391)
+++ include/libc/string.h	(working copy)
@@ -47,7 +47,7 @@
 extern char	*strdup( const char *str );
 extern int	strcasecmp( const char *cs, const char *ct );
 extern int	strncasecmp( const char *cs, const char *ct, size_t count );
-
+extern char *strstr(char *buffer, const char *search_string);
 extern  char 	*strncpy_nopad( char *dest, const char *src, size_t n );
 
 #define _U      0x01    /* upper */
Index: kernel/bootstrap.c
===================================================================
--- kernel/bootstrap.c	(revision 1391)
+++ kernel/bootstrap.c	(working copy)
@@ -89,7 +89,7 @@
 	"here", "here!", "dobranch", "do?branch", "unaligned-w@",
 	"unaligned-w!", "unaligned-l@", "unaligned-l!", "ioc@", "iow@",
 	"iol@", "ioc!", "iow!", "iol!", "i", "j", "call", "sys-debug",
-	"$include", "$encode-file", "(debug", "(debug-off)"
+	"$include", "$encode-file", "(debug", "(debug-off)", "sub_>r", "sub_r>"
 };
 
 /*
Index: kernel/forth.c
===================================================================
--- kernel/forth.c	(revision 1391)
+++ kernel/forth.c	(working copy)
@@ -1848,6 +1848,37 @@
 	PUSH(rstack[rstackcnt - 2]);
 }
 
+/* The substitute return stack */
+#define MAX_SUB_RSTACK_SIZE 100
+static int sub_return_stack[MAX_SUB_RSTACK_SIZE];
+static int top = 0;
+
+/*  
+ *   sub_>r ( i -- )  (Substitute R: -- i )
+ */
+
+static void sub_gt_r(void)
+{
+    if (top >= MAX_SUB_RSTACK_SIZE) {
+        printf_console("Stack overflow\n");
+        return;
+    }
+    sub_return_stack[top++] = POP();
+}
+
+/*
+ *     sub_r> ( -- i )  (Substitute R: i -- )
+ */
+
+static void sub_r_gt(void)
+{
+    if (top < 0 ) {
+        printf_console("Stack underflow\n");
+        return;
+    }
+    PUSH(sub_return_stack[top--]);
+}
+
 /* words[] is a function array of all native code functions used by
  * the dictionary, i.e. CFAs and primitives.
  * Any change here needs a matching change in the primitive word's
@@ -1963,4 +1994,6 @@
     do_encode_file,         /* $encode-file */
     do_debug_xt,            /* (debug  */
     do_debug_off,           /* (debug-off) */
+    sub_gt_r,               /* sub_>r  */
+    sub_r_gt                /* sub_r>  */
 };
Index: libc/string.c
===================================================================
--- libc/string.c	(revision 1391)
+++ libc/string.c	(working copy)
@@ -385,3 +385,30 @@
 	return __res;
 }
 
+// Search for a string within another string
+char *strstr(char *buffer, const char *search_string)
+{
+    if (!*search_string || (strlen(search_string) == 0)) {
+        return buffer;
+    }
+ 
+    int match_found, index, index2;
+    for (index = 0; index < strlen(buffer); index++) {
+        if (buffer[index] == search_string[0]) {
+            match_found = 1;
+            // see if we have a match
+            for (index2 = 0; index2 < strlen(search_string); index2++) {
+                if (buffer[index + index2] != search_string[index2]) {
+                    match_found = 0; // match not found
+                    break;
+                }
+            }
+            if(match_found == 1) {
+                return &buffer[index];
+            }
+        }
+    }
+    
+    // Could not find search_string in buffer
+    return NULL;
+}
Index: libopenbios/bootinfo_load.c
===================================================================
--- libopenbios/bootinfo_load.c	(revision 1391)
+++ libopenbios/bootinfo_load.c	(working copy)
@@ -19,6 +19,7 @@
 #include "libopenbios/bootinfo_load.h"
 #include "libopenbios/ofmem.h"
 #include "libc/vsprintf.h"
+#include "libc/string.h"
 
 //#define DEBUG_BOOTINFO
 
@@ -116,6 +117,60 @@
 	return LOADER_NOT_SUPPORT;
 }
 
+static void erase_memory(char *memory, int size)
+{
+    int i;
+    for(i = 0; i < size; i++) {
+        memory[i] = ' ';
+    }
+}
+
+// Replace all occurrences of orig_str in buffer with replace_str
+static void replace_string(char *buffer, const char *orig_str, const char *replace_str)
+{
+    char *ptr;
+    int index, new_buf_index = 0;
+    const int max_size = 5000;
+    char *new_buffer = malloc(max_size * sizeof(char));
+    erase_memory(new_buffer, max_size);
+
+    for (index = 0; index < strlen(buffer); index++) {
+        if (buffer[index] == orig_str[0]) {
+            ptr = strstr(buffer + index, orig_str);
+
+            // if we encountered an orig_str in the buffer
+            if (index == (ptr - buffer)) {
+                sprintf(new_buffer + new_buf_index, "%s ", replace_str);
+                new_buf_index += strlen(replace_str) + 1;
+                index += strlen(orig_str);
+                continue;
+            }
+        }
+        new_buffer[new_buf_index++] = buffer[index];
+    }
+    
+    // Clear the origial buffer
+    erase_memory(buffer, max_size);
+
+    // copy new_buffer into buffer
+    for (index = 0; index < strlen(new_buffer); index++) {
+        buffer[index] = new_buffer[index];
+    }
+    buffer[index+1] = '\0';
+}
+
+/* Replace >r and r> with sub_>r and sub_r> */
+static void replace_return_stack_words(char *bootscript)
+{
+    const char *find_str1 = ">r";
+    const char *replace_str1 = "sub_>r";
+    const char *find_str2 = "r>";
+    const char *replace_str2 = "sub_r>";
+    
+    replace_string(bootscript, find_str1, replace_str1);
+    replace_string(bootscript, find_str2, replace_str2);
+}
+
 /*
   Parse SGML structure like:
   <chrp-boot>
@@ -190,8 +245,11 @@
 	while (current < size) {
 
 		c = base[current++];
+        
+        if(c == '\r')
+            c = '\n';
 
-		if (c == '<') {
+        if (c == '<') {
 			script = 0;
 			tag = 1;
 			taglen = 0;
@@ -262,6 +320,7 @@
 	/* If the payload is bootinfo then we execute it immediately */
 	if (scriptvalid) {
 		DPRINTF("bootscript: %s\n", bootscript);
+        replace_return_stack_words(bootscript);
 		feval(bootscript);
 	}
 	else





More information about the OpenBIOS mailing list