Added ability to define multiple functions (without parameters) and master
authorJason Self <j@jxself.org>
Sun, 23 Aug 2020 15:43:45 +0000 (08:43 -0700)
committerJason Self <j@jxself.org>
Sun, 23 Aug 2020 15:43:45 +0000 (08:43 -0700)
call them

27 files changed:
zilasm/Makefile.am
zilasm/compiler.cpp [new file with mode: 0644]
zilasm/compiler.h [new file with mode: 0644]
zilasm/configure.ac
zilasm/directives.c [deleted file]
zilasm/directives.cpp [new file with mode: 0644]
zilasm/directives.h
zilasm/header.c [deleted file]
zilasm/header.cpp [new file with mode: 0644]
zilasm/header.h
zilasm/include_all.h [new file with mode: 0644]
zilasm/labels.c [deleted file]
zilasm/labels.cpp [new file with mode: 0644]
zilasm/labels.h
zilasm/main.c [deleted file]
zilasm/main.cpp [new file with mode: 0644]
zilasm/opcodes.c
zilasm/opcodes.h
zilasm/parser.c [deleted file]
zilasm/parser.cpp [new file with mode: 0644]
zilasm/parser.h
zilasm/string_table.cpp [new file with mode: 0644]
zilasm/string_table.h [new file with mode: 0644]
zilasm/symtable.c
zilasm/symtable.h
zilasm/zmem.c
zilasm/zmem.h

index 5134797e6ee041a9cf829e007c29199a42dd605b..78f5d37f19979a361b55ececf37de1cd8a2c33fa 100644 (file)
@@ -2,6 +2,7 @@
 # Process this file with automake to produce Makefile.in.
 #
 # Copyright (C) 2015 Alexander Andrejevic <theflash AT sdf DOT lonestar DOT org>
+# Copyright (C) 2019, 2020 Jason Self <j@jxself.org>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as
@@ -20,5 +21,5 @@
 
 bin_PROGRAMS = zilasm
 man_MANS = zilasm.1
-zilasm_SOURCES = main.c opcodes.c symtable.c header.c parser.c directives.c labels.c zmem.c
-include_HEADERS =       opcodes.h symtable.h header.h parser.h directives.h labels.h zmem.h
+zilasm_SOURCES = main.cpp compiler.cpp opcodes.c symtable.c header.cpp parser.cpp directives.cpp labels.cpp string_table.cpp zmem.c
+include_HEADERS =       opcodes.h symtable.h header.h parser.h directives.h labels.h string_table.h zmem.h
diff --git a/zilasm/compiler.cpp b/zilasm/compiler.cpp
new file mode 100644 (file)
index 0000000..eaa2317
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+* parser.c -- part of ZilUtils/ZilAsm
+*
+* Copyright (C) 2020 Jason Self <j@jxself.org>
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License as
+* published by the Free Software Foundation, either version 3 of the
+* License, or (at your option) any later version.
+*
+* 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 Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>
+*
+* SPDX-License-Identifier: AGPL-3.0-or-later
+*/
+
+#include "include_all.h"
+
+CCompiler::CCompiler() :m_output_file(NULL)
+{
+}
+
+int
+CCompiler::assembly()
+{
+       FILE *file = fopen(m_output_file, "wb");
+       if (file)
+       {
+               program_header_reset(6);
+               int size = sizeof(program_header);
+
+               program_header.mode = 0;
+               program_header.release = 1;     // game version
+
+               m_code_size = 0;
+               ZMemblock *zmem_code = zmem_init(65536);
+
+               unsigned current_address = 64;
+
+               if (parser.m_functions.size() > 0)
+               {
+                       //unsigned function_table_size = parser.m_functions.size() * 2;
+                       program_header.H_FUNCTIONS_OFFSET = current_address >> 3;
+                       //current_address += function_table_size;
+               }
+               else
+                       program_header.H_FUNCTIONS_OFFSET = 0;
+
+               int code_start_offset = current_address;
+
+               if (parser.m_start_function_name == "")
+                       program_header.startPC = code_start_offset >> 2;
+               else
+                       program_header.startPC = parser.m_functions.find(parser.m_start_function_name)->second.address >> 2;
+
+               // write instructions' codes
+               m_code_size = parser.output_codes(zmem_code);
+
+               if (m_code_size & 7)
+               {
+                       const int additional_mem = 8 - (m_code_size & 7);
+                       for (int i = 0; i < additional_mem; ++i)
+                               zmem_putbyte(zmem_code, 0);
+                       m_code_size += additional_mem;
+               }
+
+               program_header.dynamic_size = 8;
+
+               //Program_header.h_file_size = 33;  //sizeof(Program_header) + zmb->used_size;
+
+               //m_code_size = 8;
+
+               Word stringTableOffset = m_code_size;
+               program_header.H_STRINGS_OFFSET = (64 + stringTableOffset) >> 3;
+
+               int stringTableSize = 64;
+               program_header.h_file_size =
+                       (code_start_offset + m_code_size + stringTableSize) >> 3;
+               ZMemblock *zmb = zmem_init(program_header.h_file_size * 8);
+
+               for (int i = 0; i < m_code_size; ++i)
+                       zmem_putbyte(zmb, zmem_code->contents[i]);
+
+               zmem_destroy(zmem_code);
+
+               //zmem_putbyte(zmb, 0); // number of local variables
+               //zmem_putbyte(zmb, 141); // print addr command
+
+               //Word offset = 0;
+               //zmem_putbyte(zmb, (offset >> 8) & 255);
+               //zmem_putbyte(zmb, offset & 255);
+
+               //zmem_putbyte(zmb, 186); // quit command
+
+               // output zeros until string table begins
+               while (zmb->used_size < stringTableOffset)
+                       zmem_putbyte(zmb, 0);
+               //
+               //// fill string table with one string
+               //add_string_to_string_table("Hello, World!", zmb);
+
+               outputToFile(&program_header, file);
+               //output_function_table(file);
+
+               fwrite(zmb->contents, zmb->allocated_size, 1, file);
+               fclose(file);
+       }
+
+       return OK;
+}
+
+
+char *
+CCompiler::get_output_file_name()
+{
+       return m_output_file;
+}
+
+
+void 
+CCompiler::output_function_table(FILE *file)
+{
+       if (parser.m_functions.size())
+       {
+               for(map<string, Function>::iterator iter = parser.m_functions.begin(); iter != parser.m_functions.end(); ++iter)
+               {
+                       Word w = (iter->second.address) >> 4;
+                       fprintf ( file, "%c", (w >> 8) & 255);
+                       fprintf(file, "%c", w & 255);
+               }
+
+       }
+}
\ No newline at end of file
diff --git a/zilasm/compiler.h b/zilasm/compiler.h
new file mode 100644 (file)
index 0000000..a885819
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * compiler.h -- part of ZilUtils/ZilAsm
+ *
+ * Copyright (C) 2020 Jason Self <j@jxself.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+#ifndef ZILASM_COMPILER
+#define ZILASM_COMPILER
+
+
+typedef struct
+{
+       int todo;
+} Opcode_dict;
+
+
+
+struct String_Table_Elem
+{
+       string value;                   // value in ASCII format
+       int index;
+};
+
+
+class CCompiler
+{
+public:
+       CCompiler();
+       int assembly();
+       void fill_config(void);
+       void get_arguments(int argc, char *argv[], char *envp[]);
+       char *get_output_file_name();
+       CParser parser;
+
+private:
+       char *m_output_file;
+       list < String_Table_Elem > m_string_table;
+       int m_code_size;
+
+       char *build_output_filename(const char basename[], const char *suffix);
+       void fill_zserial(void);
+       void new_file_suffix(char *result, size_t maxlen, const char *src,
+               const char *newsuffix);
+       void output_code_section();
+       void output_function_table(FILE *file);
+       void parse_intarg(int *dest, const char name[], int min, int max,
+               int defval);
+       void parse_zserial(void);
+       void print_usage(int failed);
+       void print_version();
+       void wrong_arg(const char *err, ...);
+};
+
+enum
+{
+       FAIL = -1, OK = 0, NEED_RESTART = 1
+};
+
+#endif
index 881332dc812382b7b14f15ed0145d551b509ca5c..8e7bb47728e2f881a80931eac2a4e4d171a598b9 100644 (file)
@@ -2,6 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 #
 # Copyright (C) 2015 Alexander Andrejevic <theflash AT sdf DOT lonestar DOT org>
+# Copyright (C) 2019 Jason Self <j@jxself.org>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as
@@ -20,7 +21,7 @@
 
 AC_PREREQ([2.65])
 AC_INIT([zilasm], [0.1])
-AC_CONFIG_SRCDIR([main.c])
+AC_CONFIG_SRCDIR([main.cpp])
 AC_CONFIG_HEADERS([config.h])
 
 AM_INIT_AUTOMAKE([-Wall -Werror foreign])
@@ -28,6 +29,7 @@ AC_CONFIG_FILES([Makefile])
 
 # Checks for programs.
 AC_PROG_CC
+AC_PROG_CXX
 
 # Checks for libraries.
 
diff --git a/zilasm/directives.c b/zilasm/directives.c
deleted file mode 100644 (file)
index b5aaf1a..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * directives.c -- part of ZilUtils/ZilAsm
- *
- * Copyright (C) 2016 Jason Self <j@jxself.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-#include <stdlib.h>   /* bsearch */
-#include <string.h>   /* strcmp */
-
-#include "directives.h"
-
-#define ARRAY_SIZE(x)  ((sizeof(x)) / (sizeof(x[0])))
-
-static int byte_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int end_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int endi_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int endt_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int fstr_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int funct_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int gstr_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int gvar_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int insert_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int len_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int new_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int object_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int prop_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int str_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int strl_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int table_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int vocbeg_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int vocend_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int word_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-static int zword_handler(const char *args)
-{
-       /* !!! TODO !!! */
-       return 0;
-}
-
-// Sorted array
-static Directive Directives[] = {
-       "BYTE",      byte_handler,
-       "END",        end_handler,
-       "ENDI",      endi_handler,
-       "ENDT",      endt_handler,
-       "FSTR",      fstr_handler,
-       "FUNCT",    funct_handler,
-       "GSTR",      gstr_handler,
-       "GVAR",      gvar_handler,
-       "INSERT",  insert_handler,
-       "LEN",        len_handler,
-       "NEW",        new_handler,
-       "OBJECT",  object_handler,
-       "PROP",      prop_handler,
-       "STR",        str_handler,
-       "STRL",      strl_handler,
-       "TABLE",    table_handler,
-       "VOCBEG",  vocbeg_handler,
-       "VOCEND",  vocend_handler,
-       "WORD",      word_handler,
-       "ZWORD",    zword_handler
-};
-
-typedef struct {
-       const char *contents;
-       unsigned length;
-} Name;
-
-static int namecmp(const void *key, const void *elem)
-{
-       const Name      *p = (Name     *)key;
-       const Directive *d = (Directive*)elem;
-
-       int len1 = p->length;
-       int len2 = strlen(d->name);
-
-       int rc = memcmp(p->contents, elem, len1 < len2 ? len1 : len2);
-       return rc ? rc : (len1 - len2);
-}
-
-Directive_handler directive_lookup(const char *name, unsigned namelen)
-{
-       Name n = { name, namelen };
-       Directive *p = (Directive*)bsearch(&n, Directives, ARRAY_SIZE(Directives), sizeof(Directive), namecmp);
-       return p ? p->handler : NULL;
-}
diff --git a/zilasm/directives.cpp b/zilasm/directives.cpp
new file mode 100644 (file)
index 0000000..94c39f9
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * directives.c -- part of ZilUtils/ZilAsm
+ *
+ * Copyright (C) 2016, 2020 Jason Self <j@jxself.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include "include_all.h"
+
+#define ARRAY_SIZE(x)  ((sizeof(x)) / (sizeof(x[0])))
+
+int g_stopParsing = 0;
+stack<FILE*> g_fileHandlers;
+
+
+
+static int
+byte_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+static int
+end_handler (const char *args, CParser* parser)
+{
+       g_stopParsing = 1;
+       return 0;
+}
+
+static int
+endi_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+static int
+endt_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+static int
+fstr_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+static int
+funct_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  
+       parser->add_function(args);
+       return 0;
+}
+
+static int
+gstr_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+static int
+gvar_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+static int
+insert_handler (const char *args, CParser* parser)
+{
+       string file_name;
+       char *p = (char*)args;
+       while (*p == ' ') p++;
+
+       if (*p == '"')
+       {
+               p++;
+               do
+               {
+                       file_name += *p;
+                       p++;
+               }
+               while (*p != '"' && *p != 0 ) ;
+       }
+       else
+       {
+               do
+               {
+                       file_name += *p;
+                       p++;
+               } while (*p != ' ' && *p != '\n' && *p != '\r' && *p != '\t' && *p != 0);
+       }
+       
+       if (file_name.find('.') == string::npos)
+       {
+               file_name += ".zap";
+       }
+
+#ifdef WIN32
+       char delimeter = '\\';
+#else
+       char delimeter = '/';
+#endif
+
+       Parsing_Context pc;
+       if (file_name.rfind(delimeter) == string::npos)
+       {
+               pc.current_directory = "";
+               pc.current_file_name = file_name;
+       }
+       else
+       {
+               pc.current_directory = file_name.substr(0, file_name.rfind(delimeter)+1);
+               pc.current_file_name = file_name.substr(file_name.rfind(delimeter)+1);
+       }
+
+       pc.current_directory = g_parsing_contexts.top().current_directory + pc.current_directory;
+       //pc.current_file_name = s;
+       g_parsing_contexts.push(pc);
+       
+       unsigned saveLineNumber = parser->m_current_line_number;
+       parser->parse_file(); //s.c_str());
+       parser->m_current_line_number = saveLineNumber;
+       return strlen(args);
+}
+
+static int
+len_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+static int
+newdirective_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+static int
+object_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+static int
+prop_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+static int
+str_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+static int
+strl_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+static int
+table_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+static int
+vocbeg_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+static int
+vocend_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+static int
+word_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+static int
+zword_handler (const char *args, CParser* parser)
+{
+  /* !!! TODO !!! */
+  return 0;
+}
+
+
+
+typedef struct
+{
+  const char *contents;
+  unsigned length;
+} Name;
+
+static int
+namecmp (const void *key, const void *elem)
+{
+  const Name *p = (Name *) key;
+  const Directive *d = (Directive *) elem;
+
+  int len1 = p->length;
+  int len2 = strlen (d->name);
+
+  int rc = memcmp (p->contents, elem, len1 < len2 ? len1 : len2);
+  return rc ? rc : (len1 - len2);
+}
+
+Directive_handler
+CDirectives::directive_lookup (const char *name, unsigned namelen)
+{
+       // Sorted array
+       static Directive Directives[] = {
+               "BYTE", byte_handler,
+               "END", end_handler,
+               "ENDI", endi_handler,
+               "ENDT", endt_handler,
+               "FSTR", fstr_handler,
+               "FUNCT", funct_handler,
+               "GSTR", gstr_handler,
+               "GVAR", gvar_handler,
+               "INSERT", insert_handler,
+               "LEN", len_handler,
+               "NEW", newdirective_handler,
+               "OBJECT", object_handler,
+               "PROP", prop_handler,
+               "STR", str_handler,
+               "STRL", strl_handler,
+               "TABLE", table_handler,
+               "VOCBEG", vocbeg_handler,
+               "VOCEND", vocend_handler,
+               "WORD", word_handler,
+               "ZWORD", zword_handler
+       };
+       
+       Name n = { name, namelen };
+  Directive *p =
+    (Directive *) bsearch (&n, Directives, ARRAY_SIZE (Directives),
+                          sizeof (Directive), namecmp);
+  return p ? p->handler : NULL;
+}
+
+
+CDirectives::CDirectives(CParser *parser) :m_parser(parser)
+{
+}
\ No newline at end of file
index 5b5982ebf96ba7a30253e57a68c2b36e32da5997..9f66060c1e16e4d550697dd7c1ad105a1e7f1940 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * directives.h -- part of ZilUtils/ZilAsm
  *
