kolibrios/programs/demos/life2/t2fasm.cpp

421 lines
9.7 KiB
C++

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <cstring>
#include <string>
using namespace std;
char str[20000], *word[100];
int wordlen[sizeof(word) / sizeof(word[0])];
char words_ignore[100][100] = { "?debug",
"if",
"ifdef",
"ifndef",
"endif",
"macro",
"endm",
"dgroup",
"assume",
"segment",
"ends",
"public",
"proc",
"endp",
"extrn",
"model",
"label",
"end",
""};
#define WI_macro (words_ignore[5])
#define WI_endm (words_ignore[6])
#define WI_segment (words_ignore[9])
#define WI_ends (words_ignore[10])
#define WI_proc (words_ignore[12])
#define WI_endp (words_ignore[13])
#define WI_label (words_ignore[16])
const char *WI_END = "END";
int nwords_ignore = -1;
char *words_ign_sort[sizeof(words_ignore) / sizeof(words_ignore[0])];
int strcmp1(const char *s0, int n0, const char *s1, int n1)
{
while (n0 && n1)
{
n0--; n1--;
int c = (int)tolower(*s0) - (int)tolower(*s1);
if (c < 0) return -1;
if (c > 0) return 1;
if (!*(s0++) || !*(s1++)) return 0;
}
if (n0 && *s0) return 1;
if (n1 && *s1) return -1;
return 0;
}
int strlen1(const char *s, int n)
{
int i = 0;
while (i < n && s[i]) i++;
return i;
}
char *strcpy1(char *r, const char *s, int n)
{
char *r0 = r;
while (n-- && *s) *(r++) = *(s++);
*r = 0;
return r0;
}
char *strchr1(char *s, int n, char c)
{
while (n-- && *s)
{
if (*s == c) return s;
s++;
}
return 0;
}
char *first_not_space(char *s)
{
while (*s && isspace(*s)) s++;
return s;
}
char get_word(char *s)
{
int i = 0, k;
for (k = 0; k < sizeof(word) / sizeof(word[0]); k++)
{
s = first_not_space(s + i);
word[k] = s;
i = 0;
while (s[i] && !isspace(s[i]) && s[i] != ';' && s[i] != ',' && s[i] != ':')
{
i++;
}
if (i == 0)
{
if (s[i] != ',' && s[i] != ':') break;
i = 1;
}
wordlen[k] = i;
}
for (; k < sizeof(word) / sizeof(word[0]); k++)
{
word[k] = s; wordlen[k] = 0;
}
return s[i];
}
void build_words_ignore()
{
int i, j;
nwords_ignore = 0;
while (words_ignore[nwords_ignore][0])
{
words_ign_sort[nwords_ignore] = words_ignore[nwords_ignore];
nwords_ignore++;
}
for (i = 0; i < nwords_ignore; i++) for (j = 0; j < i; j++)
{
if (strcmp1(words_ign_sort[j], -1, words_ign_sort[i], -1) > 0)
{
char *s = words_ign_sort[j];
words_ign_sort[j] = words_ign_sort[i];
words_ign_sort[i] = s;
}
}
words_ign_sort[nwords_ignore] = words_ignore[nwords_ignore];
}
int find_word_ign_sort(const char *s, int n)
{
int i0, i1, i;
if (nwords_ignore < 0) build_words_ignore();
i0 = -1; i1 = nwords_ignore;
while (i1 > i0 + 1)
{
i = (i0 + i1) / 2;
if (strcmp1(s, n, words_ign_sort[i], -1) > 0) i0 = i;
else i1 = i;
}
return i1;
}
char *find_word_ignore(const char *s, int n)
{
int i = find_word_ign_sort(s, n);
return (strcmp1(s, n, words_ign_sort[i], -1) == 0) ? words_ign_sort[i] : 0;
}
char *add_word_ignore(const char *s, int n)
{
int i = find_word_ign_sort(s, n), j;
if (strcmp1(s, n, words_ign_sort[i], -1) != 0)
{
if (s[0] && strlen1(s, n) < sizeof(words_ignore[0]) &&
words_ignore[nwords_ignore+1] < words_ignore[0] + sizeof(words_ignore))
{
strcpy1(words_ignore[nwords_ignore], s, n);
words_ignore[nwords_ignore+1][0] = 0;
for (j = nwords_ignore; j >= i; j--) words_ign_sort[j+1] = words_ign_sort[j];
words_ign_sort[i] = words_ignore[nwords_ignore];
nwords_ignore++;
words_ign_sort[nwords_ignore] = words_ignore[nwords_ignore];
}
else return 0;
}
return words_ign_sort[i];
}
struct CSegment
{
char name[100];
int state;
string text;
};
int nsegment = 0, cursegment = 0, stack_segment[50], nstack_segment = 0;
CSegment segment[100];
void push_stack_segment()
{
if (nstack_segment < sizeof(stack_segment) / sizeof(stack_segment[0]))
{
stack_segment[nstack_segment] = cursegment;
}
nstack_segment++;
}
void pop_stack_segment()
{
if (nstack_segment > 0) nstack_segment--;
if (nstack_segment < sizeof(stack_segment) / sizeof(stack_segment[0]))
{
cursegment = stack_segment[nstack_segment];
}
}
void newsegment()
{
segment[nsegment].name[0] = 0;
segment[nsegment].state = 0;
segment[nsegment].text = "";
cursegment = nsegment++;
}
void tosegment(char *name, int nameL)
{
int i;
cursegment = 0;
if (strlen1(name, nameL) >= sizeof(segment[0].name)) return;
for (i = 0; i < nsegment; i++)
{
if (strcmp1(name, nameL, segment[i].name, -1) == 0)
{
cursegment = i;
return;
}
}
if (nsegment >= sizeof(segment) / sizeof(segment[0])) return;
newsegment();
strcpy1(segment[cursegment].name, name, nameL);
}
void outsegment()
{
if (segment[cursegment].state == 0) return;
fputs("\nsegment", stdout);
if (segment[cursegment].name[0])
{
fputc(' ', stdout);
fputs(segment[cursegment].name, stdout);
}
fputc('\n', stdout);
fputs(segment[cursegment].text.c_str(), stdout);
fputs("endseg", stdout);
if (segment[cursegment].name[0])
{
fputs(" ", stdout);
fputs(segment[cursegment].name, stdout);
}
fputc('\n', stdout);
}
void transform_label(int in_define, bool label = false)
{
if (in_define)
{
memmove(str + 8, word[0], wordlen[0]);
memcpy(str, "nextdef ", 8);
str[wordlen[0]+8] = '\n';
str[wordlen[0]+9] = 0;
}
else if (label)
{
memmove(str, word[0], wordlen[0]);
str[wordlen[0]] = ':';
str[wordlen[0]+1] = '\n';
str[wordlen[0]+2] = 0;
}
segment[cursegment].state |= 4;
}
int main()
{
char *s;
int in_macro = 0, in_define = 0, i;
newsegment();
for (;;)
{
i = sizeof(str) - 200;
if (!fgets(str, i, stdin)) break;
if ((s = strchr(str, '\n')) == NULL)
{
if (strlen(str) < i-1) strcat(str, "\n");
else
{
while (fgets(str, sizeof(str), stdin))
{
if (strchr(str, '\n')) break;
}
continue;
}
}
char* p;
while (p=strstr(str,"st("))
{
p[2]=p[3];
memmove(p+3,p+5,strlen(p+5)+1);
}
get_word(str);
if (word[1][0] == ':') transform_label(in_define, false);
else
{
if (word[0][0] == '.') continue;
if (strcmp1(word[0], wordlen[0], WI_macro, -1) == 0 ||
strcmp1(word[1], wordlen[1], WI_macro, -1) == 0)
{
add_word_ignore(word[0], wordlen[0]);
in_macro++;
continue;
}
if (strcmp1(word[0], wordlen[0], WI_endm, -1) == 0)
{
if (in_macro > 0) in_macro--;
continue;
}
if (strcmp1(word[1], wordlen[1], WI_segment, -1) == 0)
{
push_stack_segment();
add_word_ignore(word[0], wordlen[0]);
tosegment(word[0], wordlen[0]);
continue;
}
if (strcmp1(word[1], wordlen[1], WI_ends, -1) == 0)
{
pop_stack_segment();
continue;
}
if (find_word_ignore(word[0], wordlen[0])) continue;
if (wordlen[0] == 0 || strcmp1(word[0], wordlen[0], "align", -1) == 0)
{
if (word[0][0] == 0) {str[0] = '\n'; str[1] = 0;}
}
else if (strcmp1(word[1], wordlen[1], WI_endp, -1) == 0)
{
if (in_define > 0) strcpy(str, (--in_define) ? "newdef\n" : "enddef\n");
}
else if (strcmp1(word[1], wordlen[1], WI_proc, -1) == 0)
{
memmove(str + 8, word[0], wordlen[0]);
memcpy(str, (in_define++) ? "newdef " : "define ", 8);
str[wordlen[0]+8] = '\n';
str[wordlen[0]+9] = 0;
segment[cursegment].state |= 4;
}
else if (strcmp1(word[1], wordlen[1], WI_label, -1) == 0)
{
transform_label(in_define, true);
}
else
{
for (i = 0; i <= 1; i++)
{
if (strcmp1(word[i], wordlen[i], "db", -1) == 0 &&
wordlen[i+2] >= 3 && strcmp1(word[i+2], 3, "dup", 3) == 0)
{
if (word[i][0] == 'd') word[i][0] = 'r';
else if (word[i][0] == 'D') word[i][0] = 'R';
word[i+1][wordlen[i+1]] = '\n';
word[i+1][wordlen[i+1]+1] = 0;
segment[cursegment].state |= 2;
break;
}
}
if (i > 1)
{
int word_shift = 0;
for (i = 1; i < sizeof(word) / sizeof(word[0]); i++)
{
word[i] += word_shift;
if (wordlen[i] >= 4 && word[i][0] != '[' &&
word[i][wordlen[i]-1] == ']' &&
(s = strchr1(word[i], wordlen[i], '[')) != 0)
{
*s = '+';
memmove(word[i] + 1, word[i], strlen(word[i]) + 1);
word[i][0] = '[';
wordlen[i]++;
word_shift++;
}
else if (wordlen[i] >= 1 && !strchr1(word[i], wordlen[i], '[') &&
strcmp1(word[i-1], wordlen[i-1], "ptr", -1) == 0)
{
memmove(word[i] + wordlen[i] + 2, word[i] + wordlen[i],
strlen(word[i] + wordlen[i]) + 1);
memmove(word[i] + 1, word[i], wordlen[i]);
word[i][0] = '['; word[i][wordlen[i] + 1] = ']';
wordlen[i] += 2;
word_shift += 2;
}
else if (wordlen[i] >= 5 && word[i][wordlen[i]-1] == ')' &&
strcmp1(word[i], wordlen[i], "st(", -1))
{
memmove(word[i] + 2, word[i] + 3, wordlen[i] - 4);
memmove(word[i] + wordlen[i] - 2, word[i] + wordlen[i],
strlen(word[i] + wordlen[i]) + 1);
word_shift -= 2;
}
}
segment[cursegment].state |= 1;
}
}
}
if (in_macro) continue;
if ((s = strchr(str, ';')) != NULL)
{
s[0] = '\n'; s[1] = 0;
if (!first_not_space(str)[0]) continue;
}
segment[cursegment].text += str;
}
for (cursegment = 0; cursegment < nsegment; cursegment++)
{
if ((segment[cursegment].state & 3) != 2) outsegment();
}
fputs("\nI_END:\n", stdout);
for (cursegment = 0; cursegment < nsegment; cursegment++)
{
if ((segment[cursegment].state & 3) == 2) outsegment();
}
fputs("\nalign 0x10\nU_END:\n", stdout);
return 0;
}