bin_PROGRAMS = zilasm
man_MANS = zilasm.1
-zilasm_SOURCES = main.cpp opcodes.c symtable.c header.cpp parser.cpp directives.cpp labels.cpp string_table.cpp zmem.c
+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
--- /dev/null
+/*
+* 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
--- /dev/null
+/*
+ * 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
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-#include <stdlib.h> /* bsearch */
-#include <string.h> /* strcmp */
-#include <stdio.h>
-#include <stack>
-#include <string>
-using namespace std;
-
-#include "header.h"
-#include "parser.h"
-#include "directives.h"
+#include "include_all.h"
#define ARRAY_SIZE(x) ((sizeof(x)) / (sizeof(x[0])))
static int
-byte_handler (const char *args)
+byte_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
return 0;
}
static int
-end_handler (const char *args)
+end_handler (const char *args, CParser* parser)
{
g_stopParsing = 1;
return 0;
}
static int
-endi_handler (const char *args)
+endi_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
return 0;
}
static int
-endt_handler (const char *args)
+endt_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
return 0;
}
static int
-fstr_handler (const char *args)
+fstr_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
return 0;
}
static int
-funct_handler (const char *args)
+funct_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
- return 0;
+
+ parser->add_function(args);
+ return 0;
}
static int
-gstr_handler (const char *args)
+gstr_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
return 0;
}
static int
-gvar_handler (const char *args)
+gvar_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
return 0;
}
static int
-insert_handler (const char *args)
+insert_handler (const char *args, CParser* parser)
{
string file_name;
char *p = (char*)args;
//pc.current_file_name = s;
g_parsing_contexts.push(pc);
-
- unsigned saveLineNumber = g_currentLineNumber;
- parse_file(); //s.c_str());
- g_currentLineNumber = saveLineNumber;
+ 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)
+len_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
return 0;
}
static int
-newdirective_handler (const char *args)
+newdirective_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
return 0;
}
static int
-object_handler (const char *args)
+object_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
return 0;
}
static int
-prop_handler (const char *args)
+prop_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
return 0;
}
static int
-str_handler (const char *args)
+str_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
return 0;
}
static int
-strl_handler (const char *args)
+strl_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
return 0;
}
static int
-table_handler (const char *args)
+table_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
return 0;
}
static int
-vocbeg_handler (const char *args)
+vocbeg_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
return 0;
}
static int
-vocend_handler (const char *args)
+vocend_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
return 0;
}
static int
-word_handler (const char *args)
+word_handler (const char *args, CParser* parser)
{
/* !!! TODO !!! */
return 0;
}
static int
-zword_handler (const char *args)
+zword_handler (const char *args, CParser* parser)
{
/* !!! 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", 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
-};
+
typedef struct
{
}
Directive_handler
-directive_lookup (const char *name, unsigned namelen)
+CDirectives::directive_lookup (const char *name, unsigned namelen)
{
- Name n = { name, 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
#ifndef ZILASM_DIRECTIVES
#define ZILASM_DIRECTIVES 1
-typedef int (*Directive_handler) (const char *directive_args);
+class CParser;
+
+typedef int (*Directive_handler) (const char *directive_args, CParser* parser);
typedef struct
{
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 */
/*
* header.c -- 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
#include "header.h"
-Program_header_struct Program_header;
+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;
+ 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);
+ zmem_putbyte (zmb, program_header.version);
/* TODO */
return zmb;
}
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_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);
/*
* 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
} Program_header_struct;
-extern Program_header_struct Program_header;
+extern Program_header_struct program_header;
void program_header_reset (unsigned zversion);
ZMemblock *program_header_build (void);
void outputToFile (Program_header_struct * h, FILE * file);
-void relase_parser ();
+//void relase_parser ();
#endif /* ifndef ZILASM_HEADER */
--- /dev/null
+/*
+ * 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
+
*
* 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>
-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 "parser.h"
-
-
+//
+//#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 };
-enum
-{ FAIL = -1, OK = 0, NEED_RESTART = 1 };
+
static struct option const long_options[] = {
{"help", no_argument, NULL, 'h'},
};
-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_number_of_instructions; ++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 ()
+struct
{
- return m_output_file;
-}
-
+ int zversion; /* 0 - 8 */
+ int zorkid; /* 0 - 65535 */
+ char zserial[7]; /* YYMMDD */
+ Opcode_dict *opcode_dict;
+} Config;
void
-CMain::get_arguments (int argc, char *argv[], char *envp[])
+CCompiler::get_arguments (int argc, char *argv[], char *envp[])
{
int opt = 0;
while ((opt = getopt_long (argc, argv, "hVo:", long_options, NULL)) != -1)
void
-CMain::wrong_arg (const char *err, ...)
+CCompiler::wrong_arg (const char *err, ...)
{
if (err)
{
void
-CMain::print_version ()
+CCompiler::print_version ()
{
printf (PACKAGE_STRING "\n"
"License AGPLv3+: GNU AGPL version 3 or later\n"
void
-CMain::print_usage (int failed)
+CCompiler::print_usage (int failed)
{
printf ("Usage: " PACKAGE_NAME " [OPTION...] [FILES...]\n"
"\n"
}
void
-CMain::fill_zserial (void)
+CCompiler::fill_zserial (void)
{
time_t t;
struct tm *timeinfo;
void
-CMain::fill_config (void)
+CCompiler::fill_config (void)
{
bzero (&Config, sizeof (Config));
Config.zversion = DEFAULT_ZVERSION;
void
-CMain::parse_intarg (int *dest, const char name[], int min, int max,
+CCompiler::parse_intarg (int *dest, const char name[], int min, int max,
int defval)
{
if (!optarg)
void
-CMain::parse_zserial (void)
+CCompiler::parse_zserial (void)
{
if (!optarg)
{
void
-CMain::new_file_suffix (char *result, size_t maxlen, const char *src,
+CCompiler::new_file_suffix (char *result, size_t maxlen, const char *src,
const char *newsuffix)
{
strncpy (result, src, maxlen);
char *
-CMain::build_output_filename (const char basename[], const char *suffix)
+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. */
void
-CMain::output_code_section ()
+CCompiler::output_code_section ()
{
}
-
int
main (int argc, char *argv[], char *envp[])
{
- CMain main;
+ CCompiler compiler;
- main.fill_config ();
- main.get_arguments (argc, argv, envp);
+ compiler.fill_config ();
+ compiler.get_arguments (argc, argv, envp);
init_opcodes (Config.zversion, 0);
- init_parser ();
-
+
//for (int i = optind; i < argc; i++)
// parse_file(argv[i]);
}
g_parsing_contexts.push(pc);
- parse_file();// argv[optind]);
- if ( !g_haveErrors )
- main.assembly ();
+ compiler.parser.parse_file();// argv[optind]);
+ if ( !compiler.parser.have_errors())
+ compiler.assembly ();
/* TODO! List global symbols */
/* TODO! Find abbreviations */
- relase_parser ();
+ //relase_parser ();
return 0;
}
/*
* opcodes.c -- part of ZilUtils/ZilAsm
*
- * Copyright (C) 2016, 2019 Jason Self <j@jxself.org>
+ * Copyright (C) 2016, 2019, 2020 Jason Self <j@jxself.org>
*
* Based on ZILF (c) 2010, 2015 Jesse McGrew
*
{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
+ {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
/*
* opcodes.h -- part of ZilUtils/ZilAsm
*
- * Copyright (C) 2016, 2019 Jason Self <j@jxself.org>
+ * Copyright (C) 2016, 2019, 2020 Jason Self <j@jxself.org>
*
* Based on ZILF (c) 2010, 2015 Jesse McGrew
*
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_CRLF = 187
+ Opcode_RTRUE = 176
};
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-#include <stdlib.h>
-#include <stdio.h> /* fopen, fgets */
-#include <string.h> /* strlen */
-#include <ctype.h>
-#include <string>
-#include <stack>
-using namespace std;
-
-#include "header.h"
-#include "parser.h"
-#include "directives.h"
-
-extern "C"
-{
-#include "opcodes.h"
-}
-#include "labels.h"
-#include "string_table.h"
+#include "include_all.h"
#define iscomment(c) ((c) == ';')
//#define fatal_error(errmsg) printf(errmsg)
#define PC NULL
-unsigned g_number_of_instructions = 0;
-unsigned g_currentLineNumber = 0;
-//string g_source_directory;
-bool g_haveErrors = false;
stack<Parsing_Context> g_parsing_contexts;
-ZMemblock (*g_codes[MAX_NUMBER_OF_INSTRUCTIONS]);
+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
-build_error_message(const char *message)
+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(), g_currentLineNumber, message);
+ g_parsing_contexts.top().current_file_name.c_str(), m_current_line_number, message);
return string(buff);
}
void
-fatal_error(const char *errmsg)
+CParser::fatal_error(const char *errmsg)
{
printf( "%s\n", errmsg);
g_haveErrors = true;
void
-checksep (const char *p)
+CParser::checksep (const char *p)
{
if (!*p || iscomment (*p) || isspace (*p))
return;
const char *
-pass_spaces (const char *p)
+CParser::pass_spaces (const char *p)
{
while (p && isspace (*p))
p++;
}
-int tryparse_instruction (const char *a);
-
int
-tryparse_directive (const char *p)
+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 = directive_lookup (a, b - a);
+ Directive_handler f = m_pdirectives->directive_lookup (a, b - a);
if (!f)
return 0;
- return (b-a) + (*f) (b);
+ 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)
{
int
-tryparse_label (const char *a, const char *b, const char *c)
+CParser::tryparse_label (const char *a, const char *b, const char *c)
{
if (*(c + 1) != ':')
{
int
-tryparse_name (const char *a)
+CParser::tryparse_name (const char *a)
{
const char *b = pass_alnums (a);
const char *c = pass_spaces (b);
}
+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
-tryparse_instruction (const char *a)
+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)
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 == '\"')
+ case Opcode_CRLF:
+ case Opcode_PRINT:
+ case Opcode_QUIT:
+ case Opcode_RTRUE:
+ break;
+
+ case Opcode_PRINTI:
+ case Opcode_PRINTR:
{
- p++;
string str;
- while (*p != '\"')
- {
- str += *p;
- ++p;
- }
- len = p - a;
- mem_additional =
- String_table::encrypt_string(str.c_str(), NULL);
+ 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;
+ }
}
- 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_destroy(mem_additional);
}
+
+
++g_number_of_instructions;
return len;
}
}
else
{
- //display_error = true;
string message = "wrong line \"" + string(a) + string("\"");
fatal_error(build_error_message(message.c_str()).c_str());
}
* Line can be one from: Comment, Global label, Local label, Directive, Name=Value, Instruction
*/
int
-parse_line (const char *p)
+CParser::parse_line (const char *p)
{
for (; *p; p++)
{
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))
#define MAX_LINESIZE 1024
int
-parse_file (/*const char *filename*/)
+CParser::parse_file ()
{
if (g_parsing_contexts.size() > 0)
{
if (fp)
{
- g_currentLineNumber = 0;
+ m_current_line_number = 0;
//const int MAX_LINESIZE = 1024;
char line[MAX_LINESIZE];
while (g_stopParsing == 0 && fgets(line, MAX_LINESIZE, fp))
{
- ++g_currentLineNumber;
+ ++m_current_line_number;
if (newline_missing)
fatal_error(build_error_message("line too long").c_str());
return 0;
}
-/*
-line_passed() {
- skip_spaces();
- return (current_token == LINE_END || current_token == LINE_COMMENT);
+CParser::CParser()
+{
+ g_number_of_instructions = 0;
+ m_current_line_number = 0;
+ m_current_address = 0;
+ g_haveErrors = false;
+ m_pdirectives = new CDirectives(this);
}
-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)
-}
-
-*/
+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;
+}
-void
-init_parser ()
+ZMemblock **
+CParser::get_codes()
{
- g_number_of_instructions = 0;
+ return g_codes;
}
+unsigned
+CParser::get_number_of_instructions()
+{
+ return g_number_of_instructions;
+}
+
+bool
+CParser::have_errors()
+{
+ return g_haveErrors;
+}
-void
-relase_parser ()
+void
+CParser::calculate_function_addresses()
{
- for (int i = 0; i < g_number_of_instructions; ++i)
- {
- zmem_destroy (g_codes[i]);
- }
- g_number_of_instructions = 0;
+ //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
int size;
};
-void init_parser ();
+#define MAX_NUMBER_OF_INSTRUCTIONS 65536
-int parse_file();// const char *filename);
+struct Function
+{
+ Function() : index(0), address(0), number_of_local_variables(0)
+ {
+ }
-extern unsigned g_number_of_instructions;
+ unsigned index;
+ unsigned address;
+ unsigned number_of_local_variables;
+};
-#define MAX_NUMBER_OF_INSTRUCTIONS 65536
-extern ZMemblock (*g_codes[MAX_NUMBER_OF_INSTRUCTIONS]);
+
+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
{
};
extern stack<Parsing_Context> g_parsing_contexts;
-extern unsigned g_currentLineNumber;
-extern bool g_haveErrors;
+//extern unsigned g_currentLineNumber;
+//extern bool g_haveErrors;
#endif /* ifndef ZILASM_PARSER */
}
else if (c == ' ')
{
- //if (numberOfSymbolsInWord != 0)
- //{
- // zmem_putbyte(zmb, (w >> 8) & 255);
- // zmem_putbyte(zmb, w & 255);
- // numberOfSymbolsInWord = 0;
- // w = 0;
- //}
write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 0);
}
else