421 lines
9.7 KiB
C++
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;
|
||
|
}
|
||
|
|