*
* 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++;
{
while (p && isalnum (*p))
p++;
- return (p && *p) ? p : NULL;
+ //return (p && *p) ? p : NULL;
+ return 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