454 lines
15 KiB
C
454 lines
15 KiB
C
/*
|
|
* asm-savers.h
|
|
*
|
|
* Copyright 2026
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301, USA.
|
|
*
|
|
*
|
|
*/
|
|
|
|
#if (!defined(NTSYS__S_ASSEMBLER_H___))
|
|
#define NTSYS__S_ASSEMBLER_H___
|
|
|
|
#define ntsys_exit_if_error(parser) if (!ntsys_asm_arg_new((parser)->string, (parser)->cache))
|
|
#define ntsys_run_asm_parser(ss) __ntsys_arg_function_loader(&(ss))
|
|
#define create_ntsys_asm_parser(cache, fp, str, table, table_size, labels, labels_pos, labels_count, cyc, f_sz) ((ntsys_argument_parser_t){(cache), (fp), (str), (table), (table_size), (labels), (labels_pos), (labels_count), (cyc), (f_sz), NULL})
|
|
#define create_ntsys_asm_save(ss) ((ntsys_asm_save_t){(ss), (ss)})
|
|
#define create_ntsys_asm_cache(ss) ((ntsys_asm_cache_t)&(ss))
|
|
#define ntsys_asm_arg_new(str, __cache) ((ntsys_get_arg((__cache))) && ((str) = __cache->string))
|
|
#define ntsys_asm_arg_or_zero_len_str(str, __cache) ((((ntsys_get_arg((__cache))) && ((str) = __cache->string)) == NULL) ? ("") : (str))
|
|
|
|
/*
|
|
* #define __SPACE_SHIFT while (is_space(st[pos])) { pos ++; }
|
|
* #define __NEXT_ARG {__e_byte_t isStr = 0;while (!is_space(st[save]) || isStr == 1) { if (st[save] == '"' && st[save - 1] != '\\') {isStr = !isStr;}save ++; }}while (is_space(st[save])) { save ++; }{size_t n_p = save;__e_byte_t isStr = 0;while (!is_space(st[n_p]) || isStr == 1) { if (st[n_p] == '"' && st[n_p - 1] != '\\') {isStr = !isStr;}n_p ++; }st[n_p] = '\0';}
|
|
* #define get_mem_pos() *mem_pos = ftell(fp) == 0 ? 0 : ftell(fp) - 1;
|
|
*/
|
|
|
|
#define __READ_FILE_WITH_EOF_OR_LN ((c = getc(fp)) != EOF && c != '\n' && c != '\r')
|
|
#define is_space(c) (c >= 0 && c <= 32)
|
|
|
|
static byte_t is_spaces(char* str) {
|
|
size_t pos = 0;
|
|
while (pos < strlen(str)) {
|
|
if (!is_space(str[pos])) return 0;
|
|
pos ++;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
char* ntsys_get_str(char* ptr, FILE* fp) {
|
|
if (ptr != NULL) {
|
|
free(ptr);
|
|
}
|
|
unsigned long len = 0;
|
|
int c;
|
|
{
|
|
unsigned long save_ptr = ftell(fp);
|
|
__e_byte_t tr = 0;
|
|
while (__READ_FILE_WITH_EOF_OR_LN) {
|
|
if (!is_space(c)) tr = 1;
|
|
len ++;
|
|
}
|
|
if (tr == 0) len = 0;
|
|
if (len == 0 && c == EOF) return NULL;
|
|
if (len == 0) {
|
|
ptr = malloc(5 * sizeof(char));
|
|
return strcpy(ptr, "pass");
|
|
}
|
|
fseek(fp, save_ptr, SEEK_SET);
|
|
}
|
|
ptr = malloc(len + 1);
|
|
if (ptr == NULL) {
|
|
ntsys_error("Out of memory!");
|
|
return NULL;
|
|
}
|
|
len = 0;
|
|
while (__READ_FILE_WITH_EOF_OR_LN) {
|
|
ptr[len] = c;
|
|
len ++;
|
|
}
|
|
ptr[len] = '\0';
|
|
size_t i = 0;
|
|
__e_byte_t isStr = 0;
|
|
while (i < strlen(ptr)) {
|
|
if (ptr[i] == '"' && ptr[((i == 0) ? 1 : i) - 1] != '\\') {isStr = !isStr;}
|
|
if ((ptr[i] == ';' || ptr[i] == '#') && isStr == 0) ptr[i] = '\0';
|
|
if ((ptr[i] == ',') && isStr == 0) ptr[i] = ' ';
|
|
i ++;
|
|
}
|
|
if (strlen(ptr) == 0 || is_spaces(ptr)) {
|
|
free(ptr);
|
|
ptr = malloc(5 * sizeof(char));
|
|
return strcpy(ptr, "pass");
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
#undef __READ_FILE_WITH_EOF_OR_LN
|
|
|
|
typedef struct {
|
|
char* string;
|
|
char* cache;
|
|
} ntsys_asm_save_t;
|
|
|
|
typedef ntsys_asm_save_t* ntsys_asm_cache_t;
|
|
|
|
static void __str_slice(char* str) {
|
|
size_t i = 1;
|
|
while (i < strlen(str)) {
|
|
str[i - 1] = str[i];
|
|
i ++;
|
|
}
|
|
str[strlen(str) - 1] = '\0';
|
|
}
|
|
|
|
char* ntsys_get_arg(ntsys_asm_cache_t save) {
|
|
char* str = save->cache;
|
|
while (1) {
|
|
if ((!is_space(str[0])) || str[0] == '\0') {
|
|
break;
|
|
}
|
|
str ++;
|
|
}
|
|
{
|
|
size_t n_p = 0;
|
|
__e_byte_t isStr = 0;
|
|
while (1) {
|
|
if (str[n_p] == '"' && str[((n_p == 0) ? 1 : n_p) - 1] != '\\') {isStr = !isStr;}
|
|
if ((is_space(str[n_p]) && isStr == 0) || str[n_p] == '\0') {
|
|
break;
|
|
}
|
|
n_p ++;
|
|
}
|
|
byte_t t = 1;
|
|
if (n_p + t > strlen(str)) t = 0;
|
|
save->cache = &str[n_p + t];
|
|
str[n_p] = '\0';
|
|
}
|
|
if (str[strlen(str) - 1] == '\n' || str[strlen(str) - 1] == '\r') str[strlen(str) - 1] = '\0';
|
|
if (strlen(str) == 0) {
|
|
str = NULL;
|
|
save->string = NULL;
|
|
return NULL;
|
|
}
|
|
if (str[0] == '"') {
|
|
str ++;
|
|
if (str[strlen(str) - 1] != '"' || str[(strlen(str) < 2 ? 2 : strlen(str)) - 2] == '\\') {
|
|
ntsys_error("No close of string!");
|
|
str = NULL;
|
|
save->string = NULL;
|
|
return NULL;
|
|
} else {
|
|
str[strlen(str) - 1] = '\0';
|
|
size_t i = 0;
|
|
while (i < strlen(str)) {
|
|
if (str[i] == '\\') {
|
|
__str_slice(&str[i]);
|
|
switch (str[i]) {
|
|
case '0': str[i] = '\0'; break;
|
|
case 'a': str[i] = '\a'; break;
|
|
case 'b': str[i] = '\b'; break;
|
|
case 't': str[i] = '\t'; break;
|
|
case 'n': str[i] = '\n'; break;
|
|
case 'v': str[i] = '\v'; break;
|
|
case 'f': str[i] = '\f'; break;
|
|
case 'r': str[i] = '\r'; break;
|
|
case '"': str[i] = '"'; break;
|
|
default:
|
|
ntsys_error("Unknown ident!");
|
|
str = NULL;
|
|
save->string = NULL;
|
|
return NULL;
|
|
break;
|
|
}
|
|
}
|
|
i ++;
|
|
}
|
|
}
|
|
}
|
|
save->string = str;
|
|
return str;
|
|
}
|
|
|
|
typedef char** ntsys_labels_array_t;
|
|
typedef struct {
|
|
ntsys_asm_cache_t cache;
|
|
FILE* fp;
|
|
char* string;
|
|
char** table;
|
|
size_t table_length;
|
|
char** labels;
|
|
word_t* labels_positions;
|
|
size_t* labels_count;
|
|
byte_t is_rewrite;
|
|
dword_t* file_size;
|
|
word_t* memory_size;
|
|
} ntsys_argument_parser_t;
|
|
|
|
static void __input_datatype(ntsys_argument_parser_t* parser, byte_t* mode) {
|
|
ntsys_exit_if_error(parser) {
|
|
ntsys_error("Cannot find argument!");
|
|
return;
|
|
}
|
|
byte_t data_type = 0x01;
|
|
char* str = parser->string;
|
|
if (strcmp(str, "byte") == 0) {
|
|
data_type = 0x01;
|
|
} else if (strcmp(str, "word") == 0) {
|
|
data_type = 0x02;
|
|
} else if (strcmp(str, "dw") == 0) {
|
|
data_type = 0x02;
|
|
} else if (strcmp(str, "dword") == 0) {
|
|
data_type = 0x04;
|
|
} else if (strcmp(str, "qword") == 0) {
|
|
data_type = 0x08;
|
|
} else if (strcmp(str, "sbyte") == 0) {
|
|
data_type = 0xF1;
|
|
} else if (strcmp(str, "sword") == 0) {
|
|
data_type = 0xF2;
|
|
} else if (strcmp(str, "sdword") == 0) {
|
|
data_type = 0xF4;
|
|
} else if (strcmp(str, "sqword") == 0) {
|
|
data_type = 0xF8;
|
|
} else if (strcmp(str, "db") == 0) {
|
|
data_type = 0xB2;
|
|
} else {
|
|
ntsys_error("Incorrect datatype!");
|
|
return;
|
|
}
|
|
if (data_type == 0xB2) fputc((__e_byte_t)0x02, parser->fp);
|
|
else fputc((__e_byte_t)data_type, parser->fp);
|
|
*mode = data_type;
|
|
}
|
|
|
|
static void __write_label(ntsys_argument_parser_t* parser) {
|
|
if (parser->is_rewrite == 0) {
|
|
putc('E', parser->fp);
|
|
putc('F', parser->fp);
|
|
return;
|
|
}
|
|
size_t i = 0;
|
|
/* printf("Count: 0x%04lX\n", *(parser->labels_count)); */
|
|
while (i < *(parser->labels_count)) {
|
|
/* printf("Label: \"%s\" to \"%s\" at 0x%08X\n", parser->string, parser->labels[i], parser->labels_positions[i]); */
|
|
if (strcmp(parser->string, parser->labels[i]) == 0) {
|
|
word_t cnt = parser->labels_positions[i];
|
|
int __i = 1;
|
|
if (!(*((char *)&__i) == 1)) {
|
|
/* BIG ENDIAN */
|
|
byte_t* ar = (byte_t*)&cnt;
|
|
byte_t s = ar[0];
|
|
ar[0] = ar[1];
|
|
ar[1] = s;
|
|
}
|
|
fwrite(&cnt, 1, sizeof(word_t), parser->fp);
|
|
return;
|
|
}
|
|
i ++;
|
|
}
|
|
|
|
}
|
|
|
|
static void __input_data(ntsys_argument_parser_t* parser, byte_t* mode) {
|
|
ntsys_exit_if_error(parser) {
|
|
ntsys_error("Cannot find argument!");
|
|
return;
|
|
}
|
|
byte_t data_type = *mode;
|
|
char* str = parser->string;
|
|
if (str[0] >= '0' && str[0] <= '9') {
|
|
int count_system = 10;
|
|
if (str[1] == 'x') {
|
|
count_system = 16;
|
|
} else if (str[1] == 'b') {
|
|
count_system = 2;
|
|
} else if ((str[1] < '0' || str[1] > '9') && !is_space(str[1])) {
|
|
ntsys_error("Unknown number system!");
|
|
return;
|
|
}
|
|
if (count_system != 10) {
|
|
str += 2;
|
|
}
|
|
long cnt = strtol(str, NULL, count_system);
|
|
FILE* fp = parser->fp;
|
|
int __i = 1;
|
|
if (!(*((char *)&__i) == 1)) {
|
|
/* BIG ENDIAN */
|
|
if ((data_type & 0x0F) != 0x01) {
|
|
size_t i = 0;
|
|
byte_t* ar = (byte_t*)&cnt;
|
|
while (i < (data_type & 0x0F)) {
|
|
byte_t s = ar[i];
|
|
ar[i] = ar[(data_type & 0x0F) - i - 1];
|
|
ar[(data_type & 0x0F) - i - 1] = s;
|
|
i ++;
|
|
}
|
|
}
|
|
}
|
|
switch (data_type) {
|
|
case 0x01: fwrite((__e_byte_t*)((byte_t*)&cnt), 1, sizeof(byte_t), fp);
|
|
break;
|
|
case 0x02: fwrite((__e_byte_t*)((word_t*)&cnt), 1, sizeof(word_t), fp);
|
|
break;
|
|
case 0x04: fwrite((__e_byte_t*)((dword_t*)&cnt), 1, sizeof(dword_t), fp);
|
|
break;
|
|
case 0x08: fwrite((__e_byte_t*)((qword_t*)&cnt), 1, sizeof(qword_t), fp);
|
|
break;
|
|
case 0xF1: fwrite((__e_byte_t*)((sbyte_t*)&cnt), 1, sizeof(sbyte_t), fp);
|
|
break;
|
|
case 0xF2: fwrite((__e_byte_t*)((sword_t*)&cnt), 1, sizeof(sword_t), fp);
|
|
break;
|
|
case 0xF4: fwrite((__e_byte_t*)((sdword_t*)&cnt), 1, sizeof(sdword_t), fp);
|
|
break;
|
|
case 0xF8: fwrite((__e_byte_t*)((sqword_t*)&cnt), 1, sizeof(sqword_t), fp);
|
|
break;
|
|
}
|
|
} else {
|
|
if (data_type != 0xB2) {
|
|
ntsys_error("Incorrect datatype! For jump to label please use db type!");
|
|
return;
|
|
}
|
|
__write_label(parser);
|
|
}
|
|
|
|
}
|
|
|
|
static void __input_string(ntsys_argument_parser_t* parser) {
|
|
ntsys_exit_if_error(parser) {
|
|
ntsys_error("Cannot find argument!");
|
|
return;
|
|
}
|
|
char* str = parser->string;
|
|
size_t i = 0;
|
|
while (i < strlen(str)) {
|
|
fputc(str[i], parser->fp);
|
|
i ++;
|
|
}
|
|
fputc('\0', parser->fp);
|
|
}
|
|
|
|
static int __arg_writer(char* str, ntsys_argument_parser_t* parser, byte_t* mode) {
|
|
if (str[0] == ':') {
|
|
if (str[1] == 'T') {
|
|
__input_datatype(parser, mode);
|
|
} else if (str[1] == 'D') {
|
|
__input_data(parser, mode);
|
|
} else if (str[1] == 'S') {
|
|
__input_string(parser);
|
|
}
|
|
} else {
|
|
byte_t x = strtol(str, NULL, 16);
|
|
fputc((char)x, parser->fp);
|
|
/* printf("Input: 0x%04X\n", x); */
|
|
}
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
int __load_label(ntsys_argument_parser_t* parser) {
|
|
char* str = parser->string;
|
|
str[strlen(str) - 1] = '\0';
|
|
parser->labels[*(parser->labels_count)] = malloc(strlen(str) + 1);
|
|
if (parser->labels[*(parser->labels_count)] == NULL) {
|
|
ntsys_error("Out of memory!");
|
|
return EXIT_FAILURE;
|
|
}
|
|
strcpy(parser->labels[*(parser->labels_count)], str);
|
|
parser->labels_positions[*(parser->labels_count)] = (word_t)(ftell(parser->fp));
|
|
/* printf("Label: \"%s\" on 0x%08X\n", str, parser->labels_positions[*(parser->labels_count)]); */
|
|
*parser->labels_count += 1;
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
static int select_argument(ntsys_argument_parser_t* parser) {
|
|
size_t i = 0;
|
|
byte_t internal = 0x00;
|
|
char* str = parser->string;
|
|
if (str[strlen(str) - 1] == ':' && parser->is_rewrite == 0) {
|
|
return __load_label(parser);
|
|
}
|
|
if (str[strlen(str) - 1] == ':') return EXIT_SUCCESS;
|
|
char buf[64];
|
|
char** table = parser->table;
|
|
while (i < parser->table_length) {
|
|
size_t t = 0;
|
|
while (t < strlen(table[i])) {
|
|
if (table[i][t] == '=') break;
|
|
t ++;
|
|
}
|
|
strncpy(buf, table[i], t);
|
|
buf[t] = '\0';
|
|
if (strcmp(str, buf) == 0) {
|
|
char* se = &table[i][t + 1];
|
|
while (strlen(se) > 1) {
|
|
char is[3];
|
|
strncpy(is, se, 2);
|
|
is[2] = '\0';
|
|
if (__arg_writer(is, parser, &internal) == EXIT_FAILURE) {
|
|
ntsys_error("Internal program error!");
|
|
return EXIT_FAILURE;
|
|
}
|
|
se += sizeof(char) * 2;
|
|
}
|
|
return EXIT_SUCCESS;
|
|
}
|
|
i ++;
|
|
}
|
|
printf("\033[1mntsys: \033[91mUndefined operator \"%s\"!\033[0m\n", str);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
byte_t fGH6VSEzu7qNiGVE_hd_ew = 0;
|
|
|
|
static void __write_header(ntsys_argument_parser_t* parser) {
|
|
if (fGH6VSEzu7qNiGVE_hd_ew == 1) return;
|
|
fGH6VSEzu7qNiGVE_hd_ew = 1;
|
|
fputc(0x4D, parser->fp);
|
|
fputc(0x5A, parser->fp);
|
|
parser->memory_size = &fGH6VSEzu7qNiGVE_mem_size;
|
|
*parser->file_size += 8;
|
|
int __i = 1;
|
|
if (!(*((char *)&__i) == 1)) {
|
|
/* BIG ENDIAN */
|
|
size_t i = 0;
|
|
byte_t* ar = (byte_t*)parser->file_size;
|
|
while (i < (sizeof(dword_t))) {
|
|
byte_t s = ar[i];
|
|
ar[i] = ar[(sizeof(dword_t)) - i - 1];
|
|
ar[(sizeof(dword_t)) - i - 1] = s;
|
|
i ++;
|
|
}
|
|
ar = (byte_t*)parser->memory_size;
|
|
byte_t s = ar[0];
|
|
ar[0] = ar[1];
|
|
ar[1] = s;
|
|
}
|
|
fwrite(parser->file_size, 1, sizeof(dword_t), parser->fp);
|
|
fwrite(parser->memory_size, 1, sizeof(word_t), parser->fp);
|
|
}
|
|
|
|
int __ntsys_arg_function_loader(ntsys_argument_parser_t* parser) {
|
|
if (parser->is_rewrite) __write_header(parser);
|
|
while (ntsys_asm_arg_new(parser->string, parser->cache)) {
|
|
if (select_argument(parser) == EXIT_FAILURE) return EXIT_FAILURE;
|
|
}
|
|
if (parser->is_rewrite == 0) *parser->file_size = ftell(parser->fp) + 1;
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
#undef is_space
|
|
|
|
#endif |