- * Copyright (C) 2016 Jason Self <j@jxself.org>
+ * Copyright (C) 2016, 2020 Jason Self <j@jxself.org>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
 #ifndef ZILASM_DIRECTIVES
 #define ZILASM_DIRECTIVES 1
 
-typedef int (*Directive_handler)(const char *directive_args);
+class CParser;
 
-typedef struct {
-       const char        name[16];
-       Directive_handler handler;
+typedef int (*Directive_handler) (const char *directive_args, CParser* parser);
+
+typedef struct
+{
+  const char name[16];
+  Directive_handler handler;
 } Directive;
 
-Directive_handler directive_lookup(const char *name, unsigned namelen);
+extern int g_stopParsing;
+extern stack<FILE*> g_fileHandlers;
+
+
+class CDirectives
+{
+public:
+       CDirectives(CParser *parser);
+       Directive_handler directive_lookup(const char *name, unsigned namelen);
 
+private:
+       CParser *m_parser;
+       
+       CDirectives();
+       //int   insert_handler(const char *args);
+};
 #endif /* ifndef ZILASM_DIRECTIVES */
diff --git a/zilasm/header.c b/zilasm/header.c
deleted file mode 100644 (file)
index e5f350f..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * header.c -- part of ZilUtils/ZilAsm
- *
- * Copyright (C) 2016, 2019 Jason Self <j@jxself.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-#include <string.h>  /* bzero */
-#include <assert.h>
-#include <stdio.h>
-
-#include "header.h"
-
-Program_header_struct Program_header;
-
-const unsigned MAX_HEADER_LEN = 40;
-
-void program_header_reset(unsigned zversion)
-{
-       bzero(&Program_header, sizeof(Program_header));
-       Program_header.version = zversion;
-}
-
-ZMemblock *program_header_build(void)
-{
-       ZMemblock *zmb = zmem_init(MAX_HEADER_LEN);
-       zmem_putbyte(zmb, Program_header.version);
-       /* TODO */
-       return zmb;
-}
-
-
-Word swapBytes(Word w)
-{
-       return ((w & 255) << 8) + (w >> 8);
-}
-
-
-void outputToFile(Program_header_struct *pHeader, FILE* file)
-{
-       Program_header_struct h;
-       memcpy(&h, pHeader, sizeof(Program_header_struct));
-
-       h.startPC = swapBytes(h.startPC);
-       h.h_file_size = swapBytes(h.h_file_size);
-       fwrite(&h, sizeof(Program_header_struct), 1, file);
-}
\ No newline at end of file
diff --git a/zilasm/header.cpp b/zilasm/header.cpp
new file mode 100644 (file)
index 0000000..c643eeb
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * header.c -- part of ZilUtils/ZilAsm
+ *
+ * Copyright (C) 2016, 2019, 2020 Jason Self <j@jxself.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <string.h>            /* bzero */
+#include <assert.h>
+#include <stdio.h>
+
+#include "header.h"
+
+Program_header_struct program_header;
+
+const unsigned MAX_HEADER_LEN = 40;
+
+void
+program_header_reset (unsigned zversion)
+{
+  bzero (&program_header, sizeof (program_header));
+  program_header.version = zversion;
+}
+
+ZMemblock *
+program_header_build (void)
+{
+  ZMemblock *zmb = zmem_init (MAX_HEADER_LEN);
+  zmem_putbyte (zmb, program_header.version);
+  /* TODO */
+  return zmb;
+}
+
+
+Word
+swapBytes (Word w)
+{
+  return ((w & 255) << 8) + (w >> 8);
+}
+
+
+void
+outputToFile (Program_header_struct * pHeader, FILE * file)
+{
+  Program_header_struct h;
+  memcpy (&h, pHeader, sizeof (Program_header_struct));
+
+  h.startPC = swapBytes (h.startPC);
+  h.h_file_size = swapBytes (h.h_file_size);
+  h.H_STRINGS_OFFSET = swapBytes(h.H_STRINGS_OFFSET);
+
+  h.H_FUNCTIONS_OFFSET = swapBytes(h.H_FUNCTIONS_OFFSET);
+
+  int size = sizeof (Program_header_struct);
+  fwrite (&h, sizeof (Program_header_struct), 1, file);
+}
index 41f82fbaf6ee01ff8cf4b7d9d449247eebebbdc8..5607b3a0b95ff0c43090737472a45a63cf1fb107 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * header.h -- part of ZilUtils/ZilAsm
  *
- * Copyright (C) 2016, 2019 Jason Self <j@jxself.org>
+ * Copyright (C) 2016, 2019, 2020 Jason Self <j@jxself.org>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
 
 #ifndef ZILASM_HEADER
 #define ZILASM_HEADER 1
-
+extern "C"
+{
 #include "zmem.h"
-
-typedef unsigned long   Byte_address;
-typedef unsigned long   Word_address;
+}
+typedef unsigned long Byte_address;
+typedef unsigned long Word_address;
 typedef unsigned long Packed_address;
-typedef unsigned long        Offset8;
-typedef unsigned short          Word;
-typedef unsigned char           Byte;
-typedef          int            Bool;
+typedef unsigned long Offset8;
+typedef unsigned short Word;
+typedef unsigned char Byte;
+typedef int Bool;
 
 //typedef struct {
-//     unsigned version;  // 1..6
-//     // [$01] V1..V3: Flags1
-//     Bool  statusline_type;      // bit1: 0=score/turns, 1=hh:mm
-//     Bool  split_two_discs;      // bit2
-//     Bool  statusline_notavail;  // bit4
-//     Bool  screensplit_avail;    // bit5
-//     Bool  varpitchfont_default; // bit6
-//     // [$01] V4: Flags1
-//     Bool  colors_avail;         // v5: bit0
-//     Bool  pics_avail;           // v6: bit1
-//     Bool  bold_avail;           // v4: bit2
-//     Bool  italic_avail;         // v4: bit3
-//     Bool  fixedspace_avail;     // v4: bit4
-//     Bool  sound_avail;          // v6: bit5
-//     Bool  timedkeyb_avail;      // v4: bit7
-//     // Addresses
-//     Byte_address   highmem_base;  // [$04]
-//     Byte_address   start_pc;      //  [$06], v1
-//     Packed_address start_routine; //  [$06], v6
-//     Byte_address   dictionary;    // [$08]
-//     Byte_address   objects;       // [$0A]
-//     Byte_address   globals;       // [$0C]
-//     Byte_address   static_base;   // [$0E]
-//     // [$10] Flags2
-//     Bool  transcript_on;        // v1: bit0
-//     Bool  print_fixedfont;      // v3: bit1
-//     Bool  request_redraw;       // v6: bit2
-//     Bool  want_pics;            // v5: bit3
-//     Bool  want_undo;            // v5: bit4
-//     Bool  want_mouse;           // v5: bit5
-//     Bool  want_colors;          // v5: bit6
-//     Bool  want_sound;           // v5: bit7
-//     Bool  want_menus;           // v5: bit8
-//     //
-//     Byte_address  abbrevs;        // [$18], v2
-//     Word  file_length;            // [$1A], v3
-//     Word  checksum;               // [$1C], v3
-//     Byte  interpreter_number;     // [$1E], v4
-//     Byte  interpreter_version;    // [$1F], v4
-//     // Screen
-//     Byte  screen_lines;           // [$20], v4 ($FF = infinite)
-//     Byte  screen_chars;           // [$21], v4
-//     Word  screen_width;           // [$22], v5
-//     Word  screen_height;          // [$24], v5
-//     Byte  font_width;             // [$26], v5/v6
-//     Byte  font_height;            // [$27], v5/v6
-//     // Tables
-//     Offset8  routines;            // [$28], v6
-//     Offset8  strings;             // [$2A], v6
-//     Byte     backcolor;           // [$2C], v5
-//     Byte     forecolor;           // [$2D], v5
-//     Byte_address  term_chartable; // [$2E], v5
-//     Word     width3;              // [$30], v6
-//     Word     revnumber;           // [$32], v1
-//     Byte_address  alphabet;       // [$34], v5
-//     Byte_address  header_ext;     // [$36], v5
+//      unsigned version;  // 1..6
+//      // [$01] V1..V3: Flags1
+//      Bool  statusline_type;      // bit1: 0=score/turns, 1=hh:mm
+//      Bool  split_two_discs;      // bit2
+//      Bool  statusline_notavail;  // bit4
+//      Bool  screensplit_avail;    // bit5
+//      Bool  varpitchfont_default; // bit6
+//      // [$01] V4: Flags1
+//      Bool  colors_avail;         // v5: bit0
+//      Bool  pics_avail;           // v6: bit1
+//      Bool  bold_avail;           // v4: bit2
+//      Bool  italic_avail;         // v4: bit3
+//      Bool  fixedspace_avail;     // v4: bit4
+//      Bool  sound_avail;          // v6: bit5
+//      Bool  timedkeyb_avail;      // v4: bit7
+//      // Addresses
+//      Byte_address   highmem_base;  // [$04]
+//      Byte_address   start_pc;      //  [$06], v1
+//      Packed_address start_routine; //  [$06], v6
+//      Byte_address   dictionary;    // [$08]
+//      Byte_address   objects;       // [$0A]
+//      Byte_address   globals;       // [$0C]
+//      Byte_address   static_base;   // [$0E]
+//      // [$10] Flags2
+//      Bool  transcript_on;        // v1: bit0
+//      Bool  print_fixedfont;      // v3: bit1
+//      Bool  request_redraw;       // v6: bit2
+//      Bool  want_pics;            // v5: bit3
+//      Bool  want_undo;            // v5: bit4
+//      Bool  want_mouse;           // v5: bit5
+//      Bool  want_colors;          // v5: bit6
+//      Bool  want_sound;           // v5: bit7
+//      Bool  want_menus;           // v5: bit8
+//      //
+//      Byte_address  abbrevs;        // [$18], v2
+//      Word  file_length;            // [$1A], v3
+//      Word  checksum;               // [$1C], v3
+//      Byte  interpreter_number;     // [$1E], v4
+//      Byte  interpreter_version;    // [$1F], v4
+//      // Screen
+//      Byte  screen_lines;           // [$20], v4 ($FF = infinite)
+//      Byte  screen_chars;           // [$21], v4
+//      Word  screen_width;           // [$22], v5
+//      Word  screen_height;          // [$24], v5
+//      Byte  font_width;             // [$26], v5/v6
+//      Byte  font_height;            // [$27], v5/v6
+//      // Tables
+//      Offset8  routines;            // [$28], v6
+//      Offset8  strings;             // [$2A], v6
+//      Byte     backcolor;           // [$2C], v5
+//      Byte     forecolor;           // [$2D], v5
+//      Byte_address  term_chartable; // [$2E], v5
+//      Word     width3;              // [$30], v6
+//      Word     revnumber;           // [$32], v1
+//      Byte_address  alphabet;       // [$34], v5
+//      Byte_address  header_ext;     // [$36], v5
 //} Program_header_struct;
 
 
 enum MODE_FLAGS
 {
-       COLOR_AVAILABLE = 0,
-       DISPLAY_AVAILABLE = 1,
-       BOLD_AVAILABLE = 2,
-       ITALIC_AVAILABLE = 4,
-       MONOSPACE_AVAILABLE = 8
+  COLOR_AVAILABLE = 0,
+  DISPLAY_AVAILABLE = 1,
+  BOLD_AVAILABLE = 2,
+  ITALIC_AVAILABLE = 4,
+  MONOSPACE_AVAILABLE = 8
 };
 
-typedef struct {
-       Byte version;  // 1..6
-       Byte mode;
-       Word release;
-       Word resident_size;
-       Word startPC;
-       Word dictionaryTableOffset;
-       Word objectsTableOffset;
-       Word globalsTableOffset;
-       Word dynamic_size;
-       Word flags;
-       unsigned char serial[6];
-       Word h_abbreviations;
-       Word h_file_size;
-       Word checkSum;
-       unsigned char interpreterNumber;
-       unsigned char interpreterVersion;
-       unsigned char H_SCREEN_ROWS;
-       unsigned char H_SCREEN_COLS;
-       Word H_SCREEN_WIDTH;
-       Word H_SCREEN_HEIGHT;
-       unsigned char H_FONT_HEIGHT; /* this is the font width in V5 */
-       unsigned char H_FONT_WIDTH; /* this is the font height in V5 */
-       Word H_FUNCTIONS_OFFSET;
-       Word H_STRINGS_OFFSET;
-       unsigned char H_DEFAULT_BACKGROUND;
-       unsigned char  H_DEFAULT_FOREGROUND;
-       Word H_TERMINATING_KEYS;
-       Word H_LINE_WIDTH;
-       unsigned char  H_STANDARD_HIGH;
-       unsigned char H_STANDARD_LOW;
-       Word H_ALPHABET;
-       Word H_EXTENSION_TABLE;
-       char USER_NAME[8];
+typedef struct
+{
+  Byte version;                        // 1..6
+  Byte mode;
+  Word release;
+  Word resident_size;          // also it's a start of "high" memory region
+  Word startPC;
+  Word dictionaryTableOffset;
+  Word objectsTableOffset;
+  Word globalsTableOffset;
+  Word dynamic_size;           // also it's a start of "static" memory region
+  Word flags;
+  unsigned char serial[6];
+  Word h_abbreviations;
+  Word h_file_size;
+  Word checkSum;
+  unsigned char interpreterNumber;
+  unsigned char interpreterVersion;
+  unsigned char H_SCREEN_ROWS;
+  unsigned char H_SCREEN_COLS;
+  Word H_SCREEN_WIDTH;
+  Word H_SCREEN_HEIGHT;
+  unsigned char H_FONT_HEIGHT; /* this is the font width in V5 */
+  unsigned char H_FONT_WIDTH;  /* this is the font height in V5 */
+  Word H_FUNCTIONS_OFFSET;
+  Word H_STRINGS_OFFSET;
+  unsigned char H_DEFAULT_BACKGROUND;
+  unsigned char H_DEFAULT_FOREGROUND;
+  Word H_TERMINATING_KEYS;
+  Word H_LINE_WIDTH;
+  unsigned char H_STANDARD_HIGH;
+  unsigned char H_STANDARD_LOW;
+  Word H_ALPHABET;
+  Word H_EXTENSION_TABLE;
+  char USER_NAME[8];
 } Program_header_struct;
 
-extern Program_header_struct Program_header;
 
-void program_header_reset(unsigned zversion);
-ZMemblock *program_header_build(void);
+extern Program_header_struct program_header;
+
+void program_header_reset (unsigned zversion);
+ZMemblock *program_header_build (void);
 
-typedef struct {
-       Byte numberOfSelfinseringCharacters;
-       Byte *pSymbols;
-       Byte numberOfBytesInEachEntry;
+typedef struct
+{
+  Byte numberOfSelfinseringCharacters;
+  Byte *pSymbols;
+  Byte numberOfBytesInEachEntry;
 
-} Program_dictionary_struct ;
+} Program_dictionary_struct;
 
 
 
-void outputToFile(Program_header_struct *h, FILE* file);
+void outputToFile (Program_header_struct * h, FILE * file);
 
-#endif  /* ifndef ZILASM_HEADER */
+//void relase_parser ();
+#endif /* ifndef ZILASM_HEADER */
diff --git a/zilasm/include_all.h b/zilasm/include_all.h
new file mode 100644 (file)
index 0000000..66e0c06
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * include_all.h -- part of ZilUtils/ZilAsm
+ *
+ * Copyright (C) 2020 Jason Self <j@jxself.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#pragma once
+
+#ifndef INCLUDE_ALL
+#define INCLUDE_ALL
+
+
+//#include <stdio.h>
+//#include <stdlib.h>
+//#include <stdarg.h>
+//#include <string.h>
+
+
+#include <stdlib.h>
+#include <stdio.h>             /* fopen, fgets */
+#include <stdarg.h>
+#include <string.h>            /* strlen */
+extern "C"
+{
+#include <strings.h>
+}
+#include <getopt.h>
+#include <time.h>
+#include <ctype.h>
+
+
+#include <string>
+#include <stack>
+#include <list>
+#include <vector>
+#include <map>
+using namespace std;
+
+
+
+#include "config.h"
+#include "header.h"
+extern "C"
+{
+#include "opcodes.h"
+}
+
+#include "header.h"
+#include "directives.h"
+#include "parser.h"
+
+
+//extern "C"
+//{
+//#include "opcodes.h"
+//}
+#include "labels.h"
+#include "string_table.h"
+#include "compiler.h"
+#endif
+
diff --git a/zilasm/labels.c b/zilasm/labels.c
deleted file mode 100644 (file)
index c396397..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * labels.c -- part of ZilUtils/ZilAsm
- *
- * Copyright (C) 2016 Jason Self <j@jxself.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-#include <assert.h>
-
-#include "labels.h"
-
-Symtable *Global_labels;
-Symtable  *Local_labels;
-
-const unsigned MAX_GLOBAL_LABELS = 1024;
-const unsigned MAX_LOCAL_LABELS  = 256;
-const unsigned MAX_LABEL_LEN     = 32;
-const unsigned ADDRESS_SIZE      = sizeof(long long);  /* TODO!!! */
-
-void init_local_labels(void)
-{
-       if (Local_labels)
-               symtable_destroy(Local_labels);
-       Local_labels = symtable_create(MAX_LOCAL_LABELS, MAX_LABEL_LEN, ADDRESS_SIZE);
-}
-
-void init_global_labels(void)
-{
-       assert(Global_labels);
-       Global_labels = symtable_create(MAX_GLOBAL_LABELS, MAX_LABEL_LEN, ADDRESS_SIZE);
-}
diff --git a/zilasm/labels.cpp b/zilasm/labels.cpp
new file mode 100644 (file)
index 0000000..c8f97f9
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * labels.c -- part of ZilUtils/ZilAsm
+ *
+ * Copyright (C) 2016, 2019 Jason Self <j@jxself.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <assert.h>
+
+#include "labels.h"
+
+Symtable *Global_labels;
+Symtable *Local_labels;
+
+const unsigned MAX_GLOBAL_LABELS = 1024;
+const unsigned MAX_LOCAL_LABELS = 256;
+const unsigned MAX_LABEL_LEN = 32;
+const unsigned ADDRESS_SIZE = sizeof (long long);      /* TODO!!! */
+
+void
+init_local_labels (void)
+{
+  if (Local_labels)
+    symtable_destroy (Local_labels);
+  Local_labels =
+    symtable_create (MAX_LOCAL_LABELS, MAX_LABEL_LEN, ADDRESS_SIZE);
+}
+
+void
+init_global_labels (void)
+{
+  assert (Global_labels);
+  Global_labels =
+    symtable_create (MAX_GLOBAL_LABELS, MAX_LABEL_LEN, ADDRESS_SIZE);
+}
index 5ade61346d9d396e31c81c9258e76926528d1347..abef3ce9fe27472f301f7a4bac48ba0b66fb77f9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * labels.h -- part of ZilUtils/ZilAsm
  *
- * Copyright (C) 2016 Jason Self <j@jxself.org>
+ * Copyright (C) 2016, 2019 Jason Self <j@jxself.org>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
 
 #ifndef ZILASM_LABELS
 #define ZILASM_LABELS 1
-
+extern "C"
+{
 #include "symtable.h"
-
+}
 extern Symtable *Global_labels;
-extern Symtable  *Local_labels;
+extern Symtable *Local_labels;
 
-extern void init_local_labels(void);
-extern void init_global_labels(void);
+extern void init_local_labels (void);
+extern void init_global_labels (void);
 
 #endif /* ifndef ZILASM_LABELS */
diff --git a/zilasm/main.c b/zilasm/main.c
deleted file mode 100644 (file)
index b602339..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * main.c
- *
- * Copyright (C) 2015 Alexander Andrejevic <theflash AT sdf DOT lonestar DOT org>
- * Copyright (C) 2015, 2019 Jason Self <j@jxself.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <getopt.h>
-#include <time.h>
-#include <ctype.h>
-
-#include "config.h"
-
-#include "header.h"
-
-const int DEFAULT_ZVERSION = 6;
-
-enum { ZVERSION = 11, ZORKID, ZSERIAL };
-
-enum { FAIL = -1, OK = 0, NEED_RESTART = 1 };
-
-static struct option const long_options[] =
-{
-       { "help",     no_argument,       NULL, 'h' },
-       { "version",  no_argument,       NULL, 'V' },
-       { "output",   required_argument, NULL, 'o' },
-       { "zversion", required_argument, NULL, ZVERSION },
-       { "zorkid",   required_argument, NULL, ZORKID   },
-       { "serial",   required_argument, NULL, ZSERIAL  },
-       { NULL, 0, NULL, 0 }
-};
-
-typedef struct {
-       int todo;
-} Opcode_dict;
-
-struct
-{
-       int  zversion;     /* 0 - 8     */
-       int  zorkid;       /* 0 - 65535 */
-       char zserial[7];   /* YYMMDD    */
-       Opcode_dict *opcode_dict;
-} Config;
-
-void wrong_arg(const char *err, ...)
-{
-       if (err) {
-               va_list ap;
-               va_start(ap, err);
-               vfprintf(stderr, err, ap);
-               va_end(ap);
-       }
-       fprintf(stderr, "Try `" PACKAGE_NAME " --help' for more information.\n");
-       exit(1);
-}
-
-void print_version()
-{
-       printf( PACKAGE_STRING "\n"
-              "License AGPLv3+: GNU AGPL version 3 or later\n"
-              "<http://gnu.org/licenses/agpl.html>\n"
-              "This is free software: you are free to change and redistribute it.\n"
-              "There is NO WARRANTY, to the extent permitted by law.\n"
-       );
-       exit(0);
-}
-
-void print_usage(int failed)
-{
-       printf("Usage: " PACKAGE_NAME " [OPTION...] [FILES...]\n"
-              "\n"
-              "--version  Display program version and exit\n"
-              "--help     Display this help\n"
-              "\n"
-              "--zversion (accepts numbers 1 - 8, defaults to %d if not specified)\n"
-              "--zorkid   (integer between 0 and 65535, defaults to 0 if not specified)\n"
-              "--serial   (six characters of ASCII, defaults to current date\n"
-              "            in the form YYMMDD if not specified)\n",
-              DEFAULT_ZVERSION
-       );
-       exit(failed);
-}
-
-void fill_zserial(void)
-{
-       time_t t;
-       struct tm *timeinfo;
-       time (&t);
-       timeinfo = localtime(&t);
-       strftime (Config.zserial, sizeof(Config.zserial), "%y%m%d", timeinfo);
-}
-
-void fill_config(void)
-{
-       bzero(&Config, sizeof(Config));
-       Config.zversion = DEFAULT_ZVERSION;
-       fill_zserial();
-}
-
-void parse_intarg(int *dest, const char name[], int min, int max, int defval)
-{
-       if (!optarg) {
-               *dest = defval;
-               return;
-       }
-       int n = atoi(optarg);
-       if (n >= min && n <= max) {
-               *dest = n;
-               return;
-       }
-       wrong_arg("Wrong %s value %s, must be integer between %d and %d\n",
-               name, optarg, min, max);
-}
-
-void parse_zserial(void)
-{
-       if (!optarg) {
-               fill_zserial();
-               return;
-       }
-       size_t n = strlen(optarg);
-       if (n == sizeof(Config.zserial) - 1) {
-               char *p = optarg;
-               while (*p && isalnum(*p))
-                       p++;
-               if (!*p) {    /* ..optarg contains alphanumeric only? */
-                       strncpy(Config.zserial, optarg, sizeof(Config.zserial));
-                       return;
-               }
-       }
-       wrong_arg("Wrong zserial value %s, must be 6 ascii characters\n", optarg);
-}
-
-void new_file_suffix(char *result, size_t maxlen, const char *src, const char *newsuffix)
-{
-       strncpy(result, src, maxlen);
-       char *p = strrchr(result, '.');
-       if (p && strchr(p, '/'))
-               p = NULL;
-       if (p) {
-               strncpy(p, newsuffix, maxlen - (p - result));
-       } else {
-               strncat(result, newsuffix, maxlen);
-       }
-       result[maxlen] = 0;
-}
-
-char *build_output_filename(const char basename[], const char *suffix)
-{
-       int n = strlen(basename) + strlen(suffix);
-       char *ofile = malloc(n + 1);  /* todo!!! check for NULL. free. */
-       new_file_suffix(ofile, n, basename, suffix);
-       return ofile;
-}
-
-int init_assembly(void)
-{
-       /* TODO */
-       return OK;
-}
-
-int assembly(char *output_file)
-{
-       /* TODO */
-       FILE *file = fopen(output_file, "w");
-       if (file)
-       {
-               program_header_reset(6);
-
-               int size = sizeof(Program_header );
-               //Program_header.
-
-               Program_header.mode = 0; // DISPLAY_AVAILABLE | MONOSPACE_AVAILABLE;
-               Program_header.release = 1; // game version
-
-               Program_header.startPC = 64;
-
-               Program_header.dynamic_size = 128;
-               Program_header.h_file_size = 9;  //sizeof(Program_header) + zmb->used_size;
-
-               ZMemblock *zmb = zmem_init(Program_header.h_file_size * 8);
-
-               //fprintf(file, "%c", 178); // printi command
-               //fprintf(file, "hello, world!");
-
-               zmem_putbyte(zmb, 186); // quit command
-
-
-
-               outputToFile(&Program_header, file);
-
-               //fprintf(file, "%c", 186);
-               fwrite(zmb->contents, zmb->allocated_size, 1, file);
-               fclose(file);
-       }
-
-       return OK;
-}
-
-int main(int argc, char *argv[], char *envp[])
-{
-       const char *output_file = NULL;
-       int i;
-
-       fill_config();
-
-       int opt = 0;
-       while ((opt = getopt_long (argc, argv, "hVo:", long_options, NULL)) != -1) {
-               switch(opt) {
-               case 'h'     : print_usage(0);
-               case 'V'     : print_version();
-               case 'o'     : if (output_file) wrong_arg("Output file must be given once\n");
-                              output_file = optarg;
-                              break;
-               case ZVERSION: parse_intarg(&Config.zversion, "zversion", 1, 8,      1); break;
-               case ZORKID  : parse_intarg(&Config.zorkid,   "zorkid",   0, 0xFFFF, 0); break;
-               case ZSERIAL : parse_zserial();                                          break;
-               default      : wrong_arg(0);
-               }
-       }
-
-       int first_input_file = optind;
-       if (first_input_file >= argc)
-               wrong_arg("Missing input file\n");
-       if (!output_file)
-               output_file = build_output_filename(argv[first_input_file], ".dat");
-
-       // TODO: Everything :)
-
-       printf("Input files:\n");
-       for (i = optind; i < argc; i++)
-               printf("\t%s\n", argv[i]);
-
-       printf("Output file: %s\n\n", output_file);
-
-       printf("Config:\n"
-              "- ZVersion: %d\n"
-              "- ZorkID:   %d\n"
-              "- ZSerial:  %s\n",
-              Config.zversion, Config.zorkid, Config.zserial
-       );
-
-       init_opcodes(Config.zversion, 0);
-
-       while(init_assembly() == OK && assembly(output_file) == NEED_RESTART);
-
-       /* TODO! List global symbols */
-       /* TODO! Find abbreviations */
-
-       return 0;
-}
diff --git a/zilasm/main.cpp b/zilasm/main.cpp
new file mode 100644 (file)
index 0000000..e7bd734
--- /dev/null
@@ -0,0 +1,337 @@
+/*
+ * main.c
+ *
+ * Copyright (C) 2015 Alexander Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Copyright (C) 2015, 2019, 2020 Jason Self <j@jxself.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+//
+//#include <stdio.h>
+//#include <stdlib.h>
+//#include <stdarg.h>
+//#include <string.h>
+//#include <string>
+//#include <list>
+//#include <stack>
+//#include <list>
+//#include <vector>
+//using namespace std;
+//
+//
+//extern "C"
+//{
+//#include <strings.h>
+//}
+//#include <getopt.h>
+//#include <time.h>
+//#include <ctype.h>
+//#include "config.h"
+//#include "header.h"
+//extern "C"
+//{
+//#include "opcodes.h"
+//}
+//#include "directives.h"
+//#include "parser.h"
+//#include "compiler.h"
+
+
+#include "include_all.h"
+
+const int DEFAULT_ZVERSION = 6;
+
+enum
+{ ZVERSION = 11, ZORKID, ZSERIAL };
+
+
+
+static struct option const long_options[] = {
+  {"help", no_argument, NULL, 'h'},
+  {"version", no_argument, NULL, 'V'},
+  {"output", required_argument, NULL, 'o'},
+  {"zversion", required_argument, NULL, ZVERSION},
+  {"zorkid", required_argument, NULL, ZORKID},
+  {"serial", required_argument, NULL, ZSERIAL},
+  {NULL, 0, NULL, 0}
+};
+
+
+
+
+
+
+
+
+
+
+struct
+{
+       int zversion;                   /* 0 - 8     */
+       int zorkid;                     /* 0 - 65535 */
+       char zserial[7];                /* YYMMDD    */
+       Opcode_dict *opcode_dict;
+} Config;
+
+void
+CCompiler::get_arguments (int argc, char *argv[], char *envp[])
+{
+  int opt = 0;
+  while ((opt = getopt_long (argc, argv, "hVo:", long_options, NULL)) != -1)
+    {
+      switch (opt)
+       {
+       case 'h':
+         print_usage (0);
+       case 'V':
+         print_version ();
+       case 'o':
+         if (m_output_file)
+           wrong_arg ("Output file must be given once\n");
+         m_output_file = optarg;
+         break;
+       case ZVERSION:
+         parse_intarg (&Config.zversion, "zversion", 1, 8, 1);
+         break;
+       case ZORKID:
+         parse_intarg (&Config.zorkid, "zorkid", 0, 0xFFFF, 0);
+         break;
+       case ZSERIAL:
+         parse_zserial ();
+         break;
+       default:
+         wrong_arg (0);
+       }
+    }
+
+  int first_input_file = optind;
+  if (first_input_file >= argc)
+    wrong_arg ("Missing input file\n");
+  if (!m_output_file)
+    m_output_file = build_output_filename (argv[first_input_file], ".dat");
+
+  // TODO: Everything :)
+
+
+  printf ("Input files:\n");
+  for (int i = optind; i < argc; i++)
+    printf ("\t%s\n", argv[i]);
+
+  printf ("Output file: %s\n\n", m_output_file);
+
+  printf ("Config:\n"
+         "- ZVersion: %d\n"
+         "- ZorkID:   %d\n"
+         "- ZSerial:  %s\n", Config.zversion, Config.zorkid, Config.zserial);
+
+}
+
+
+void
+CCompiler::wrong_arg (const char *err, ...)
+{
+  if (err)
+    {
+      va_list ap;
+      va_start (ap, err);
+      vfprintf (stderr, err, ap);
+      va_end (ap);
+    }
+  fprintf (stderr, "Try `" PACKAGE_NAME " --help' for more information.\n");
+  exit (1);
+}
+
+
+void
+CCompiler::print_version ()
+{
+  printf (PACKAGE_STRING "\n"
+         "License AGPLv3+: GNU AGPL version 3 or later\n"
+         "<http://gnu.org/licenses/agpl.html>\n"
+         "This is free software: you are free to change and redistribute it.\n"
+         "There is NO WARRANTY, to the extent permitted by law.\n");
+  exit (0);
+}
+
+
+void
+CCompiler::print_usage (int failed)
+{
+  printf ("Usage: " PACKAGE_NAME " [OPTION...] [FILES...]\n"
+         "\n"
+         "--version  Display program version and exit\n"
+         "--help     Display this help\n"
+         "\n"
+         "--zversion (accepts numbers 1 - 8, defaults to %d if not specified)\n"
+         "--zorkid   (integer between 0 and 65535, defaults to 0 if not specified)\n"
+         "--serial   (six characters of ASCII, defaults to current date\n"
+         "            in the form YYMMDD if not specified)\n",
+         DEFAULT_ZVERSION);
+  exit (failed);
+}
+
+void
+CCompiler::fill_zserial (void)
+{
+  time_t t;
+  struct tm *timeinfo;
+  time (&t);
+  timeinfo = localtime (&t);
+  strftime (Config.zserial, sizeof (Config.zserial), "%y%m%d", timeinfo);
+}
+
+
+void
+CCompiler::fill_config (void)
+{
+  bzero (&Config, sizeof (Config));
+  Config.zversion = DEFAULT_ZVERSION;
+  fill_zserial ();
+}
+
+
+void
+CCompiler::parse_intarg (int *dest, const char name[], int min, int max,
+                    int defval)
+{
+  if (!optarg)
+    {
+      *dest = defval;
+      return;
+    }
+  int n = atoi (optarg);
+  if (n >= min && n <= max)
+    {
+      *dest = n;
+      return;
+    }
+  wrong_arg ("Wrong %s value %s, must be integer between %d and %d\n",
+            name, optarg, min, max);
+}
+
+
+void
+CCompiler::parse_zserial (void)
+{
+  if (!optarg)
+    {
+      fill_zserial ();
+      return;
+    }
+  size_t n = strlen (optarg);
+  if (n == sizeof (Config.zserial) - 1)
+    {
+      char *p = optarg;
+      while (*p && isalnum (*p))
+       p++;
+      if (!*p)
+       {                       /* ..optarg contains alphanumeric only? */
+         strncpy (Config.zserial, optarg, sizeof (Config.zserial));
+         return;
+       }
+    }
+  wrong_arg ("Wrong zserial value %s, must be 6 ascii characters\n", optarg);
+}
+
+
+void
+CCompiler::new_file_suffix (char *result, size_t maxlen, const char *src,
+                       const char *newsuffix)
+{
+  strncpy (result, src, maxlen);
+  char *p = strrchr (result, '.');
+  if (p && strchr (p, '/'))
+    p = NULL;
+  if (p)
+    {
+      strncpy (p, newsuffix, maxlen - (p - result));
+    }
+  else
+    {
+      strncat (result, newsuffix, maxlen);
+    }
+  result[maxlen] = 0;
+}
+
+
+char *
+CCompiler::build_output_filename (const char basename[], const char *suffix)
+{
+  int n = strlen (basename) + strlen (suffix);
+  char *ofile = (char *) malloc (n + 1);       /* todo!!! check for NULL. free. */
+  new_file_suffix (ofile, n, basename, suffix);
+  return ofile;
+}
+
+
+int
+init_assembly (void)
+{
+  /* TODO */
+  return OK;
+}
+
+
+void
+CCompiler::output_code_section ()
+{
+
+}
+
+
+int
+main (int argc, char *argv[], char *envp[])
+{
+  CCompiler compiler;
+
+  compiler.fill_config ();
+  compiler.get_arguments (argc, argv, envp);
+  init_opcodes (Config.zversion, 0);
+
+  
+       //for (int i = optind; i < argc; i++)
+       //      parse_file(argv[i]);
+  
+  string file_name = argv[optind];
+  Parsing_Context pc;
+
+#ifdef WIN32
+  char delimeter = '\\';
+#else
+  char delimeter = '/';
+#endif
+
+  if (file_name.rfind(delimeter) == string::npos)
+  {
+         pc.current_directory = "";
+         pc.current_file_name = file_name;
+  }
+  else
+  {
+         pc.current_directory = file_name.substr(0, file_name.rfind(delimeter)+1);
+         pc.current_file_name = file_name.substr(file_name.rfind(delimeter)+1);
+  }
+  g_parsing_contexts.push(pc);
+
+  compiler.parser.parse_file();// argv[optind]);
+  if ( !compiler.parser.have_errors())
+       compiler.assembly ();
+
+  /* TODO! List global symbols */
+  /* TODO! Find abbreviations */
+  //relase_parser ();
+  return 0;
+}
index 1d9ad6436ad88cf48d895703527d4dcc5fd2fca0..b85b0dabeeea06383324e235fbcd1828b9d0d5f0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * opcodes.c -- part of ZilUtils/ZilAsm
  *
- * Copyright (C) 2016 Jason Self <j@jxself.org>
+ * Copyright (C) 2016, 2019, 2020 Jason Self <j@jxself.org>
  *
  * Based on ZILF (c) 2010, 2015 Jesse McGrew
  *
 
 #include "opcodes.h"
 
-typedef struct {
-       unsigned opcode;
-       const char *classic_name;
-       const char *inform_name;
-       int minver;
-       int maxver;
-       ZOpcode_flags flags;
+typedef struct
+{
+  unsigned opcode;
+  const char *classic_name;
+  const char *inform_name;
+  int minver;
+  int maxver;
+  ZOpcode_flags flags;
 } Opcode_detailed_info;
 
+
 static Opcode_detailed_info detailed_opcodes[] = {
-       { 20,  "ADD",         "add",             1, 6, Zop_store   },              // Add
-       { 259, "ASHIFT",      "art_shift",       5, 6, Zop_store   },              // Ashift
-       { 255, "ASSIGNED?",   "check_arg_count", 5, 6, Zop_branch | Zop_indvar },  // Assigned_P
-       { 9,   "BAND",        "and",             1, 6, Zop_store   },              // Band
-       { 143, "BCOM",        "not",             1, 4, Zop_store   },              // Bcom_V1
-       { 248, "BCOM",        "not",             5, 6, Zop_store   },              // Bcom_V5
-       { 8,   "BOR",         "or",              1, 6, Zop_store   },              // Bor
-       { 7,   "BTST",        "test",            1, 6, Zop_branch  },              // Btst
-       { 242, "BUFOUT",      "buffer_mode",     4, 6, 0           },              // Bufout
-       { 224, "CALL",        "call_vs",         1, 6, Zop_store | Zop_call },     // Call
-       { 136, "CALL1",       "call_1s",         4, 6, Zop_store | Zop_call },     // Call1
-       { 25,  "CALL2",       "call_2s",         4, 6, Zop_store | Zop_call },     // Call2
-       { 185, "CATCH",       "catch",           5, 6, Zop_store   },              // Catch
-       { 268, "CHECKU",      "check_unicode",   5, 6, Zop_store   },              // Checku
-       { 237, "CLEAR",       "erase_window",    4, 6, 0           },              // Clear
-       { 27,  "COLOR",       "set_colour",      5, 5, 0           },              // Color_v5
-       { 27,  "COLOR",       "set_colour",      6, 6, Zop_varargs },              // Color_v6
-       { 253, "COPYT",       "copy_table",      5, 6, 0           },              // Copyt
-       { 187, "CRLF",        "new_line",        1, 6, 0           },              // Crlf
-       { 240, "CURGET",      "get_cursor",      4, 6, 0           },              // Curget
-       { 239, "CURSET",      "set_cursor",      4, 6, 0           },              // Curset
-       { 263, "DCLEAR",      "erase_picture",   6, 6, 0           },              // Dclear
-       { 134, "DEC",         "dec",             1, 6, Zop_indvar  },              // Dec
-       { 244, "DIRIN",       "input_stream",    3, 6, 0           },              // Dir-In
-       { 243, "DIROUT",      "output_stream",   3, 6, 0           },              // Dir-Out
-       { 261, "DISPLAY",     "draw_picture",    6, 6, 0           },              // Display
-       { 23,  "DIV",         "div",             1, 6, Zop_store   },              // Div
-       { 4,   "DLESS?",      "dec_chk",         1, 6, Zop_branch | Zop_indvar },  // Dless_P
-//     { 271, "ENDMOVE",     "ENDMOVE",         5, 6, Zop_store   },              // Endmove = 271
-       { 1,   "EQUAL?",      "jeq",             1, 6, Zop_branch | Zop_varargs }, // Equal_P
-       { 238, "ERASE",       "erase_line",      4, 6, 0           },              // Erase
-       { 12,  "FCLEAR",      "clear_attr",      1, 6, 0           },              // Fclear
-       { 130, "FIRST?",      "get_child",       1, 6, Zop_store | Zop_branch },   // First_P
-       { 260, "FONT",        "set_font",        5, 6, Zop_store   },              // Font
-       { 11,  "FSET",        "set_attr",        1, 6, 0           },              // Fset
-       { 10,  "FSET?",       "test_attr",       1, 6, Zop_branch  },              // Fset_P
-       { 185, "FSTACK",      "pop",             1, 4, 0           },              // Fstack_V1
-       { 277, "FSTACK",      "pop_stack",       6, 6, 0           },              // Fstack_V6
-       { 15,  "GET",         "loadw",           1, 6, Zop_store   },              // Get
-       { 16,  "GETB",        "loadb",           1, 6, Zop_store   },              // Getb
-       { 17,  "GETP",        "get_prop",        1, 6, Zop_store   },              // Getp
-       { 18,  "GETPT",       "get_prop_addr",   1, 6, Zop_store   },              // Getpt
-       { 3,   "GRTR?",       "jg",              1, 6, Zop_branch  },              // Grtr_P
-       { 241, "HLIGHT",      "set_text_style",  4, 6, 0           },              // Hlight
-       { 249, "ICALL",       "call_vn",         5, 6, Zop_call    },              // Icall
-       { 143, "ICALL1",      "call_1n",         5, 6, Zop_call    },              // Icall1
-       { 26,  "ICALL2",      "call_2n",         5, 6, Zop_call    },              // Icall2
-       { 5,   "IGRTR?",      "inc_chk",         1, 6, Zop_branch | Zop_indvar },  // Igrtr_P
-       { 6,   "IN?",         "jin",             1, 6, Zop_branch  },              // In_P
-       { 133, "INC",         "inc",             1, 6, Zop_indvar  },              // Inc
-       { 246, "INPUT",       "read_char",       4, 6, Zop_store   },              // Input
-       { 247, "INTBL?",      "scan_table",      4, 6, Zop_store | Zop_branch },   // Intbl_P
-       { 266, "IRESTORE",    "restore_undo",    5, 6, Zop_store   },              // Irestore
-       { 265, "ISAVE",       "save_undo",       5, 6, Zop_store   },              // Isave
-       { 250, "IXCALL",      "call_vn2",        5, 6, Zop_extra | Zop_call },     // Ixcall
-       { 140, "JUMP",        "jump",            1, 6, Zop_label | Zop_term },     // Jump
-       { 2,   "LESS?",       "jl",              1, 6, Zop_branch  },              // Less_P
-       { 251, "LEX",         "tokenise",        5, 6, 0           },              // Lex
-       { 131, "LOC",         "get_parent",      1, 6, Zop_store   },              // Loc
-       { 264, "MARGIN",      "set_margins",     6, 6, 0           },              // Margin
-       { 283, "MENU",        "make_menu",       6, 6, Zop_branch  },              // Menu
-       { 24,  "MOD",         "mod",             1, 6, Zop_store   },              // Mod
-       { 278, "MOUSE-INFO",  "read_mouse",      6, 6, 0           },              // MouseInfo
-       { 279, "MOUSE-LIMIT", "mouse_window",    6, 6, 0           },              // MouseLimit
-       { 14,  "MOVE",        "insert_obj",      1, 6, 0           },              // Move
-       { 22,  "MUL",         "mul",             1, 6, Zop_store   },              // Mul
-       { 129, "NEXT?",       "get_sibling",     1, 6, Zop_store | Zop_branch },   // Next_P
-       { 19,  "NEXTP",       "get_next_prop",   1, 6, Zop_store   },              // Nextp
-       { 180, "NOOP",        "nop",             1, 6, 0           },              // Noop
-       { 191, "ORIGINAL?",   "piracy",          5, 6, Zop_branch  },              // Original_P
-       { 262, "PICINF",      "picture_data",    6, 6, Zop_branch  },              // Picinf
-       { 284, "PICSET",      "picture_table",   6, 6, 0           },              // Picset
-       { 233, "POP",         "pull",            1, 5, 0           },              // Pop_v1
-       { 233, "POP",         "pull",            6, 6, Zop_store   },              // Pop_v6
-       { 141, "PRINT",       "print_paddr",     1, 6, 0           },              // Print
-       { 135, "PRINTB",      "print_addr",      1, 6, 0           },              // Printb
-       { 229, "PRINTC",      "print_char",      1, 6, 0           },              // Printc
-       { 138, "PRINTD",      "print_obj",       1, 6, 0           },              // Printd
-       { 282, "PRINTF",      "print_form",      6, 6, 0           },              // Printf
-       { 178, "PRINTI",      "print",           1, 6, Zop_string  },              // Printi
-//     { 267, "PRINTMOVE",   "PRINTMOVE",       5, 6, Zop_store   },              // Printmove
-       { 230, "PRINTN",      "print_num",       1, 6, 0           },              // Printn
-       { 179, "PRINTR",      "print_ret",       1, 6, Zop_string | Zop_term },    // Printr
-       { 254, "PRINTT",      "print_table",     5, 6, 0           },              // Printt
-       { 267, "PRINTU",      "print_unicode",   5, 6, 0           },              // Printu
-       { 132, "PTSIZE",      "get_prop_len",    1, 6, Zop_store   },              // Ptsize
-       { 232, "PUSH",        "push",            1, 6, 0           },              // Push
-       { 225, "PUT",         "storew",          1, 6, 0           },              // Put
-       { 226, "PUTB",        "storeb",          1, 6, 0           },              // Putb
-       { 227, "PUTP",        "put_prop",        1, 6, 0           },              // Putp
-       { 186, "QUIT",        "quit",            1, 6, Zop_term    },              // Quit
-       { 231, "RANDOM",      "random",          1, 6, Zop_store   },              // Random
-       { 228, "READ",        "sread",           1, 4, 0           },              // Read_v1
-       { 228, "READ",        "aread",           5, 6, Zop_store   },              // Read_v5
-       { 137, "REMOVE",      "remove_obj",      1, 6, 0           },              // Remove
-       { 183, "RESTART",     "restart",         1, 6, Zop_term    },              // Restart
-       { 182, "RESTORE",     "restore",         1, 3, Zop_branch  },              // Restore_v1
-       { 182, "RESTORE",     "restore",         4, 4, Zop_store   },              // Restore_v4
-       { 257, "RESTORE",     "restore",         5, 6, Zop_store   },              // Restore_V5
-       { 139, "RETURN",      "ret",             1, 6, Zop_term    },              // Return
-       { 177, "RFALSE",      "rfalse",          1, 6, Zop_term    },              // Rfalse
-       { 184, "RSTACK",      "ret_popped",      1, 6, Zop_term    },              // Rstack
-//     { 268, "RTIME",       "RTIME",           5, 6, Zop_store   },              // Rtime
-       { 176, "RTRUE",       "rtrue",           1, 6, Zop_term    },              // Rtrue
-       { 181, "SAVE",        "save",            1, 3, Zop_branch  },              // Save_v1
-       { 181, "SAVE",        "save",            4, 4, Zop_store   },              // Save_v4
-       { 256, "SAVE",        "save",            5, 6, Zop_store   },              // Save_V5
-       { 235, "SCREEN",      "set_window",      3, 6, 0           },              // Screen
-       { 276, "SCROLL",      "scroll_window",   6, 6, 0           },              // Scroll
-//     { 269, "SEND",        "SEND",            5, 6, Zop_store   },              // Send
-       { 270, "SERVER",      "SERVER",          5, 6, Zop_store   },              // Server
-       { 13,  "SET",         "store",           1, 6, Zop_indvar  },              // Set
-       { 258, "SHIFT",       "log_shift",       5, 6, Zop_store   },              // Shift
-       { 245, "SOUND",       "sound_effect",    3, 6, 0           },              // Sound
-       { 234, "SPLIT",       "split_window",    3, 6, 0           },              // Split
-       { 21,  "SUB",         "sub",             1, 6, Zop_store   },              // Sub
-       { 28,  "THROW",       "throw",           5, 6, Zop_term    },              // Throw
-       { 188, "USL",         "show_status",     1, 3, 0           },              // Usl
-       { 142, "VALUE",       "load",            1, 6, Zop_store | Zop_indvar },   // Value
-       { 189, "VERIFY",      "verify",          3, 6, Zop_branch  },              // Verify
-       { 274, "WINATTR",     "window_style",    6, 6, 0           },              // Winattr
-       { 275, "WINGET",      "get_wind_prop",   6, 6, Zop_store   },              // Winget
-       { 272, "WINPOS",      "move_window",     6, 6, 0           },              // Winpos
-       { 281, "WINPUT",      "put_wind_prop",   6, 6, 0           },              // Winput
-       { 273, "WINSIZE",     "window_size",     6, 6, 0           },              // Winsize
-       { 236, "XCALL",       "call_vs2",        4, 6, Zop_store | Zop_extra | Zop_call }, // Xcall
-       { 280, "XPUSH",       "push_stack",      6, 6, Zop_branch  },              // Xpush
-       { 128, "ZERO?",       "jz",              1, 6, Zop_branch  },              // Zero_P
-       { 252, "ZWSTR",       "encode_text",     5, 6, 0           }               // Zwstr
+  {Opcode_ADD, "ADD", "add", 1, 6, Zop_store}, // Add
+  {Opcode_ASHIFT, "ASHIFT", "art_shift", 5, 6, Zop_store},     // Ashift
+  {Opcode_ASSIGNED, "ASSIGNED?", "check_arg_count", 5, 6, Zop_branch | Zop_indvar},    // Assigned_P
+  {Opcode_BAND, "BAND", "and", 1, 6, Zop_store},       // Band
+  {143, "BCOM", "not", 1, 4, Zop_store},       // Bcom_V1
+  {248, "BCOM", "not", 5, 6, Zop_store},       // Bcom_V5
+  {8, "BOR", "or", 1, 6, Zop_store},   // Bor
+  {7, "BTST", "test", 1, 6, Zop_branch},       // Btst
+  {242, "BUFOUT", "buffer_mode", 4, 6, 0},     // Bufout
+  {224, "CALL", "call_vs", 1, 6, Zop_store | Zop_call},        // Call
+  {136, "CALL1", "call_1s", 4, 6, Zop_store | Zop_call},       // Call1
+  {25, "CALL2", "call_2s", 4, 6, Zop_store | Zop_call},        // Call2
+  {185, "CATCH", "catch", 5, 6, Zop_store},    // Catch
+  {268, "CHECKU", "check_unicode", 5, 6, Zop_store},   // Checku
+  {237, "CLEAR", "erase_window", 4, 6, 0},     // Clear
+  {27, "COLOR", "set_colour", 5, 5, 0},        // Color_v5
+  {27, "COLOR", "set_colour", 6, 6, Zop_varargs},      // Color_v6
+  {253, "COPYT", "copy_table", 5, 6, 0},       // Copyt
+  {187, "CRLF", "new_line", 1, 6, 0},  // Crlf
+  {240, "CURGET", "get_cursor", 4, 6, 0},      // Curget
+  {239, "CURSET", "set_cursor", 4, 6, 0},      // Curset
+  {263, "DCLEAR", "erase_picture", 6, 6, 0},   // Dclear
+  {134, "DEC", "dec", 1, 6, Zop_indvar},       // Dec
+  {244, "DIRIN", "input_stream", 3, 6, 0},     // Dir-In
+  {243, "DIROUT", "output_stream", 3, 6, 0},   // Dir-Out
+  {261, "DISPLAY", "draw_picture", 6, 6, 0},   // Display
+  {23, "DIV", "div", 1, 6, Zop_store}, // Div
+  {4, "DLESS?", "dec_chk", 1, 6, Zop_branch | Zop_indvar},     // Dless_P
+//      { 271, "ENDMOVE",     "ENDMOVE",         5, 6, Zop_store   },              // Endmove = 271
+  {1, "EQUAL?", "jeq", 1, 6, Zop_branch | Zop_varargs},        // Equal_P
+  {238, "ERASE", "erase_line", 4, 6, 0},       // Erase
+  {12, "FCLEAR", "clear_attr", 1, 6, 0},       // Fclear
+  {130, "FIRST?", "get_child", 1, 6, Zop_store | Zop_branch},  // First_P
+  {260, "FONT", "set_font", 5, 6, Zop_store},  // Font
+  {11, "FSET", "set_attr", 1, 6, 0},   // Fset
+  {10, "FSET?", "test_attr", 1, 6, Zop_branch},        // Fset_P
+  {185, "FSTACK", "pop", 1, 4, 0},     // Fstack_V1
+  {277, "FSTACK", "pop_stack", 6, 6, 0},       // Fstack_V6
+  {15, "GET", "loadw", 1, 6, Zop_store},       // Get
+  {16, "GETB", "loadb", 1, 6, Zop_store},      // Getb
+  {17, "GETP", "get_prop", 1, 6, Zop_store},   // Getp
+  {18, "GETPT", "get_prop_addr", 1, 6, Zop_store},     // Getpt
+  {3, "GRTR?", "jg", 1, 6, Zop_branch},        // Grtr_P
+  {241, "HLIGHT", "set_text_style", 4, 6, 0},  // Hlight
+  {249, "ICALL", "call_vn", 5, 6, Zop_call},   // Icall
+  {143, "ICALL1", "call_1n", 5, 6, Zop_call},  // Icall1
+  {26, "ICALL2", "call_2n", 5, 6, Zop_call},   // Icall2
+  {5, "IGRTR?", "inc_chk", 1, 6, Zop_branch | Zop_indvar},     // Igrtr_P
+  {6, "IN?", "jin", 1, 6, Zop_branch}, // In_P
+  {133, "INC", "inc", 1, 6, Zop_indvar},       // Inc
+  {246, "INPUT", "read_char", 4, 6, Zop_store},        // Input
+  {247, "INTBL?", "scan_table", 4, 6, Zop_store | Zop_branch}, // Intbl_P
+  {266, "IRESTORE", "restore_undo", 5, 6, Zop_store},  // Irestore
+  {265, "ISAVE", "save_undo", 5, 6, Zop_store},        // Isave
+  {250, "IXCALL", "call_vn2", 5, 6, Zop_extra | Zop_call},     // Ixcall
+  {140, "JUMP", "jump", 1, 6, Zop_label | Zop_term},   // Jump
+  {2, "LESS?", "jl", 1, 6, Zop_branch},        // Less_P
+  {251, "LEX", "tokenise", 5, 6, 0},   // Lex
+  {131, "LOC", "get_parent", 1, 6, Zop_store}, // Loc
+  {264, "MARGIN", "set_margins", 6, 6, 0},     // Margin
+  {283, "MENU", "make_menu", 6, 6, Zop_branch},        // Menu
+  {24, "MOD", "mod", 1, 6, Zop_store}, // Mod
+  {278, "MOUSE-INFO", "read_mouse", 6, 6, 0},  // MouseInfo
+  {279, "MOUSE-LIMIT", "mouse_window", 6, 6, 0},       // MouseLimit
+  {14, "MOVE", "insert_obj", 1, 6, 0}, // Move
+  {22, "MUL", "mul", 1, 6, Zop_store}, // Mul
+  {129, "NEXT?", "get_sibling", 1, 6, Zop_store | Zop_branch}, // Next_P
+  {19, "NEXTP", "get_next_prop", 1, 6, Zop_store},     // Nextp
+  {180, "NOOP", "nop", 1, 6, 0},       // Noop
+  {191, "ORIGINAL?", "piracy", 5, 6, Zop_branch},      // Original_P
+  {262, "PICINF", "picture_data", 6, 6, Zop_branch},   // Picinf
+  {284, "PICSET", "picture_table", 6, 6, 0},   // Picset
+  {233, "POP", "pull", 1, 5, 0},       // Pop_v1
+  {233, "POP", "pull", 6, 6, Zop_store},       // Pop_v6
+  {Opcode_PRINT, "PRINT", "print_paddr", 1, 6, 0},     // Print
+  {135, "PRINTB", "print_addr", 1, 6, 0},      // Printb
+  {229, "PRINTC", "print_char", 1, 6, 0},      // Printc
+  {138, "PRINTD", "print_obj", 1, 6, 0},       // Printd
+  {282, "PRINTF", "print_form", 6, 6, 0},      // Printf
+  {Opcode_PRINTI, "PRINTI", "print", 1, 6, Zop_string},        // Printi
+//      { 267, "PRINTMOVE",   "PRINTMOVE",       5, 6, Zop_store   },              // Printmove
+  {230, "PRINTN", "print_num", 1, 6, 0},       // Printn
+  {Opcode_PRINTR, "PRINTR", "print_ret", 1, 6, Zop_string | Zop_term}, // Printr
+  {254, "PRINTT", "print_table", 5, 6, 0},     // Printt
+  {267, "PRINTU", "print_unicode", 5, 6, 0},   // Printu
+  {132, "PTSIZE", "get_prop_len", 1, 6, Zop_store},    // Ptsize
+  {232, "PUSH", "push", 1, 6, 0},      // Push
+  {225, "PUT", "storew", 1, 6, 0},     // Put
+  {226, "PUTB", "storeb", 1, 6, 0},    // Putb
+  {227, "PUTP", "put_prop", 1, 6, 0},  // Putp
+  {Opcode_QUIT, "QUIT", "quit", 1, 6, Zop_term},       // Quit
+  {231, "RANDOM", "random", 1, 6, Zop_store},  // Random
+  {228, "READ", "sread", 1, 4, 0},     // Read_v1
+  {228, "READ", "aread", 5, 6, Zop_store},     // Read_v5
+  {137, "REMOVE", "remove_obj", 1, 6, 0},      // Remove
+  {183, "RESTART", "restart", 1, 6, Zop_term}, // Restart
+  {182, "RESTORE", "restore", 1, 3, Zop_branch},       // Restore_v1
+  {182, "RESTORE", "restore", 4, 4, Zop_store},        // Restore_v4
+  {257, "RESTORE", "restore", 5, 6, Zop_store},        // Restore_V5
+  {139, "RETURN", "ret", 1, 6, Zop_term},      // Return
+  {177, "RFALSE", "rfalse", 1, 6, Zop_term},   // Rfalse
+  {184, "RSTACK", "ret_popped", 1, 6, Zop_term},       // Rstack
+//      { 268, "RTIME",       "RTIME",           5, 6, Zop_store   },              // Rtime
+  {Opcode_RTRUE, "RTRUE", "rtrue", 1, 6, Zop_term},    // Rtrue
+  {181, "SAVE", "save", 1, 3, Zop_branch},     // Save_v1
+  {181, "SAVE", "save", 4, 4, Zop_store},      // Save_v4
+  {256, "SAVE", "save", 5, 6, Zop_store},      // Save_V5
+  {235, "SCREEN", "set_window", 3, 6, Zop_none},       // Screen
+  {276, "SCROLL", "scroll_window", 6, 6, Zop_none},    // Scroll
+//      { 269, "SEND",        "SEND",            5, 6, Zop_store   },              // Send
+  {270, "SERVER", "SERVER", 5, 6, Zop_store},  // Server
+  {13, "SET", "store", 1, 6, Zop_indvar},      // Set
+  {258, "SHIFT", "log_shift", 5, 6, Zop_store},        // Shift
+  {245, "SOUND", "sound_effect", 3, 6, 0},     // Sound
+  {234, "SPLIT", "split_window", 3, 6, 0},     // Split
+  {21, "SUB", "sub", 1, 6, Zop_store}, // Sub
+  {28, "THROW", "throw", 5, 6, Zop_term},      // Throw
+  {188, "USL", "show_status", 1, 3, 0},        // Usl
+  {142, "VALUE", "load", 1, 6, Zop_store | Zop_indvar},        // Value
+  {189, "VERIFY", "verify", 3, 6, Zop_branch}, // Verify
+  {274, "WINATTR", "window_style", 6, 6, 0},   // Winattr
+  {275, "WINGET", "get_wind_prop", 6, 6, Zop_store},   // Winget
+  {272, "WINPOS", "move_window", 6, 6, 0},     // Winpos
+  {281, "WINPUT", "put_wind_prop", 6, 6, 0},   // Winput
+  {273, "WINSIZE", "window_size", 6, 6, 0},    // Winsize
+  {236, "XCALL", "call_vs2", 4, 6, Zop_store | Zop_extra | Zop_call},  // Xcall
+  {280, "XPUSH", "push_stack", 6, 6, Zop_branch},      // Xpush
+  {128, "ZERO?", "jz", 1, 6, Zop_branch},      // Zero_P
+  {252, "ZWSTR", "encode_text", 5, 6, Zop_none}        // Zwstr
 };
 
 Symtable *Opcodes;
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
 
-void init_opcodes(int version, int inform_syntax)
+void
+init_opcodes (int version, int inform_syntax)
 {
-       const unsigned maxnamelen = 16;
-       int n;
-       if (Opcodes) symtable_destroy(Opcodes); 
-       Opcodes = symtable_create(2 * ARRAY_SIZE(detailed_opcodes), maxnamelen, sizeof(ZOpcode));
-       assert(Opcodes);
-       for(n = 0; n < ARRAY_SIZE(detailed_opcodes); n++) {
-               Opcode_detailed_info *p = &detailed_opcodes[n];
-               if (version < p->minver) continue;
-               if (version > p->maxver) continue;
-               ZOpcode q = { p->opcode, p->flags };
-               symtable_add(Opcodes, inform_syntax ? p->inform_name : p->classic_name, &q);
-       }
+  const unsigned maxnamelen = 16;
+  int n;
+  if (Opcodes)
+    symtable_destroy (Opcodes);
+  Opcodes =
+    symtable_create (2 * ARRAY_SIZE (detailed_opcodes), maxnamelen,
+                    sizeof (ZOpcode));
+  assert (Opcodes);
+  for (n = 0; n < ARRAY_SIZE (detailed_opcodes); n++)
+    {
+      Opcode_detailed_info *p = &detailed_opcodes[n];
+      if (version < p->minver)
+       continue;
+      if (version > p->maxver)
+       continue;
+      ZOpcode q = { p->opcode, p->flags };
+      symtable_add (Opcodes, inform_syntax ? p->inform_name : p->classic_name,
+                   &q);
+    }
 }
index 21e8ac0d0c9140eb45feb57b00ecf2673093a7d8..95a0f4fabdf1ff1ed5ae23632958fdf71e7a673a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * opcodes.h -- part of ZilUtils/ZilAsm
  *
- * Copyright (C) 2016 Jason Self <j@jxself.org>
+ * Copyright (C) 2016, 2019, 2020 Jason Self <j@jxself.org>
  *
  * Based on ZILF (c) 2010, 2015 Jesse McGrew
  *
 
 #include "symtable.h"
 
-typedef enum {
-       Zop_none    =   0,
-       Zop_store   =   1,   // ..stores a result
-       Zop_branch  =   2,   // ..branches to a label
-       Zop_extra   =   4,   // ..takes an extra operand type byte, for a total of 8 possible operands
-       Zop_varargs =   8,   // ..is nominally 2OP but can take up to 4 operands
-       Zop_string  =  16,   // ..has a string literal operand
-       Zop_label   =  32,   // ..can take a local label operand
-       Zop_indvar  =  64,   // ..first operand is an indirect variable number
-       Zop_call    = 128,   // ..first operand is a packed routine address
-       Zop_term    = 256    // ..control flow does not pass to the following instruction
+typedef enum
+{
+  Zop_none = 0,
+  Zop_store = 1,               // ..stores a result
+  Zop_branch = 2,              // ..branches to a label
+  Zop_extra = 4,               // ..takes an extra operand type byte, for a total of 8 possible operands
+  Zop_varargs = 8,             // ..is nominally 2OP but can take up to 4 operands
+  Zop_string = 16,             // ..has a string literal operand
+  Zop_label = 32,              // ..can take a local label operand
+  Zop_indvar = 64,             // ..first operand is an indirect variable number
+  Zop_call = 128,              // ..first operand is a packed routine address
+  Zop_term = 256               // ..control flow does not pass to the following instruction
 } ZOpcode_flags;
 
-typedef struct {
-       unsigned opcode;
-       ZOpcode_flags flags;
+typedef struct
+{
+  unsigned opcode;
+  ZOpcode_flags flags;
 } ZOpcode;
 
 extern Symtable *Opcodes;
 
-void init_opcodes(int version, int inform_syntax);
+void init_opcodes (int version, int inform_syntax);
 
-#endif  /* ifndef ZILASM_OPCODES */
+enum Opcodes
+{
+  Opcode_ADD = 20,
+  Opcode_ASHIFT = 259,
+  Opcode_ASSIGNED = 255,
+  Opcode_BAND = 9,
+  Opcode_CRLF = 187,
+  Opcode_ICALL1 = 143,
+  Opcode_ICALL2 = 26,
+  Opcode_PRINT = 141,
+  Opcode_PRINTI = 178,
+  Opcode_PRINTR = 179,
+  Opcode_QUIT = 186,
+  Opcode_RTRUE = 176
+};
+
+
+#endif /* ifndef ZILASM_OPCODES */
diff --git a/zilasm/parser.c b/zilasm/parser.c
deleted file mode 100644 (file)
index 81713cc..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * parser.c -- part of ZilUtils/ZilAsm
- *
- * Copyright (C) 2016, 2019 Jason Self <j@jxself.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-#include <stdio.h>   /* fopen, fgets */
-#include <string.h>  /* strlen */
-
-#include "parser.h"
-#include "directives.h"
-#include "opcodes.h"
-#include "labels.h"
-
-#define iscomment(c)   ((c) == '#')
-#define isbindigit(c)  ((c) == '0' || (c) == '1')
-
-/* !!! TODO !!! */
-#define fatal_error(errmsg)
-#define PC NULL
-
-void checksep(const char *p)
-{
-       if (!*p || iscomment(*p) || isspace(*p)) return;
-       fatal_error("wrong chars");
-}
-
-const char *pass_spaces(const char *p)
-{
-       while(p && isspace(*p)) p++;
-       return (p && *p) ? p : NULL;
-}
-
-const char *pass_alnums(const char *p)
-{
-       while(p && isalnum(*p)) p++;
-       return (p && *p) ? p : NULL;
-}
-
-int tryparse_directive(const char *p)
-{
-       if (*p != '.')
-               return 0;
-       const char *a = p+1;
-       const char *b = pass_alnums(a);
-       checksep(b);
-       Directive_handler f = directive_lookup(a, b - a);
-       if (!f) return 0;
-       return (*f)(b);
-}
-
-int tryparse_assignment(const char *a, const char *b, const char *c)
-{
-       return 0;
-}
-
-int tryparse_label(const char *a, const char *b, const char *c)
-{
-       if (*(c+1) != ':') {
-               symtable_add2(Local_labels, a, b - a, PC);
-       } else if (*(c+2) != ':') {
-               symtable_add2(Global_labels, a, b - a, PC);
-       } else {
-               fatal_error("wrong label type");
-       }
-
-       while (*c++ == ':');
-       if (*c && ((c = pass_spaces(c)) != NULL) && *c)
-               return tryparse_instruction(c);
-       return 1;
-}
-
-int tryparse_name(const char *a)
-{
-       const char *b = pass_alnums(a);
-       const char *c = pass_spaces(b);
-
-       if (!c)        return 0;
-       if (*c == '=') return tryparse_assignment(a, b, c + 1);
-       if (*c == ':') return tryparse_label(a, b, c);
-       return 0;
-}
-
-int tryparse_instruction(const char *a)
-{
-       const char *b = pass_alnums(a);
-       ZOpcode *op = symtable_lookup2(Opcodes, a, b - a);
-       if (!op) return 0;
-       ZOpcode_flags flags = op->flags;
-       /* !!! TODO !!! */
-       return 0;
-}
-
-/*
- *  Line can be one from: Comment, Global label, Local label, Directive, Name=Value, Instruction
- */
-int parse_line(const char *p)
-{
-       for (; *p; p++) {
-               char c = *p;
-               int n;
-               if (isspace(c))                  continue;
-               if (iscomment(c))                return 0;
-               if (n = tryparse_directive(p))   return n;
-               if (n = tryparse_name(p))        return n;  // ..label or assignment
-               if (n = tryparse_instruction(p)) return n;
-               fatal_error("wrong line");
-       }
-       return 0;
-}
-
-#define MAX_LINESIZE 1024
-
-int parse_file(const char *filename)
-{
-       FILE *fp = fopen(filename, "r");
-       if (!fp) fatal_error("wrong file");
-
-        //const int MAX_LINESIZE = 1024;
-       char line[MAX_LINESIZE];
-       int newline_missing = 0;
-
-       while (fgets(line, MAX_LINESIZE, fp)) {
-               if (newline_missing) fatal_error("line too long");
-
-               int n = strlen(line);
-               if (!n) continue;
-
-               parse_line(line);
-
-               newline_missing = (line[n-1] != '\n');
-       }
-
-       close(fp);
-}
-
-/*
-
-line_passed() {
-    skip_spaces();
-    return (current_token == LINE_END || current_token == LINE_COMMENT);
-}
-
-if (line_passed()) continue;
-if (current_token == DIRECTIVE) {
-    if (!try_next_token(NAME))
-        fatal_error("directive contains incorrect chars")
-    handler = get_directive_handler(current_token);
-    if (!handler)
-        fatal error("unknown directive");
-    (*handler)(remaining_line);
-    if (line_passed()) continue;
-    fatal_error("unexpected line tail");
-} else if (current_token == NAME) {
-    skip_spaces();
-    if (current_token == ASSIGNMENT)
-}
-    
-
-*/
diff --git a/zilasm/parser.cpp b/zilasm/parser.cpp
new file mode 100644 (file)
index 0000000..1ea4aa7
--- /dev/null
@@ -0,0 +1,533 @@
+/*
+ * parser.c -- part of ZilUtils/ZilAsm
+ *
+ * Copyright (C) 2016, 2019, 2020 Jason Self <j@jxself.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include "include_all.h"
+
+
+#define iscomment(c)   ((c) == ';')
+#define isbindigit(c)  ((c) == '0' || (c) == '1')
+
+/* !!! TODO !!! */
+//#define fatal_error(errmsg) printf(errmsg)
+#define PC NULL
+
+
+
+stack<Parsing_Context> g_parsing_contexts;
+
+
+void
+CParser::add_function(const char *s)
+{
+       string name = "";
+       s = pass_spaces(s);
+       while (*s != 0 && *s != ' ' && *s != '\n')
+       {
+               name += *s;
+               s++;
+       }
+       
+       unsigned memory_for_function = 1;
+       unsigned alignment = 0;
+       if (m_current_address & 3)
+       {
+               alignment = 4 - (m_current_address & 3);
+               memory_for_function += alignment;
+       }
+       
+       g_codes[g_number_of_instructions] = zmem_init(memory_for_function);
+       for ( int i = 0; i < memory_for_function; ++i)
+               zmem_putbyte(g_codes[g_number_of_instructions], 0);  // output number of local variables
+       
+
+       m_function_addresses.push_back(m_current_address + alignment);
+       Function f;
+       f.address = m_current_address + alignment;
+       f.index = g_number_of_instructions;
+       m_functions.insert(make_pair(name, f)); /// add key pair: function name and current instruction index
+
+       m_current_address += memory_for_function;
+       ++g_number_of_instructions;
+}
+
+
+string
+CParser::build_error_message(const char *message)
+{
+       char buff[300];
+       sprintf(buff, "error at %s%s line %d: %s", g_parsing_contexts.top().current_directory.c_str(),
+               g_parsing_contexts.top().current_file_name.c_str(), m_current_line_number, message);
+       return string(buff);
+}
+
+
+void
+CParser::fatal_error(const char *errmsg)
+{
+       printf( "%s\n", errmsg);
+       g_haveErrors = true;
+}
+
+
+
+void
+CParser::checksep (const char *p)
+{
+  if (!*p || iscomment (*p) || isspace (*p))
+    return;
+  fatal_error (build_error_message ("wrong chars").c_str());
+}
+
+
+const char *
+CParser::pass_spaces (const char *p)
+{
+  while (p && isspace (*p))
+    p++;
+  return (p && *p) ? p : NULL;
+}
+
+
+const char *
+pass_alnums (const char *p)
+{
+  while (p && isalnum (*p))
+    p++;
+  //return (p && *p) ? p : NULL;
+  return p;
+}
+
+
+int
+CParser::tryparse_directive (const char *p)
+{
+  if (*p != '.')
+    return 0;
+  const char *a = p + 1;
+  const char *b = pass_alnums (a);
+  checksep (b);
+  Directive_handler f = m_pdirectives->directive_lookup (a, b - a);
+  if (!f)
+    return 0;
+  return (b-a) + (*f) (b, this);
+}
+
+
+int
+CParser::tryparse_startup_directive(const char *p)
+{
+       const char *a = p;
+       string s = "%START::";
+       if (memcmp(p, s.c_str(), s.length()) == 0)
+       {
+               p += s.length();
+               while (isspace(*p))
+                       p++;
+               m_start_function_name = "";
+               while (isalnum(*p))
+                       m_start_function_name += *p++;
+
+       }
+
+       return p - a;
+}
+
+
+
+int
+tryparse_assignment (const char *a, const char *b, const char *c)
+{
+  return 0;
+}
+
+
+int
+CParser::tryparse_label (const char *a, const char *b, const char *c)
+{
+  if (*(c + 1) != ':')
+    {
+      symtable_add2 (Local_labels, a, b - a, PC);
+    }
+  else if (*(c + 2) != ':')
+    {
+      symtable_add2 (Global_labels, a, b - a, PC);
+    }
+  else
+    {
+      fatal_error (build_error_message("wrong label type").c_str());
+    }
+
+  while (*c++ == ':');
+  if (*c && ((c = pass_spaces (c)) != NULL) && *c)
+    return tryparse_instruction (c);
+  return 1;
+}
+
+
+int
+CParser::tryparse_name (const char *a)
+{
+  const char *b = pass_alnums (a);
+  const char *c = pass_spaces (b);
+
+  if (!c)
+    return 0;
+  if (*c == '=')
+    return tryparse_assignment (a, b, c + 1);
+  if (*c == ':')
+    return tryparse_label (a, b, c);
+  return 0;
+}
+
+
+int 
+CParser::read_instructions_parameter(char *a, string& str)
+{
+       int len = 0;
+       str = "";
+       char *p = (char *)pass_spaces(a);
+       if (*p == '\"')
+       {
+               p++;
+               while (*p != '\"')
+               {
+                       str += *p;
+                       ++p;
+               }
+               len = p - a;
+       }
+       return len;
+}
+
+
+int
+CParser::read_instructions_parameter2(char *a, string& str)
+{
+       int len = 0;
+       str = "";
+       char *p = (char *)pass_spaces(a);
+       str="";
+       
+       const char *b = pass_alnums(p);
+       str = string(p).substr(0, b - p);
+
+       len = b - a;
+       return len;
+}
+
+int
+CParser::tryparse_instruction (const char *a)
+{
+       bool display_error = false;
+       int len = 0;
+       const char *b = pass_alnums(a);
+       if (b != a)
+       {
+               string call_function_name = "";
+
+               len = b ? b - a : strlen(a);
+               ZOpcode *op = (ZOpcode *)symtable_lookup2(Opcodes, a, len);
+               if (op)
+               {
+                       ZOpcode_flags flags = op->flags;
+                       ZMemblock *mem_additional = NULL;
+
+                       switch (op->opcode)
+                       {
+                               case Opcode_CRLF:
+                               case Opcode_PRINT:
+                               case Opcode_QUIT:
+                               case Opcode_RTRUE:
+                                       break;
+
+                               case Opcode_PRINTI:
+                               case Opcode_PRINTR:
+                               {
+                                       string str;
+                                       len += read_instructions_parameter((char *)a + len, str);
+                                       if ( str.length())
+                                               mem_additional = String_table::encrypt_string(str.c_str(), NULL);
+                                       break;
+                               }
+                               case Opcode_ICALL1:
+                               {
+                                       len += read_instructions_parameter2((char *)a + len, call_function_name);
+                                       m_calls.push_back(call_function_name);
+                                       mem_additional = zmem_init(2);   // reserve two bytes of memory for the address
+                                       zmem_putbyte(mem_additional, 0); // and write there some two bytes, e.g. zeros
+                                       zmem_putbyte(mem_additional, 0);
+                               }
+                               break;
+                               default:
+                               {
+                                       display_error = true;
+                               }
+                       }
+
+                       if (display_error == false)
+                       {
+                               int instruction_size = 1;
+                               if (mem_additional)
+                                       instruction_size += mem_additional->used_size;
+
+                               g_codes[g_number_of_instructions] = zmem_init(instruction_size);
+                               zmem_putbyte(g_codes[g_number_of_instructions], op->opcode);
+                               m_current_address += instruction_size;
+                               if (mem_additional)
+                               {
+                                       for (int i = 0; i < mem_additional->used_size; ++i)
+                                               zmem_putbyte(g_codes[g_number_of_instructions],
+                                                       mem_additional->contents[i]);
+                                       zmem_destroy(mem_additional);
+                               }
+
+                               
+
+                               ++g_number_of_instructions;
+                               return len;
+                       }
+               }
+               else
+               {
+                       string message = "wrong line \"" + string(a) + string("\"");
+                       fatal_error(build_error_message(message.c_str()).c_str());
+               }
+       }
+
+       if (display_error)
+       {
+               char buff[300];
+               if (len == 0)
+                       len = strlen(a);
+               char *instrcution_name = (char *)malloc(len + 1);
+               memcpy(instrcution_name, a, len);
+               instrcution_name[len] = 0;
+               string message = "instruction " + string(instrcution_name) + string(" is not supported yet");
+               fatal_error(build_error_message(message.c_str()).c_str());
+               free(instrcution_name);
+       }
+
+       return strlen(a);
+}
+
+
+/*
+ *  Line can be one from: Comment, Global label, Local label, Directive, Name=Value, Instruction
+ */
+int
+CParser::parse_line (const char *p)
+{
+  for (; *p; p++)
+    {
+      char c = *p;
+      int n;
+      if (isspace (c))
+       continue;
+      if (iscomment (c))
+       return 0;
+         if (c == '%')
+         {
+                 if (n = tryparse_startup_directive(p))
+                         return n;
+         }
+
+
+      if (n = tryparse_directive (p))
+       return n;
+      if (n = tryparse_name (p))
+       return n;               // ..label or assignment
+      if (n = tryparse_instruction (p))
+       return n;
+      //fatal_error ("wrong line");
+    }
+  return 0;
+}
+
+#define MAX_LINESIZE 1024
+
+int
+CParser::parse_file ()
+{
+       if (g_parsing_contexts.size() > 0)
+       {
+               string filename = g_parsing_contexts.top().current_directory + g_parsing_contexts.top().current_file_name;
+
+               FILE *fp = fopen(filename.c_str(), "r");
+               if (fp)
+               {
+
+                       m_current_line_number = 0;
+
+                       //const int MAX_LINESIZE = 1024;
+                       char line[MAX_LINESIZE];
+                       int newline_missing = 0;
+
+                       while (g_stopParsing == 0 && fgets(line, MAX_LINESIZE, fp))
+                       {
+                               ++m_current_line_number;
+
+                               if (newline_missing)
+                                       fatal_error(build_error_message("line too long").c_str());
+
+                               int n = strlen(line);
+                               if (!n)
+                                       continue;
+
+                               parse_line(line);
+
+                               newline_missing = (line[n - 1] != '\n');
+                       }
+
+                       fclose(fp);
+               }
+               else
+               {
+                       string message = string("can't open file ") + filename;
+                       fatal_error(message.c_str());
+               }
+
+               g_parsing_contexts.pop();
+       }
+       return 0;
+}
+
+
+CParser::CParser() 
+{
+  g_number_of_instructions = 0;
+  m_current_line_number = 0;
+  m_current_address = 0;
+  g_haveErrors = false;
+  m_pdirectives = new CDirectives(this);
+}
+
+
+CParser::~CParser ()
+{
+       for (int i = 0; i < g_number_of_instructions; ++i)
+       {
+               zmem_destroy(g_codes[i]);
+       }
+       g_number_of_instructions = 0;
+       delete m_pdirectives;
+}
+
+
+ZMemblock **
+CParser::get_codes()
+{
+       return g_codes;
+}
+
+
+unsigned 
+CParser::get_number_of_instructions()
+{
+       return g_number_of_instructions;
+}
+
+
+bool 
+CParser::have_errors()
+{
+       return g_haveErrors;
+}
+
+
+void 
+CParser::calculate_function_addresses()
+{
+       //unsigned address = 0;
+       ////map<string, Function>::iterator function_iter = m_functions.begin();
+       //unsigned j = 0;
+
+       //
+       //for (int i = 0; i < get_number_of_instructions(); ++i)
+       //{
+       //      //if (function_iter == m_functions.end())
+       //      //{
+       //      //      break;
+       //      //}
+
+       //      if (m_function_addresses[j] == address)
+       //      {
+       //              if (address & 3)
+       //                      address += 4 - (address & 3);
+       //              
+
+       //              for (map<string, Function>::iterator function_iter = m_functions.begin(); function_iter != m_functions.end(); ++function_iter)
+       //              {
+       //                      if (function_iter->second.index == i)
+       //                      {
+       //                              function_iter->second.address = address;
+       //                              break;
+       //                      }
+       //      
+       //              }
+       //              m_function_addresses[j] = address;
+       //              ++j;
+       //      }
+       //      address += g_codes[i]->used_size;
+       //}
+}
+
+
+unsigned
+CParser::output_codes(ZMemblock *zmem_code)
+{
+       unsigned code_size = 0;
+       map<string, Function>::iterator function_iter = m_functions.begin();
+       unsigned address = 0;
+
+       unsigned calls_index = 0;
+       for (int i = 0; i < get_number_of_instructions(); ++i)
+       {
+               ////if ( parser.)
+               //if (function_iter != m_functions.end())
+               //{
+               //      if (function_iter->second.index == i)
+               //      {
+               //              /// write few bytes for alignment purposes
+               //              for (int j = 0; j < function_iter->second.address - address; ++j)
+               //                      zmem_putbyte(zmem_code, 0);
+               //      }
+               //}
+
+               // write actual addresses to calls
+               if (g_codes[i]->contents[0] == Opcode_ICALL1)
+               {
+                       //vector<unsigned>::iterator iter = find(m_function_addresses.begin(), m_function_addresses.end(), address);
+                       unsigned target_addr = m_functions.find(m_calls[calls_index])->second.address >> 2;
+                       g_codes[i]->contents[1] = (target_addr >> 8) & 255;
+                       g_codes[i]->contents[2] = target_addr & 255;
+                       ++calls_index;
+               }
+
+
+               for (int j = 0; j < g_codes[i]->used_size; ++j)
+               {
+                       zmem_putbyte(zmem_code, g_codes[i]->contents[j]);
+                       ++code_size;
+               }
+       }
+
+       return code_size;
+}
\ No newline at end of file
index c708f4d3bf75b5a3b0037b6d9a9eaafda1a3776d..e867439cc72561507a49ecc6e9197270781dd4a5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * parser.h -- part of ZilUtils/ZilAsm
  *
- * Copyright (C) 2016 Jason Self <j@jxself.org>
+ * Copyright (C) 2016, 2019, 2020 Jason Self <j@jxself.org>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
 #ifndef ZILASM_PARSER
 #define ZILASM_PARSER 1
 
-int parse_file(const char *filename);
 
-#endif  /* ifndef ZILASM_PARSER */
+struct Instruction
+{
+  Byte *pCodes;
+  int size;
+};
+
+#define MAX_NUMBER_OF_INSTRUCTIONS 65536
+
+struct Function
+{
+       Function() : index(0), address(0), number_of_local_variables(0)
+       {
+       }
+
+       unsigned index;
+       unsigned address;
+       unsigned number_of_local_variables;
+};
+
+
+class CParser
+{
+public:
+       CParser();
+       ~CParser();
+       void calculate_function_addresses();
+       unsigned get_number_of_instructions();
+       ZMemblock **get_codes();
+       bool have_errors();
+       unsigned output_codes(ZMemblock *zmem_code);
+       int     parse_file();
+       void add_function(const char *s);
+       unsigned m_current_line_number;
+       unsigned m_current_address;
+
+
+       map <string, Function> m_functions;
+       vector<unsigned> m_function_addresses;
+       string m_start_function_name;
+
+private:
+       unsigned g_number_of_instructions;// = 0;
+
+
+       ZMemblock(*g_codes[MAX_NUMBER_OF_INSTRUCTIONS]);
+       bool g_haveErrors;
+       CDirectives *m_pdirectives;
+       vector<string> m_calls; // contains functions names' if current instruction is call/icall or empty string otherwise
+
+       string build_error_message(const char *message);
+       void checksep(const char *p);
+       void fatal_error(const char *errmsg);
+       int parse_line(const char *p);
+       const char *pass_spaces(const char *p);
+       int     read_instructions_parameter(char *a, string& str);
+       int     read_instructions_parameter2(char *a, string& str);
+       int     tryparse_directive(const char *p);
+       int     tryparse_startup_directive(const char *p);
+
+       int     tryparse_name(const char *a);
+       int tryparse_label(const char *a, const char *b, const char *c);
+       int tryparse_instruction(const char *a);
+};
+
+//void init_parser ();
+
+//int parse_file();// const char *filename);
+
+//extern unsigned g_number_of_instructions;
+
+
+//extern ZMemblock (*g_codes[MAX_NUMBER_OF_INSTRUCTIONS]);
+
+struct Parsing_Context
+{
+       string current_directory;
+       string current_file_name;
+};
+
+extern stack<Parsing_Context> g_parsing_contexts;
+//extern unsigned g_currentLineNumber;
+//extern bool g_haveErrors;
+
+#endif /* ifndef ZILASM_PARSER */
diff --git a/zilasm/string_table.cpp b/zilasm/string_table.cpp
new file mode 100644 (file)
index 0000000..4e2233d
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * string_table.cpp -- part of ZilUtils/ZilAsm
+ *
+ * Copyright (C) 2019, 2020 Jason Self <j@jxself.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "header.h"
+#include "string_table.h"
+#include <string.h>
+extern "C"
+{
+#include <strings.h>
+}
+
+unsigned
+String_table::add_string_to_string_table (const char *str, ZMemblock * zmb)
+{
+  encrypt_string (str, zmb);
+  return 0;
+}
+
+
+ZMemblock *
+String_table::encrypt_string (const char *str, ZMemblock * zmb)
+{
+  if (!zmb)
+    zmb = zmem_init (strlen (str) * 3);
+
+  int currentCharSet = 0;
+  Byte currentByte = 0;
+  int index = 0;
+  Word w = 0;
+  int numberOfSymbolsInWord = 0;
+  while (index < (int) strlen (str))
+    {
+      char c = str[index];
+      if (c >= 'a' && c <= 'z')
+       {
+         switch (currentCharSet)
+           {
+           case 0:
+             break;
+           case 1:
+             write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 5);      // permanently changes to the zero charset
+             currentCharSet = 0;
+             break;
+           case 2:
+             write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 4);      // permanently changes to the zero charset
+             currentCharSet = 0;
+             break;
+           }
+         write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord,
+                                         c - 'a' + 6);
+       }
+      else if (c >= 'A' && c <= 'Z')
+       {
+         switch (currentCharSet)
+           {
+           case 0:
+             write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 4);      // temporarily changes to the zero charset
+             break;
+           case 1:
+             break;
+           case 2:
+             write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 4);      // permanently changes to the zero charset
+             currentCharSet = 0;
+             write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 4);      // temporarily changes to the first charset
+             break;
+           }
+         write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord,
+                                         c - 'A' + 6);
+
+       }
+      else if (c == ' ')
+       {
+                 write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 0);
+       }
+      else
+       {
+         char ar[] = "*0123456789.,!?_#'\"/\\-:()";
+         for (int i = 0; i < (int) strlen (ar); ++i)
+           {
+             if (ar[i] == c)
+               {
+                 c = i + 7;
+                 break;
+               }
+           }
+
+         switch (currentCharSet)
+           {
+           case 0:
+             write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 5);      // temporarily changes to the second charset
+             break;
+           case 1:
+             write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 5);      // permanently changes to the zero charset
+             currentCharSet = 0;
+             write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 5);      // temporarily changes to the second charset
+             break;
+           case 2:
+             break;
+           }
+         write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, c);
+       }
+
+      ++index;
+    }
+
+  if (numberOfSymbolsInWord != 0)
+    {
+      zmem_putbyte (zmb, (w >> 8) & 255);
+      zmem_putbyte (zmb, w & 255);
+      numberOfSymbolsInWord = 0;
+      w = 0;
+    }
+  
+  if ((zmb->contents[zmb->used_size - 1] & 31) == 0) // if the last symbol is a space or not filled
+         zmb->contents[zmb->used_size - 2] |= 0x80;     // then we mark this word as the last word
+  else
+  {
+         zmem_putbyte(zmb, 0x80);                       // otherwise we add one more empty word
+         zmem_putbyte(zmb, 0x0);                        // with 15-th bit set
+  }
+
+  return zmb;
+}
+
+void
+String_table::write_one_word_to_string_table (ZMemblock * zmb, Word * w,
+                                             int *numberOfSymbolsInWord,
+                                             Byte symbol)
+{
+  int shift = ((2 - *numberOfSymbolsInWord) * 5);
+  *w |= (symbol << shift);
+
+  (*numberOfSymbolsInWord)++;
+
+  if (*numberOfSymbolsInWord == 3)
+    {
+      zmem_putbyte (zmb, (*w >> 8) & 255);
+      zmem_putbyte (zmb, (*w) & 255);
+      *numberOfSymbolsInWord = 0;
+      (*w) = 0;
+    }
+}
diff --git a/zilasm/string_table.h b/zilasm/string_table.h
new file mode 100644 (file)
index 0000000..36fda87
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * string_table.h -- part of ZilUtils/ZilAsm
+ *
+ * Copyright (C) 2019 Jason Self <j@jxself.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#ifndef ZILASM_STRING_TABLE_
+#define ZILASM_STRING_TABLE_
+
+class String_table
+{
+public:
+  unsigned add_string_to_string_table (const char *str, ZMemblock * zmb);
+
+  static ZMemblock *encrypt_string (const char *str, ZMemblock * zmb);
+
+private:
+  static void write_one_word_to_string_table (ZMemblock * zmb, Word * w,
+                                             int *numberOfSymbolsInWord,
+                                             Byte symbol);
+};
+
+#endif
index 2c5735f93cebb003ce8241b4ae898c9bf7575bb8..a5ff791b864307b80df14bb9088b8097d621c6fe 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * symtable.c -- part of ZilUtils/ZilAsm
  *
- * Copyright (C) 2016 Jason Self <j@jxself.org>
+ * Copyright (C) 2016, 2019 Jason Self <j@jxself.org>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -20,6 +20,7 @@
  */
 
 #include <string.h>
+#include "strings.h"
 #include <stdlib.h>
 #include <assert.h>
 
 
 #define FIELD_SIZE(Typ,Field)  (sizeof(((Typ*)0)->Field))
 
-Symtable* symtable_create(unsigned elems_count, unsigned name_size, unsigned elem_size)
+Symtable *
+symtable_create (unsigned elems_count, unsigned name_size, unsigned elem_size)
 {
-       size_t n = elems_count * (name_size + elem_size) + sizeof(Symtable) - FIELD_SIZE(Symtable, contents);
-       Symtable *p = malloc(n);
-       assert(p);
-       bzero(p, n);
-       p->elems_count = elems_count;
-       p->name_size   = name_size;
-       p->elem_size   = elem_size;
-       return p;
+  //size_t n = elems_count * (name_size + elem_size) + sizeof(Symtable) - FIELD_SIZE(Symtable, contents);
+  //Symtable *p = malloc(n);
+
+  Symtable *p = (Symtable *) malloc (sizeof (Symtable));
+  assert (p);
+  size_t n = elems_count * sizeof (SymtableElem);
+  p->contents = (SymtableElem *) malloc (n);
+  bzero (p->contents, n);
+  p->elems_count = elems_count;
+  p->name_size = name_size;
+  p->elem_size = elem_size;
+  return p;
 }
 
