From 82b0f84ab797141758929d16894d42e12ef79af7 Mon Sep 17 00:00:00 2001 From: Jason Self Date: Thu, 23 May 2019 05:51:49 -0700 Subject: [PATCH] Updating to reflect the latest work --- zilasm/Makefile.am | 5 +- zilasm/configure.ac | 4 +- zilasm/directives.c | 217 +++++++++------- zilasm/directives.h | 11 +- zilasm/{header.c => header.cpp} | 43 ++-- zilasm/header.h | 229 +++++++++-------- zilasm/{labels.c => labels.cpp} | 28 +- zilasm/labels.h | 13 +- zilasm/main.c | 270 -------------------- zilasm/main.cpp | 435 ++++++++++++++++++++++++++++++++ zilasm/opcodes.c | 310 ++++++++++++----------- zilasm/opcodes.h | 50 ++-- zilasm/parser.c | 175 ------------- zilasm/parser.cpp | 313 +++++++++++++++++++++++ zilasm/parser.h | 20 +- zilasm/string_table.cpp | 155 ++++++++++++ zilasm/string_table.h | 38 +++ zilasm/symtable.c | 216 +++++++++------- zilasm/symtable.h | 40 ++- zilasm/zmem.c | 38 +-- zilasm/zmem.h | 17 +- 21 files changed, 1635 insertions(+), 992 deletions(-) rename zilasm/{header.c => header.cpp} (55%) rename zilasm/{labels.c => labels.cpp} (62%) delete mode 100644 zilasm/main.c create mode 100644 zilasm/main.cpp delete mode 100644 zilasm/parser.c create mode 100644 zilasm/parser.cpp create mode 100644 zilasm/string_table.cpp create mode 100644 zilasm/string_table.h diff --git a/zilasm/Makefile.am b/zilasm/Makefile.am index 5134797..5faa8ef 100644 --- a/zilasm/Makefile.am +++ b/zilasm/Makefile.am @@ -2,6 +2,7 @@ # Process this file with automake to produce Makefile.in. # # Copyright (C) 2015 Alexander Andrejevic +# Copyright (C) 2019 Jason Self # # 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 opcodes.c symtable.c header.cpp parser.cpp directives.c 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/configure.ac b/zilasm/configure.ac index 881332d..8e7bb47 100644 --- a/zilasm/configure.ac +++ b/zilasm/configure.ac @@ -2,6 +2,7 @@ # Process this file with autoconf to produce a configure script. # # Copyright (C) 2015 Alexander Andrejevic +# Copyright (C) 2019 Jason Self # # 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 index b5aaf1a..7c4eb19 100644 --- a/zilasm/directives.c +++ b/zilasm/directives.c @@ -19,177 +19,202 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -#include /* bsearch */ -#include /* strcmp */ +#include /* bsearch */ +#include /* strcmp */ #include "directives.h" #define ARRAY_SIZE(x) ((sizeof(x)) / (sizeof(x[0]))) -static int byte_handler(const char *args) +static int +byte_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int end_handler(const char *args) +static int +end_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int endi_handler(const char *args) +static int +endi_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int endt_handler(const char *args) +static int +endt_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int fstr_handler(const char *args) +static int +fstr_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int funct_handler(const char *args) +static int +funct_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int gstr_handler(const char *args) +static int +gstr_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int gvar_handler(const char *args) +static int +gvar_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int insert_handler(const char *args) +static int +insert_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int len_handler(const char *args) +static int +len_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int new_handler(const char *args) +static int +new_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int object_handler(const char *args) +static int +object_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int prop_handler(const char *args) +static int +prop_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int str_handler(const char *args) +static int +str_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int strl_handler(const char *args) +static int +strl_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int table_handler(const char *args) +static int +table_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int vocbeg_handler(const char *args) +static int +vocbeg_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int vocend_handler(const char *args) +static int +vocend_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int word_handler(const char *args) +static int +word_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! TODO !!! */ + return 0; } -static int zword_handler(const char *args) +static int +zword_handler (const char *args) { - /* !!! TODO !!! */ - return 0; + /* !!! 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 + "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; +typedef struct +{ + const char *contents; + unsigned length; } Name; -static int namecmp(const void *key, const void *elem) +static int +namecmp (const void *key, const void *elem) { - const Name *p = (Name *)key; - const Directive *d = (Directive*)elem; + const Name *p = (Name *) key; + const Directive *d = (Directive *) elem; - int len1 = p->length; - int len2 = strlen(d->name); + int len1 = p->length; + int len2 = strlen (d->name); - int rc = memcmp(p->contents, elem, len1 < len2 ? len1 : len2); - return rc ? rc : (len1 - len2); + int rc = memcmp (p->contents, elem, len1 < len2 ? len1 : len2); + return rc ? rc : (len1 - len2); } -Directive_handler directive_lookup(const char *name, unsigned namelen) +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; + 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.h b/zilasm/directives.h index 5b5982e..5988c0a 100644 --- a/zilasm/directives.h +++ b/zilasm/directives.h @@ -22,13 +22,14 @@ #ifndef ZILASM_DIRECTIVES #define ZILASM_DIRECTIVES 1 -typedef int (*Directive_handler)(const char *directive_args); +typedef int (*Directive_handler) (const char *directive_args); -typedef struct { - const char name[16]; - Directive_handler handler; +typedef struct +{ + const char name[16]; + Directive_handler handler; } Directive; -Directive_handler directive_lookup(const char *name, unsigned namelen); +Directive_handler directive_lookup (const char *name, unsigned namelen); #endif /* ifndef ZILASM_DIRECTIVES */ diff --git a/zilasm/header.c b/zilasm/header.cpp similarity index 55% rename from zilasm/header.c rename to zilasm/header.cpp index e5f350f..863c65e 100644 --- a/zilasm/header.c +++ b/zilasm/header.cpp @@ -19,7 +19,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -#include /* bzero */ +#include /* bzero */ #include #include @@ -29,33 +29,40 @@ Program_header_struct Program_header; const unsigned MAX_HEADER_LEN = 40; -void program_header_reset(unsigned zversion) +void +program_header_reset (unsigned zversion) { - bzero(&Program_header, sizeof(Program_header)); - Program_header.version = zversion; + bzero (&Program_header, sizeof (Program_header)); + Program_header.version = zversion; } -ZMemblock *program_header_build(void) +ZMemblock * +program_header_build (void) { - ZMemblock *zmb = zmem_init(MAX_HEADER_LEN); - zmem_putbyte(zmb, Program_header.version); - /* TODO */ - return zmb; + ZMemblock *zmb = zmem_init (MAX_HEADER_LEN); + zmem_putbyte (zmb, Program_header.version); + /* TODO */ + return zmb; } -Word swapBytes(Word w) +Word +swapBytes (Word w) { - return ((w & 255) << 8) + (w >> 8); + return ((w & 255) << 8) + (w >> 8); } -void outputToFile(Program_header_struct *pHeader, FILE* file) +void +outputToFile (Program_header_struct * pHeader, FILE * file) { - Program_header_struct h; - memcpy(&h, pHeader, sizeof(Program_header_struct)); + 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 + h.startPC = swapBytes (h.startPC); + h.h_file_size = swapBytes (h.h_file_size); + h.H_STRINGS_OFFSET = swapBytes (h.H_STRINGS_OFFSET); + + int size = sizeof (Program_header_struct); + fwrite (&h, sizeof (Program_header_struct), 1, file); +} diff --git a/zilasm/header.h b/zilasm/header.h index 41f82fb..c63e665 100644 --- a/zilasm/header.h +++ b/zilasm/header.h @@ -21,136 +21,141 @@ #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); +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/labels.c b/zilasm/labels.cpp similarity index 62% rename from zilasm/labels.c rename to zilasm/labels.cpp index c396397..c8f97f9 100644 --- a/zilasm/labels.c +++ b/zilasm/labels.cpp @@ -1,7 +1,7 @@ /* * labels.c -- part of ZilUtils/ZilAsm * - * Copyright (C) 2016 Jason Self + * Copyright (C) 2016, 2019 Jason Self * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -24,22 +24,26 @@ #include "labels.h" Symtable *Global_labels; -Symtable *Local_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!!! */ +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) +void +init_local_labels (void) { - if (Local_labels) - symtable_destroy(Local_labels); - Local_labels = symtable_create(MAX_LOCAL_LABELS, MAX_LABEL_LEN, ADDRESS_SIZE); + if (Local_labels) + symtable_destroy (Local_labels); + Local_labels = + symtable_create (MAX_LOCAL_LABELS, MAX_LABEL_LEN, ADDRESS_SIZE); } -void init_global_labels(void) +void +init_global_labels (void) { - assert(Global_labels); - Global_labels = symtable_create(MAX_GLOBAL_LABELS, MAX_LABEL_LEN, ADDRESS_SIZE); + assert (Global_labels); + Global_labels = + symtable_create (MAX_GLOBAL_LABELS, MAX_LABEL_LEN, ADDRESS_SIZE); } diff --git a/zilasm/labels.h b/zilasm/labels.h index 5ade613..abef3ce 100644 --- a/zilasm/labels.h +++ b/zilasm/labels.h @@ -1,7 +1,7 @@ /* * labels.h -- part of ZilUtils/ZilAsm * - * Copyright (C) 2016 Jason Self + * Copyright (C) 2016, 2019 Jason Self * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -21,13 +21,14 @@ #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 index b602339..0000000 --- a/zilasm/main.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * main.c - * - * Copyright (C) 2015 Alexander Andrejevic - * Copyright (C) 2015, 2019 Jason Self - * - * 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 - * - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -#include -#include -#include -#include -#include -#include -#include - -#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" - "\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 index 0000000..22b7e71 --- /dev/null +++ b/zilasm/main.cpp @@ -0,0 +1,435 @@ +/* + * main.c + * + * Copyright (C) 2015 Alexander Andrejevic + * Copyright (C) 2015, 2019 Jason Self + * + * 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 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include +#include +#include +#include +extern "C" +{ +#include +} +#include +#include +#include +#include "config.h" +#include "header.h" +extern "C" +{ +#include "opcodes.h" +} +#include "parser.h" + +#include +#include +using namespace std; + +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; + + +struct String_Table_Elem +{ + string value; // value in ASCII format + int index; +}; + + +class CMain +{ +public: + CMain (); + int assembly (); + void fill_config (void); + void get_arguments (int argc, char *argv[], char *envp[]); + + char *get_output_file_name (); +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 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, ...); + +}; + + +CMain::CMain ():m_output_file (NULL) +{ +} + +int +CMain::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 + + int code_start_offset = 64; + Program_header.startPC = code_start_offset >> 2; + + m_code_size = 0; + ZMemblock *zmem_code = zmem_init (65536); + + /// write zero number of local variables + zmem_putbyte (zmem_code, 0); // number of local variables + ++m_code_size; + + // write instructions' codes + for (int i = 0; i < g_numberOfInstructions; ++i) + { + for (int j = 0; j < g_codes[i]->used_size; ++j) + { + zmem_putbyte (zmem_code, g_codes[i]->contents[j]); + ++m_code_size; + } + } + + if (m_code_size & 7) + m_code_size += 8 - (m_code_size & 7); + + 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); + fwrite (zmb->contents, zmb->allocated_size, 1, file); + fclose (file); + } + + return OK; +} + + +char * +CMain::get_output_file_name () +{ + return m_output_file; +} + + +void +CMain::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 +CMain::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 +CMain::print_version () +{ + printf (PACKAGE_STRING "\n" + "License AGPLv3+: GNU AGPL version 3 or later\n" + "\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 +CMain::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 +CMain::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 +CMain::fill_config (void) +{ + bzero (&Config, sizeof (Config)); + Config.zversion = DEFAULT_ZVERSION; + fill_zserial (); +} + + +void +CMain::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 +CMain::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 +CMain::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 * +CMain::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 +CMain::output_code_section () +{ + +} + + + +int +main (int argc, char *argv[], char *envp[]) +{ + CMain main; + + main.fill_config (); + main.get_arguments (argc, argv, envp); + init_opcodes (Config.zversion, 0); + + init_parser (); + + for (int i = optind; i < argc; i++) + parse_file (argv[i]); + main.assembly (); + + /* TODO! List global symbols */ + /* TODO! Find abbreviations */ + relase_parser (); + return 0; +} diff --git a/zilasm/opcodes.c b/zilasm/opcodes.c index 1d9ad64..f848e0e 100644 --- a/zilasm/opcodes.c +++ b/zilasm/opcodes.c @@ -1,7 +1,7 @@ /* * opcodes.c -- part of ZilUtils/ZilAsm * - * Copyright (C) 2016 Jason Self + * Copyright (C) 2016, 2019 Jason Self * * Based on ZILF (c) 2010, 2015 Jesse McGrew * @@ -25,163 +25,173 @@ #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 + {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, 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); + } } diff --git a/zilasm/opcodes.h b/zilasm/opcodes.h index 21e8ac0..53e3509 100644 --- a/zilasm/opcodes.h +++ b/zilasm/opcodes.h @@ -1,7 +1,7 @@ /* * opcodes.h -- part of ZilUtils/ZilAsm * - * Copyright (C) 2016 Jason Self + * Copyright (C) 2016, 2019 Jason Self * * Based on ZILF (c) 2010, 2015 Jesse McGrew * @@ -26,26 +26,42 @@ #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_PRINT = 141, + Opcode_PRINTI = 178, + Opcode_PRINTR = 179, + Opcode_QUIT = 186, + Opcode_CRLF = 187 +}; + + +#endif /* ifndef ZILASM_OPCODES */ diff --git a/zilasm/parser.c b/zilasm/parser.c deleted file mode 100644 index 81713cc..0000000 --- a/zilasm/parser.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * parser.c -- part of ZilUtils/ZilAsm - * - * Copyright (C) 2016, 2019 Jason Self - * - * 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 - * - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -#include /* fopen, fgets */ -#include /* 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 index 0000000..31e257f --- /dev/null +++ b/zilasm/parser.cpp @@ -0,0 +1,313 @@ +/* + * parser.c -- part of ZilUtils/ZilAsm + * + * Copyright (C) 2016, 2019 Jason Self + * + * 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 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +#include +#include /* fopen, fgets */ +#include /* strlen */ +#include +#include +using namespace std; + + +#include "header.h" +#include "parser.h" + +extern "C" +{ +#include "directives.h" +#include "opcodes.h" +} +#include "labels.h" +#include "string_table.h" + + +#define iscomment(c) ((c) == ';') +#define isbindigit(c) ((c) == '0' || (c) == '1') + +/* !!! TODO !!! */ +#define fatal_error(errmsg) printf(errmsg) +#define PC NULL + +unsigned g_numberOfInstructions = 0; + + +ZMemblock (*g_codes[MAX_NUMBER_OF_INSTRUCTIONS]); + + +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_instruction (const char *a); + +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); + if (b != a) + { + int len = b ? b - a : strlen (a); + ZOpcode *op = (ZOpcode *) symtable_lookup2 (Opcodes, a, len); + if (!op) + return 0; + ZOpcode_flags flags = op->flags; + /* !!! TODO !!! */ + + + ZMemblock *mem_additional = NULL; + + switch (op->opcode) + { + case Opcode_CRLF: + case Opcode_PRINT: + case Opcode_QUIT: + break; + + case Opcode_PRINTI: + case Opcode_PRINTR: + { + char *p = (char *) a + len; + p = (char *) pass_spaces (p); + if (*p == '\"') + { + p++; + string str; + while (*p != '\"') + { + str += *p; + ++p; + } + len = p - a; + mem_additional = + String_table::encrypt_string (str.c_str (), NULL); + } + break; + } + default: + fatal_error ("error! instruction not supported"); + return 0; + } + + int instruction_size = 1; + if (mem_additional) + instruction_size += mem_additional->used_size; + //printf("instruction %s", a); + + g_codes[g_numberOfInstructions] = zmem_init (instruction_size); + zmem_putbyte (g_codes[g_numberOfInstructions], op->opcode); + + if (mem_additional) + { + for (int i = 0; i < mem_additional->used_size; ++i) + zmem_putbyte (g_codes[g_numberOfInstructions], + mem_additional->contents[i]); + zmem_destroy (mem_additional); + } + + ++g_numberOfInstructions; + return len; + } + + 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'); + } + + fclose (fp); + return 0; +} + +/* + +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) +} + + +*/ + + +void +init_parser () +{ + g_numberOfInstructions = 0; +} + + +void +relase_parser () +{ + for (int i = 0; i < g_numberOfInstructions; ++i) + { + zmem_destroy (g_codes[i]); + } + g_numberOfInstructions = 0; +} diff --git a/zilasm/parser.h b/zilasm/parser.h index c708f4d..2ed9ae7 100644 --- a/zilasm/parser.h +++ b/zilasm/parser.h @@ -1,7 +1,7 @@ /* * parser.h -- part of ZilUtils/ZilAsm * - * Copyright (C) 2016 Jason Self + * Copyright (C) 2016, 2019 Jason Self * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -22,6 +22,20 @@ #ifndef ZILASM_PARSER #define ZILASM_PARSER 1 -int parse_file(const char *filename); -#endif /* ifndef ZILASM_PARSER */ +struct Instruction +{ + Byte *pCodes; + int size; +}; + +void init_parser (); + +int parse_file (const char *filename); + +extern unsigned g_numberOfInstructions; + +#define MAX_NUMBER_OF_INSTRUCTIONS 65536 +extern ZMemblock (*g_codes[MAX_NUMBER_OF_INSTRUCTIONS]); + +#endif /* ifndef ZILASM_PARSER */ diff --git a/zilasm/string_table.cpp b/zilasm/string_table.cpp new file mode 100644 index 0000000..a086b87 --- /dev/null +++ b/zilasm/string_table.cpp @@ -0,0 +1,155 @@ +/* + * string_table.cpp -- part of ZilUtils/ZilAsm + * + * Copyright (C) 2019 Jason Self + * + * 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 + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include +#include +#include "header.h" +#include "string_table.h" +#include +extern "C" +{ +#include +} + +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; + } + zmb->contents[zmb->used_size - 2] |= 0x80; + + 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 index 0000000..36fda87 --- /dev/null +++ b/zilasm/string_table.h @@ -0,0 +1,38 @@ +/* + * string_table.h -- part of ZilUtils/ZilAsm + * + * Copyright (C) 2019 Jason Self + * + * 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 + * + * 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 diff --git a/zilasm/symtable.c b/zilasm/symtable.c index 2c5735f..a5ff791 100644 --- a/zilasm/symtable.c +++ b/zilasm/symtable.c @@ -1,7 +1,7 @@ /* * symtable.c -- part of ZilUtils/ZilAsm * - * Copyright (C) 2016 Jason Self + * Copyright (C) 2016, 2019 Jason Self * * 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 +#include "strings.h" #include #include @@ -27,120 +28,163 @@ #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 */ diff --git a/zilasm/symtable.h b/zilasm/symtable.h index bbb7084..8903d8d 100644 --- a/zilasm/symtable.h +++ b/zilasm/symtable.h @@ -1,7 +1,7 @@ /* * symtable.h -- part of ZilUtils/ZilAsm * - * Copyright (C) 2016 Jason Self + * Copyright (C) 2016, 2019 Jason Self * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -22,19 +22,31 @@ #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 */ diff --git a/zilasm/zmem.c b/zilasm/zmem.c index 623e52e..bfab797 100644 --- a/zilasm/zmem.c +++ b/zilasm/zmem.c @@ -1,7 +1,7 @@ /* * zmem.c -- part of ZilUtils/ZilAsm * - * Copyright (C) 2016 Jason Self + * Copyright (C) 2016, 2019 Jason Self * * 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,30 +20,34 @@ */ #include -#include /* bzero */ -#include /* malloc, free */ +#include /* bzero */ + +#include /* 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; } diff --git a/zilasm/zmem.h b/zilasm/zmem.h index 6408770..49a9997 100644 --- a/zilasm/zmem.h +++ b/zilasm/zmem.h @@ -24,14 +24,15 @@ #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 */ -- 2.31.1