First draft of the B module code; a module name can now be specified as a
authorDavid Given <dg@cowlark.com>
Thu, 29 Dec 2016 17:10:21 +0000 (17:10 +0000)
committerDavid Given <dg@cowlark.com>
Thu, 29 Dec 2016 17:10:21 +0000 (17:10 +0000)
compiler flag, which is used to set the name of the patch table. The compiler
now understands C preprocessor line directives. Extend the standard library
somewhat.

lang/b/compiler/b.h
lang/b/compiler/b0.c
lang/b/compiler/build.lua
lang/b/lib/b.h
lang/b/lib/main.c

index 61548b6..acfb4a9 100644 (file)
@@ -4,6 +4,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <em.h>
+#include "astring.h"
 
 #define        NCPS    8       /* chars per symbol */
 #define        HSHSIZ  400     /* hash table size */
@@ -40,6 +41,7 @@ struct        swtab {
 };
 
 extern int wordsize;
+extern const char* modulename;
 int paramsize;
 struct hshtab hshtab[HSHSIZ];
 int    hshused;
@@ -89,6 +91,7 @@ char* manglename(char* name, char prefix);
 #define        RPARN   7
 #define        COLON   8
 #define        COMMA   9
+#define HASH   10
 
 #define        MCALL   15
 #define        CALL    16
index d0ea698..3d87774 100644 (file)
@@ -14,6 +14,7 @@ int   contlab = -1;
 int    brklab = -1;
 
 int wordsize = 4;
+const char* modulename = "b_module_main";
 int bsymb_part;
 int code_part;
 int string_part;
@@ -38,7 +39,7 @@ main(int argc, char *argv[])
 {
 
        for (;;) {
-               int opt = getopt(argc, argv, "-w:i:o:");
+               int opt = getopt(argc, argv, "-w:B:i:o:");
                if (opt == -1)
                        break;
 
@@ -47,6 +48,10 @@ main(int argc, char *argv[])
                                wordsize = atoi(optarg);
                                break;
 
+                       case 'B':
+                               modulename = aprintf("b_module_%s", optarg);
+                               break;
+
                        case 'i':
                                if (freopen(optarg, "r", stdin) == NULL) {
                                        error("Can't find %s", optarg);
@@ -62,7 +67,7 @@ main(int argc, char *argv[])
                                break;
 
                        derfault:
-                               error("Usage: em_b [-w wordsize] [-i inputfile] [-o outputfile]");
+                               error("Usage: em_b [-w wordsize] [-B modulename] [-i inputfile] [-o outputfile]");
                                exit(1);
                }
        }
@@ -97,8 +102,8 @@ main(int argc, char *argv[])
        if (string_part)
                C_insertpart(string_part);
 
-       C_exa_dnam("bsymb_patch_table");
-       C_df_dnam("bsymb_patch_table");
+       C_exa_dnam((char*) modulename);
+       C_df_dnam((char*) modulename);
        if (bsymb_part)
                C_insertpart(bsymb_part);
        C_rom_cst(0);
@@ -340,11 +345,30 @@ loop:
 
        case NEWLN:
                line++;
-
+               /* fall through */
        case SPACE:
                c = getchar();
                goto loop;
 
+       case HASH:
+               /* # is invalid in B; but we handle it out of convenience so that we can read
+                * in input files that have been run through the C preprocessor. Ideally we
+                * should only recognise it when it's the first character in a line, but as
+                * it's not used anywhere else we can get away with recognising it anywhere.
+                */
+
+               while ((c = getchar()) == ' ')
+                       ;
+
+               peekc = c;
+               getnum();
+               line = cval;
+
+               while ((c = getchar()) != '\n')
+                       ;
+
+               goto loop;
+
        case PLUS:
                return subseq(c,PLUS,INCBEF);
 
@@ -1242,7 +1266,7 @@ char ctab[128] = {
        LETTER, SPACE,  NEWLN,  SPACE,  SPACE,  UNKN,   UNKN,   UNKN,
        UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,
        UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,
-       SPACE,  EXCLA,  DQUOTE, UNKN,   UNKN,   MOD,    AND,    SQUOTE,
+       SPACE,  EXCLA,  DQUOTE, HASH,   UNKN,   MOD,    AND,    SQUOTE,
        LPARN,  RPARN,  TIMES,  PLUS,   COMMA,  MINUS,  UNKN,   DIVIDE,
        DIGIT,  DIGIT,  DIGIT,  DIGIT,  DIGIT,  DIGIT,  DIGIT,  DIGIT,
        DIGIT,  DIGIT,  COLON,  SEMI,   LESS,   ASSIGN, GREAT,  QUEST,
index 82095a6..2756428 100644 (file)
@@ -8,6 +8,7 @@ cprogram {
                "./*.h",
                "modules+headers",
                "modules/src/alloc+lib",
+               "modules/src/data+lib",
                "modules/src/em_code+lib_k",
                "modules/src/em_data+lib",
                "modules/src/em_mes+lib",
index 123eabc..571c179 100644 (file)
@@ -14,6 +14,9 @@
 #error Unsupported EM_PSIZE
 #endif
 
+extern FILE* input_unit;
 extern FILE* output_unit;
 
+#define END 4
+
 #endif
index 9b868ba..404e1fd 100644 (file)
@@ -1,8 +1,12 @@
 #include "b.h"
+#include <stdarg.h>
+#include <string.h>
+#include <limits.h>
 
-extern uintptr_t* bsymb_patch_table[];
+extern uintptr_t* b_module_main[];
 extern intptr_t i_main(intptr_t argc, const char* argv[]);
 
+FILE* input_unit;
 FILE* output_unit;
 
 static intptr_t i_char(intptr_t s, intptr_t n)
@@ -19,7 +23,7 @@ static void i_lchar(intptr_t s, intptr_t n, intptr_t c)
 
 static intptr_t i_getchar(void)
 {
-    return fgetc(output_unit);
+    return fgetc(input_unit);
 }
 
 static intptr_t i_putchar(intptr_t c)
@@ -28,17 +32,139 @@ static intptr_t i_putchar(intptr_t c)
     return c;
 }
 
+static intptr_t i_putstr(intptr_t s)
+{
+       char* p = (char*)(s<<SHIFT);
+       char c;
+
+       while ((c = *p++) != END)
+               fputc(c, output_unit);
+
+       return s;
+}
+
+static intptr_t i_getstr(intptr_t s)
+{
+       char* p = (char*)(s<<SHIFT);
+
+       for (;;)
+       {
+               int c = fgetc(input_unit);
+               if ((c == -1) || (c == '\n'))
+                       break;
+               *p++ = c;
+       }
+
+       *p++ = END;
+       return s;
+}
+       
+static void i_flush(void)
+{
+       fflush(output_unit);
+}
+
+static int tochar(int n)
+{
+       if (n <= 9)
+               return n + '0';
+       return n - 10 + 'a';
+}
+
+static void putnum(intptr_t value, int base)
+{
+       int i;
+       char s[32];
+
+       if (value < 0)
+       {
+               fputc('-', output_unit);
+               value = -value;
+       }
+
+       i = 0;
+       do
+               s[i++] = tochar(value % base);
+       while ((value /= base) > 0);
+
+       do
+               fputc(s[--i], output_unit);
+       while (i > 0);
+}
+
+static void i_printf(intptr_t s, ...)
+{
+       char* p = (char*)(s<<SHIFT);
+       char c;
+
+       va_list ap;
+       va_start(ap, s);
+
+       while ((c = *p++) != END)
+       {
+               switch (c)
+               {
+                       case '%':
+                       {
+                               intptr_t ss = va_arg(ap, intptr_t);
+
+                               switch ((c = *p++))
+                               {
+                                       case 's':
+                                               i_putstr(ss);
+                                               break;
+
+                                       case 'd':
+                                               putnum(ss, 10);
+                                               break;
+
+                                       case 'o':
+                                               putnum(ss, 8);
+                                               break;
+
+                                       case 'x':
+                                               putnum(ss, 16);
+                                               break;
+
+                                       case 'c':
+                                               fputc(ss, output_unit);
+                                               break;
+
+                                       default:
+                                               fputc('?', output_unit);
+                                               break;
+                               }
+                               break;
+                       }
+                               
+                       default:
+                               fputc(c, output_unit);
+                               break;
+               }
+       }
+
+       va_end(ap);
+}
+
 uintptr_t b_char = (uintptr_t)i_char;
 uintptr_t b_lchar = (uintptr_t)i_lchar;
 uintptr_t b_getchar = (uintptr_t)i_getchar;
 uintptr_t b_putchar = (uintptr_t)i_putchar;
+uintptr_t b_putstr = (uintptr_t)i_putstr;
+uintptr_t b_getstr = (uintptr_t)i_getstr;
+uintptr_t b_flush = (uintptr_t)i_flush;
+uintptr_t b_printf = (uintptr_t)i_printf;
 
-static uintptr_t* lib_patch_table[] =
+static uintptr_t* b_module_stdlib[] =
 {
     &b_char,
     &b_lchar,
     &b_getchar,
     &b_putchar,
+       &b_putstr,
+       &b_getstr,
+       &b_flush,
+       &b_printf,
     0
 };
 
@@ -53,8 +179,9 @@ static void patch_addresses(uintptr_t** p)
 
 int main(int argc, const char* argv[])
 {
-    patch_addresses(bsymb_patch_table);
-    patch_addresses(lib_patch_table);
+    patch_addresses(b_module_main);
+    patch_addresses(b_module_stdlib);
+    input_unit = stdin;
     output_unit = stdout;
     return i_main(argc, NULL);
-}
\ No newline at end of file
+}