-void symtable_destroy(Symtable *p)
+
+void
+symtable_destroy (Symtable * p)
 {
-       assert(p);
-       free(p);
+  assert (p);
+  for (int i = 0; i > p->elems_count; ++i)
+    {
+      free (p->contents[i].name);
+      free (p->contents[i].value);
+    }
+  free (p->contents);
+  free (p);
 }
 
-static unsigned name2pos(const Symtable *p, const char *name, unsigned namelen)
+
+static unsigned
+name2pos (const Symtable * p, const char *name, unsigned namelen)
 {
-       assert(p);
-       unsigned key = 0;
-       while(namelen--)
-               key = ((key << 1) | (*name++));
-       return key % p->elems_count;
+  assert (p);
+  unsigned key = 0;
+  while (namelen--)
+    key = ((key << 1) | (*name++));
+  return key % p->elems_count;
 }
 
-static char *getsym(const Symtable *p, unsigned pos)
+
+static SymtableElem *
+getsym (const Symtable * p, unsigned pos)
 {
-       //assert(p);   //already checked by caller
-       //assert(pos < p->elems_count);
-       return ((char*)p) + sizeof(Symtable) - FIELD_SIZE(Symtable, contents) + (pos * p->elem_size);
+  //assert(p);   //already checked by caller
+  //assert(pos < p->elems_count);
+  //return ((char*)p) + sizeof(Symtable) - FIELD_SIZE(Symtable, contents) + (pos * p->elem_size);
+  return &p->contents[pos];
 }
 
