mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2024-11-23 20:33:05 +00:00
Working on the assembler
This commit is contained in:
parent
8e13e8ab11
commit
7aee8ac2ef
3 changed files with 23 additions and 119 deletions
126
asm.c
126
asm.c
|
@ -78,132 +78,20 @@ void asm_clear() {
|
|||
mem_d(assembly_constants_data);
|
||||
}
|
||||
|
||||
int asm_parsetype(const char *key, char **skip, long line) {
|
||||
size_t keylen = strlen(key);
|
||||
if (!strncmp(key, *skip, keylen)) {
|
||||
if ((*skip)[keylen] != ':'){
|
||||
printf("%li: Missing `:` after decltype\n", line);
|
||||
exit(1);
|
||||
}
|
||||
*skip += keylen+1;
|
||||
/* skip whitespace */
|
||||
while (**skip == ' ' || **skip == '\t')
|
||||
(*skip)++;
|
||||
|
||||
if (!isalpha(**skip)) {
|
||||
printf("%li: Invalid identififer: %s\n", line, *skip);
|
||||
exit(1);
|
||||
} else {
|
||||
assembly_constants_add((globals) {
|
||||
.name = util_strdup("empty"),
|
||||
.offset = code_globals_elements
|
||||
});
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void asm_parse(FILE *fp) {
|
||||
char *data = NULL;
|
||||
char *skip = NULL;
|
||||
long line = 1; /* current line */
|
||||
size_t size = 0; /* size of line */
|
||||
asm_state state = ASM_NULL;
|
||||
|
||||
while ((data = skip = asm_getline(&size, fp)) != NULL) {
|
||||
/* remove any whitespace at start */
|
||||
while (*skip == ' ' || *skip == '\t')
|
||||
skip++;
|
||||
/* remove newline at end of string */
|
||||
*(skip+*(&size)-1) = '\0';
|
||||
|
||||
if (asm_parsetype(asm_keys[5], &skip, line)) {
|
||||
if (state != ASM_NULL) {
|
||||
printf("%li: Error unfinished function block, expected DONE or RETURN\n", line);
|
||||
goto end;
|
||||
}
|
||||
state = ASM_FUNCTION;
|
||||
code_defs_add((prog_section_def){
|
||||
.type = TYPE_VOID,
|
||||
.offset = code_globals_elements,
|
||||
.name = code_chars_elements
|
||||
});
|
||||
code_globals_add(code_functions_elements);
|
||||
code_functions_add((prog_section_function) {
|
||||
.entry = code_statements_elements,
|
||||
.firstlocal = 0,
|
||||
.locals = 0,
|
||||
.profile = 0,
|
||||
.name = code_chars_elements,
|
||||
.file = 0,
|
||||
.nargs = 0,
|
||||
.argsize = {0}
|
||||
});
|
||||
code_chars_put(skip, strlen(skip));
|
||||
};
|
||||
while ((data = asm_getline(&size, fp)) != NULL) {
|
||||
data = util_strsws(data); /* skip whitespace */
|
||||
data = util_strrnl(data); /* delete newline */
|
||||
|
||||
#if 0
|
||||
/* if we make it this far then we have statements */
|
||||
{
|
||||
size_t i = 0; /* counter */
|
||||
size_t o = 0; /* operands */
|
||||
size_t c = 0; /* copy */
|
||||
char *t = NULL; /* token */
|
||||
|
||||
/*
|
||||
* Most ops a single statement can have is three.
|
||||
* lets allocate some space for all of those here.
|
||||
*/
|
||||
char op[3][32768] = {{0},{0},{0}};
|
||||
for (; i < sizeof(asm_instr)/sizeof(*asm_instr); i++) {
|
||||
if (!strncmp(skip, asm_instr[i].m, asm_instr[i].l)) {
|
||||
if (state != ASM_FUNCTION) {
|
||||
printf("%li: Statement not inside function block\n", line);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* update parser state */
|
||||
if (i == INSTR_DONE || i == INSTR_RETURN) {
|
||||
goto end;
|
||||
state = ASM_NULL;
|
||||
}
|
||||
|
||||
/* parse the statement */
|
||||
c = i;
|
||||
o = asm_instr[i].o; /* operands */
|
||||
skip += asm_instr[i].l; /* skip instruction */
|
||||
t = strtok(skip, " ,");
|
||||
i = 0;
|
||||
while (t != NULL && i < 3) {
|
||||
strcpy(op[i], t);
|
||||
t = strtok(NULL, " ,");
|
||||
i ++;
|
||||
}
|
||||
|
||||
/* check */
|
||||
if (i != o) {
|
||||
printf("not enough operands, expected: %li, got %li\n", o, i);
|
||||
}
|
||||
|
||||
/* TODO: hashtable value LOAD .... etc */
|
||||
code_statements_add((prog_section_statement){
|
||||
c,
|
||||
{ atof(op[0]) },
|
||||
{ atof(op[1]) },
|
||||
{ atof(op[2]) }
|
||||
});
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* if we made it this far something is wrong */
|
||||
if (*skip != '\0')
|
||||
printf("%li: Invalid statement %s, expression, or decleration\n", line, skip);
|
||||
|
||||
end:
|
||||
/* TODO: everything */
|
||||
(void)state;
|
||||
goto end;
|
||||
end:
|
||||
mem_d(data);
|
||||
line ++;
|
||||
}
|
||||
|
|
1
gmqcc.h
1
gmqcc.h
|
@ -197,6 +197,7 @@ void util_meminfo ();
|
|||
char *util_strdup (const char *);
|
||||
char *util_strrq (char *);
|
||||
char *util_strrnl (char *);
|
||||
char *util_strsws (char *);
|
||||
void util_debug (const char *, const char *, ...);
|
||||
int util_getline (char **, size_t *, FILE *);
|
||||
void util_endianswap (void *, int, int);
|
||||
|
|
15
util.c
15
util.c
|
@ -132,6 +132,21 @@ char *util_strrnl(char *src) {
|
|||
return src;
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes any whitespace prefixed on a string by moving
|
||||
* skipping past it, and stroing the skip distance, so
|
||||
* the string can later be freed (if it was allocated)
|
||||
*/
|
||||
char *util_strsws(char *skip) {
|
||||
size_t size = 0;
|
||||
if (!skip)
|
||||
return NULL;
|
||||
|
||||
while (*skip == ' ' || *skip == '\t')
|
||||
skip++,size++;
|
||||
return skip-size;
|
||||
}
|
||||
|
||||
void util_debug(const char *area, const char *ms, ...) {
|
||||
if (!opts_debug)
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue