X-Git-Url: https://jxself.org/git/?p=zilutils.git;a=blobdiff_plain;f=zilasm%2Fparser.cpp;h=1ea4aa72aa3385af85d0a5437a1259f9c41c98fe;hp=9b976d9e0b05bcade90c8674a2470d8d656a7199;hb=b1f151e1500e1fdadafaab6b13df6e0a8f32136e;hpb=c0f515aab1285fdedb65d4582b42cc59db0c8e26 diff --git a/zilasm/parser.cpp b/zilasm/parser.cpp index 9b976d9..1ea4aa7 100644 --- a/zilasm/parser.cpp +++ b/zilasm/parser.cpp @@ -18,25 +18,8 @@ * * SPDX-License-Identifier: AGPL-3.0-or-later */ -#include -#include /* fopen, fgets */ -#include /* strlen */ -#include -#include -#include -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) == ';') @@ -46,29 +29,58 @@ extern "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 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; @@ -77,7 +89,7 @@ fatal_error(const char *errmsg) void -checksep (const char *p) +CParser::checksep (const char *p) { if (!*p || iscomment (*p) || isspace (*p)) return; @@ -86,7 +98,7 @@ checksep (const char *p) const char * -pass_spaces (const char *p) +CParser::pass_spaces (const char *p) { while (p && isspace (*p)) p++; @@ -104,23 +116,42 @@ pass_alnums (const char *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) { @@ -129,7 +160,7 @@ 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) != ':') { @@ -152,7 +183,7 @@ tryparse_label (const char *a, const char *b, const char *c) int -tryparse_name (const char *a) +CParser::tryparse_name (const char *a) { const char *b = pass_alnums (a); const char *c = pass_spaces (b); @@ -167,14 +198,51 @@ tryparse_name (const char *a) } +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) @@ -184,48 +252,45 @@ tryparse_instruction (const char *a) 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) @@ -234,13 +299,14 @@ tryparse_instruction (const char *a) 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()); } @@ -267,7 +333,7 @@ tryparse_instruction (const char *a) * 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++) { @@ -277,6 +343,13 @@ parse_line (const char *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)) @@ -291,7 +364,7 @@ parse_line (const char *p) #define MAX_LINESIZE 1024 int -parse_file (/*const char *filename*/) +CParser::parse_file () { if (g_parsing_contexts.size() > 0) { @@ -301,7 +374,7 @@ parse_file (/*const char *filename*/) if (fp) { - g_currentLineNumber = 0; + m_current_line_number = 0; //const int MAX_LINESIZE = 1024; char line[MAX_LINESIZE]; @@ -309,7 +382,7 @@ parse_file (/*const char *filename*/) 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()); @@ -336,48 +409,125 @@ parse_file (/*const char *filename*/) 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::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::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::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::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