-void* symtable_lookup2(const Symtable *p, const char *name, unsigned namelen)
-{
-       assert(p);
-       assert(name);
-       assert(namelen > 0);
-       assert(namelen < p->name_size);
-
-       unsigned start = name2pos(p, name, namelen);
-       unsigned pos = start;
-
-       do {
-               char *s = getsym(p, pos);
-               if (!*s)
-                       return NULL;
-               if (!memcmp(name, s, namelen))
-                       return s + p->name_size;
-               if (++pos >= p->elems_count)
-                       pos = 0;
-       } while(pos != start);
 
+// searches for a element in the symbols table and returns its value
+void *
+symtable_lookup2 (const Symtable * p, const char *name, unsigned namelen)
+{
+  assert (p);
+  assert (name);
+  assert (namelen > 0);
+  assert (namelen < p->name_size);
+
+  unsigned start = name2pos (p, name, namelen);
+  unsigned pos = start;
+
+  do
+    {
+      SymtableElem *s = getsym (p, pos);
+      if (!s->name)
        return NULL;
+      if (!memcmp (name, s->name, namelen))
+       return s->value;
+      if (++pos >= p->elems_count)
+       pos = 0;
+    }
+  while (pos != start);
+
+  return NULL;
 }
 
-void* symtable_lookup(const Symtable *p, const char *name)
+
+void *
+symtable_lookup (const Symtable * p, const char *name)
 {
-       assert(name);
-       return symtable_lookup2(p, name, strlen(name));
+  assert (name);
+  return symtable_lookup2 (p, name, strlen (name));
 }
 
-void* symtable_add(Symtable *p, const char *name, void *contents)
+
+void *
+symtable_add (Symtable * p, const char *name, void *value)
 {
-       assert(name);
-       return symtable_add2(p, name, strlen(name), contents);
+  assert (name);
+  return symtable_add2 (p, name, strlen (name), value);
 }
 
-void* symtable_add2(Symtable *p, const char *name, unsigned namelen, void *contents)
+
+void *
+symtable_add2 (Symtable * p, const char *name, unsigned namelen, void *value)
 {
-       assert(p);
-       assert(name);
-       assert(namelen > 0 && namelen < p->name_size);
-       assert(contents);
-
-       unsigned start = name2pos(p, name, namelen);
-       unsigned pos = start;
-
-       do {
-               char *s = getsym(p, pos);
-               if (!*s) {
-                       memcpy(s, name, namelen + 1);
-                       s[namelen] = '\0';
-                       memcpy(s + p->name_size, contents, p->elem_size);
-                       return s + p->name_size;
-               }
-               if (!memcmp(name, s, namelen) && s[namelen] == '\0') {
-                       /* TODO!! report error */
-                       return NULL;  /* ..already added */
-               }
-               if (++pos >= p->elems_count)
-                       pos = 0;
-       } while(pos != start);
-
-       /* TODO!! report overflow */
-       return NULL;
-       /* TODO!!! */
+  assert (p);
+  assert (name);
+  assert (namelen > 0 && namelen < p->name_size);
+  assert (value);
+
+  unsigned start = name2pos (p, name, namelen);
+  unsigned pos = start;
+
+  do
+    {
+      SymtableElem *elem = getsym (p, pos);
+      if (!elem->name)
+       {
+         elem->name = (char *) malloc (namelen + 1);
+         memcpy (elem->name, name, namelen + 1);
+         elem->name[namelen] = '\0';
+         elem->value = malloc (p->elem_size);
+         memcpy (elem->value, value, p->elem_size);
+         return elem;
+       }
+      if (!memcmp (name, elem->name, namelen) && elem->name[namelen] == '\0')
+       {
+         /* TODO!! report error */
+         return NULL;          /* ..already added */
+       }
+      if (++pos >= p->elems_count)
+       pos = 0;
+    }
+  while (pos != start);
+
+  /* TODO!! report overflow */
+  return NULL;
+  /* TODO!!! */
 }
 
-static int sortfunc(const void *a, const void *b)
+
+static int
+sortfunc (const void *a, const void *b)
 {
-       const char *s1 = a;
-       const char *s2 = b;
-       if (!*s1 && !*s2) return  0;
-       if (!*s1)         return  1;
-       if (!*s2)         return -1;
-       return strcmp(s1, s2);
+  const char *s1 = (const char *) a;
+  const char *s2 = (const char *) b;
+  if (!*s1 && !*s2)
+    return 0;
+  if (!*s1)
+    return 1;
+  if (!*s2)
+    return -1;
+  return strcmp (s1, s2);
 }
 
-void symtable_sort(Symtable *p)
+
+void
+symtable_sort (Symtable * p)
 {
-       assert(p);
-       qsort(getsym(p, 0), p->elems_count, p->elem_size + p->name_size, sortfunc);
+  assert (p);
+  qsort (getsym (p, 0), p->elems_count, p->elem_size + p->name_size,
+        sortfunc);
 }
 
 /* END */
index bbb70843494120d40561216492026fb7a889956a..8903d8de0e1b6ff69e8243ec091bd071323fb01a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * symtable.h -- part of ZilUtils/ZilAsm
  *
- * Copyright (C) 2016 Jason Self <j@jxself.org>
+ * Copyright (C) 2016, 2019 Jason Self <j@jxself.org>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
 #ifndef ZILASM_SYMTABLE
 #define ZILASM_SYMTABLE 1
 
-typedef struct {
-       unsigned elems_count;
-       unsigned name_size;
-       unsigned elem_size;
-       char contents[1];
+
+typedef struct
+{
+  char *name;
+  void *value;
+
+} SymtableElem;
+
+typedef struct
+{
+  unsigned elems_count;
+  unsigned name_size;
+  unsigned elem_size;
+  //char* contents;
+  SymtableElem *contents;      // table of elements
 } Symtable;
 
-Symtable* symtable_create (unsigned elems_count, unsigned name_size, unsigned elem_size);
-void*     symtable_lookup (const Symtable*, const char *name);
-void*     symtable_lookup2(const Symtable*, const char *name, unsigned namelen);
-void*     symtable_add    (Symtable*, const char *name, void *contents);
-void*     symtable_add2   (Symtable*, const char *name, unsigned namelen, void *contents);
-void      symtable_sort   (Symtable*);
-void      symtable_destroy(Symtable*);
+Symtable *symtable_create (unsigned elems_count, unsigned name_size,
+                          unsigned elem_size);
+void *symtable_lookup (const Symtable *, const char *name);
+void *symtable_lookup2 (const Symtable *, const char *name, unsigned namelen);
+void *symtable_add (Symtable *, const char *name, void *contents);
+void *symtable_add2 (Symtable *, const char *name, unsigned namelen,
+                    void *contents);
+void symtable_sort (Symtable *);
+void symtable_destroy (Symtable *);
 
-#endif  /* ifndef ZILASM_SYMTABLE */
+#endif /* ifndef ZILASM_SYMTABLE */
index 623e52edfd520eb7351fe7483362f4292ab684cd..bfab79723d2a119d5d09fc76f7ca59fabd6ad01c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * zmem.c -- part of ZilUtils/ZilAsm
  *
- * Copyright (C) 2016 Jason Self <j@jxself.org>
+ * Copyright (C) 2016, 2019 Jason Self <j@jxself.org>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
  */
 
 #include <assert.h>
-#include <strings.h>  /* bzero */
-#include <stdlib.h>   /* malloc, free */
+#include <strings.h>           /* bzero */
+
+#include <stdlib.h>            /* malloc, free */
 
 #include "zmem.h"
 
-ZMemblock* zmem_init(unsigned maxsize)
+ZMemblock *
+zmem_init (unsigned maxsize)
 {
-       ZMemblock *zmb = malloc(sizeof(ZMemblock) + maxsize - 1);
-       assert(zmb);
-       zmb->allocated_size = maxsize;
-       zmb->used_size = 0;
-       bzero(&zmb->contents, maxsize);
-       return zmb;
+  ZMemblock *zmb = malloc (sizeof (ZMemblock) + maxsize - 1);
+  assert (zmb);
+  zmb->allocated_size = maxsize;
+  zmb->used_size = 0;
+  bzero (&zmb->contents, maxsize);
+  return zmb;
 }
 
-void zmem_destroy(ZMemblock *zmb)
+void
+zmem_destroy (ZMemblock * zmb)
 {
-       assert(zmb);
-       free(zmb);
+  assert (zmb);
+  free (zmb);
 }
 
-void zmem_putbyte(ZMemblock *zmb, unsigned char val)
+void
+zmem_putbyte (ZMemblock * zmb, unsigned char val)
 {
-       assert(zmb);
-       assert(zmb->used_size < zmb->allocated_size);
-       zmb->contents[zmb->used_size++] = val;
+  assert (zmb);
+  assert (zmb->used_size < zmb->allocated_size);
+  zmb->contents[zmb->used_size++] = val;
 }
index 640877008b509b2f40de2b931473f2c518980de6..49a9997f71d09ff6ca59dbad5eed396df790bb9d 100644 (file)
 #ifndef ZILASM_ZMEM
 #define ZILASM_ZMEM 1
 
-typedef struct {
-       unsigned allocated_size;
-       unsigned used_size;
-       unsigned char contents[1];
+typedef struct
+{
+  unsigned allocated_size;
+  unsigned used_size;
+  unsigned char contents[1];
 } ZMemblock;
 
-extern ZMemblock* zmem_init(unsigned maxsize);
-extern void       zmem_destroy(ZMemblock *zmb);
-extern void       zmem_putbyte(ZMemblock *zmb, unsigned char val);
+extern ZMemblock *zmem_init (unsigned maxsize);
+extern void zmem_destroy (ZMemblock * zmb);
+extern void zmem_putbyte (ZMemblock * zmb, unsigned char val);
 
-#endif  /* ifndef ZILASM_ZMEM */
+#endif /* ifndef ZILASM_ZMEM */