2 * parser.c -- part of ZilUtils/ZilAsm
4 * Copyright (C) 2016, 2019 Jason Self <j@jxself.org>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as
8 * published by the Free Software Foundation, either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
19 * SPDX-License-Identifier: AGPL-3.0-or-later
22 #include <stdio.h> /* fopen, fgets */
23 #include <string.h> /* strlen */
34 #include "directives.h"
38 #include "string_table.h"
41 #define iscomment(c) ((c) == ';')
42 #define isbindigit(c) ((c) == '0' || (c) == '1')
45 #define fatal_error(errmsg) printf(errmsg)
48 unsigned g_numberOfInstructions = 0;
51 ZMemblock (*g_codes[MAX_NUMBER_OF_INSTRUCTIONS]);
55 checksep (const char *p)
57 if (!*p || iscomment (*p) || isspace (*p))
59 fatal_error ("wrong chars");
64 pass_spaces (const char *p)
66 while (p && isspace (*p))
68 return (p && *p) ? p : NULL;
73 pass_alnums (const char *p)
75 while (p && isalnum (*p))
77 return (p && *p) ? p : NULL;
81 int tryparse_instruction (const char *a);
84 tryparse_directive (const char *p)
88 const char *a = p + 1;
89 const char *b = pass_alnums (a);
91 Directive_handler f = directive_lookup (a, b - a);
99 tryparse_assignment (const char *a, const char *b, const char *c)
106 tryparse_label (const char *a, const char *b, const char *c)
110 symtable_add2 (Local_labels, a, b - a, PC);
112 else if (*(c + 2) != ':')
114 symtable_add2 (Global_labels, a, b - a, PC);
118 fatal_error ("wrong label type");
122 if (*c && ((c = pass_spaces (c)) != NULL) && *c)
123 return tryparse_instruction (c);
129 tryparse_name (const char *a)
131 const char *b = pass_alnums (a);
132 const char *c = pass_spaces (b);
137 return tryparse_assignment (a, b, c + 1);
139 return tryparse_label (a, b, c);
145 tryparse_instruction (const char *a)
147 const char *b = pass_alnums (a);
150 int len = b ? b - a : strlen (a);
151 ZOpcode *op = (ZOpcode *) symtable_lookup2 (Opcodes, a, len);
154 ZOpcode_flags flags = op->flags;
158 ZMemblock *mem_additional = NULL;
170 char *p = (char *) a + len;
171 p = (char *) pass_spaces (p);
183 String_table::encrypt_string (str.c_str (), NULL);
188 fatal_error ("error! instruction not supported");
192 int instruction_size = 1;
194 instruction_size += mem_additional->used_size;
195 //printf("instruction %s", a);
197 g_codes[g_numberOfInstructions] = zmem_init (instruction_size);
198 zmem_putbyte (g_codes[g_numberOfInstructions], op->opcode);
202 for (int i = 0; i < mem_additional->used_size; ++i)
203 zmem_putbyte (g_codes[g_numberOfInstructions],
204 mem_additional->contents[i]);
205 zmem_destroy (mem_additional);
208 ++g_numberOfInstructions;
217 * Line can be one from: Comment, Global label, Local label, Directive, Name=Value, Instruction
220 parse_line (const char *p)
230 if (n = tryparse_directive (p))
232 if (n = tryparse_name (p))
233 return n; // ..label or assignment
234 if (n = tryparse_instruction (p))
236 fatal_error ("wrong line");
241 #define MAX_LINESIZE 1024
244 parse_file (const char *filename)
246 FILE *fp = fopen (filename, "r");
248 fatal_error ("wrong file");
250 //const int MAX_LINESIZE = 1024;
251 char line[MAX_LINESIZE];
252 int newline_missing = 0;
254 while (fgets (line, MAX_LINESIZE, fp))
257 fatal_error ("line too long");
259 int n = strlen (line);
265 newline_missing = (line[n - 1] != '\n');
276 return (current_token == LINE_END || current_token == LINE_COMMENT);
279 if (line_passed()) continue;
280 if (current_token == DIRECTIVE) {
281 if (!try_next_token(NAME))
282 fatal_error("directive contains incorrect chars")
283 handler = get_directive_handler(current_token);
285 fatal error("unknown directive");
286 (*handler)(remaining_line);
287 if (line_passed()) continue;
288 fatal_error("unexpected line tail");
289 } else if (current_token == NAME) {
291 if (current_token == ASSIGNMENT)
301 g_numberOfInstructions = 0;
308 for (int i = 0; i < g_numberOfInstructions; ++i)
310 zmem_destroy (g_codes[i]);
312 g_numberOfInstructions = 0;