/*\
* LBPP - A GNU Compiler Compiler (GCC) Liberty Basic Frontend
* Copyright (C) 2001 Anthony Liguori <ajl13@bellatlantic.net rel='nofollow' onclick='return false;'>
*
* LBPP 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.
*
* LBPP 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\*/
#include <string.h>
#include <stdio.h>
#include <assert.h rel='nofollow' onclick='return false;'>
#include <ctype.h>
#include "lbpp.h"
void translate_label(FILE *f, int i)
{
fprintf(f, "label_%d:\n", i);
fprintf(f, "setjmp(cxt->labels[%d].jmp);\n", i);
fprintf(f, "if (setting_labels)\n"
"{\n"
" goto label_%d;\n"
"}\n", i + 1);
}
void translate_assignment(FILE *f, char *ptr)
{
char *asgn = ptr;
char *name = ptr;
char *end = skip_symbol(ptr);
int i = 0;
if (!strncasecmp(name, LET_STR, end - name) &&
(strlen(LET_STR) == end - name))
{
name = skip_space(end);
}
i = lookup_variable(name);
if (i == -1)
{
i = add_variable(name);
}
asgn = skip_symbol(name);
asgn = skip_space(asgn);
asgn = skip_param(asgn);
asgn = skip_space(asgn);
assert(*asgn == '=');
asgn = skip_space(++asgn);
if (var_table[i].type == DOUBLE)
{
translate_variable(f, name);
fprintf(f, " = ");
translate_expr(f, asgn);
asgn = skip_expr(asgn);
fprintf(f, ";\n");
}
else if (var_table[i].type == STRING)
{
fprintf(f, "lbstr_set(&(");
translate_variable(f, name);
fprintf(f, "),");
translate_string(f, asgn);
asgn = skip_string(asgn);
fprintf(f, ");\n");
}
else
{
fprintf(f, "Unknown lvalue type: %s\n", ptr);
}
asgn = skip_space(asgn);
if (*asgn == ':')
{
translate_line(f, asgn + 1);
}
}
int match_statement(char *buf, Statement *stmt)
{
char *ptr = buf;
char *end = skip_symbol(ptr);
int i;
if (!strncasecmp(ptr, stmt->name, (end - ptr)) &&
(strlen(stmt->name) == (end - ptr)))
{
ptr = skip_space(end);
for (i = 0; *ptr && i < stmt->arg_size; i++)
{
if (stmt->arg[i].literal)
{
end = ptr + strlen(stmt->arg[i].arg.string);
if (strncasecmp(ptr, stmt->arg[i].arg.string, end - ptr) ||
strlen(stmt->arg[i].arg.string) != end - ptr)
{
break;
}
ptr = end;
}
else
{
if (stmt->arg[i].arg.type != VAR_ARG && stmt->arg[i].reference)
{
ptr = skip_symbol(ptr);
ptr = skip_space(ptr);
ptr = skip_param(ptr);
}
else
{
switch (stmt->arg[i].arg.type)
{
case STRING:
ptr = skip_string(ptr);
break;
case DOUBLE:
ptr = skip_expr(ptr);
break;
case HANDLE:
if (*ptr == '#')
{
ptr = skip_symbol(++ptr);
}
break;
case KEYWORD:
ptr = skip_symbol(ptr);
break;
case LABEL:
if (*ptr == '[')
{
ptr = strchr(ptr, ']') + 1;
}
break;
case VAR_ARG:
ptr = skip_vararg(ptr);
break;
default:
break;
}
}
}
ptr = skip_space(ptr);
}
if (i == stmt->arg_size)
{
ptr = skip_space(ptr);
if (!*ptr || *ptr == '\'' || *ptr == ':')
{
stmt->dirty = 1;
return 1;
}
}
}
return 0;
}
void translate_vararg(FILE *f, char *buf)
{
char *ptr = buf;
Type type = UNKNOWN;
peek_expr(ptr, &type);
if (type == STRING)
{
fprintf(f, "lb_va_adds(");
translate_string(f, ptr);
ptr = skip_string(ptr);
}
else if (type == DOUBLE)
{
fprintf(f, "lb_va_addd(");
translate_expr(f, ptr);
ptr = skip_expr(ptr);
}
else
{
fprintf(f, "lb_va_end(VA_END_SOFT)");
return;
}
ptr = skip_space(ptr);
if (*ptr == ';')
{
fprintf(f, ", ");
translate_vararg(f, skip_space(++ptr));
fprintf(f, ")");
}
else
{
fprintf(f, ", lb_va_end(VA_END_HARD))");
}
}
void translate_vararg_ref(FILE *f, char *buf)
{
char *ptr = buf;
int i = lookup_variable(buf);
if (i == -1)
{
i = add_variable(buf);
}
fprintf(f, "lb_va_addv(&(cxt->vars[%d]), ", i);
ptr = skip_symbol(ptr);
ptr = skip_space(ptr);
if (*ptr == ',')
{
translate_vararg_ref(f, skip_space(++ptr));
}
else
{
fprintf(f, "lb_va_end(VA_END_SOFT)");
}
fprintf(f, ")");
}
void translate_statement(FILE *f, char *buf)
{
char *ptr = buf;
int i;
for (i = 0; i < statement_table_size; i++)
{
if (match_statement(ptr, &statement_table[i]))
{
break;
}
}
if (i == statement_table_size)
{
char *end = skip_symbol(ptr);
if (!strncasecmp(ptr, "IF", 2) &&
((end - ptr) == 2))
{
ptr = skip_space(ptr + 2);
end = skip_bool(ptr);
fprintf(f, "if (");
translate_bool(f, ptr);
fprintf(f, ")\n{\n");
ptr = skip_space(end);
end = skip_symbol(ptr);
assert(!strncasecmp(ptr, "THEN", 4) && ((end - ptr) == 4));
ptr = skip_space(end);
if (*ptr)
{
translate_line(f, ptr);
fprintf(f, "}\n");
}
}
else if (!strncasecmp(ptr, "WHILE", 5) &&
((end - ptr) == 5))
{
ptr = skip_space(ptr + 5);
end = skip_bool(ptr);
fprintf(f, "while (");
translate_bool(f, ptr);
fprintf(f, ")\n{\n");
ptr = skip_space(end);
}
else
{
fprintf(f, "#error %s\n", ptr);
}
}
else
{
if (!strcasecmp(statement_table[i].name, "GOTO"))
{
char *label = skip_symbol(ptr);
int j = 0;
label = skip_space(label);
j = lookup_label(label);
if (j == -1)
{
j = add_label(label);
}
fprintf(f, "longjmp(cxt->labels[%d].jmp, 1);\n", j);
ptr = skip_space(skip_symbol(label + 1) + 1);
}
else if (!strcasecmp(statement_table[i].name, "GOSUB"))
{
char *label = skip_symbol(ptr);
int j = 0;
label = skip_space(label);
j = lookup_label(label);
if (j == -1)
{
j = add_label(label);
}
fprintf(f, "if (setjmp(tmp_jmp) == 0) {\n");
fprintf(f, " lb_push_label(cxt, &tmp_jmp);\n");
fprintf(f, " longjmp(cxt->labels[%d].jmp, 1);\n}\n", j);
ptr = skip_space(skip_symbol(label + 1) + 1);
}
else if (!strcasecmp(statement_table[i].name, "RETURN"))
{
fprintf(f, "lb_pop_label(cxt, &tmp_jmp);\n");
fprintf(f, "longjmp(tmp_jmp, 1);\n");
ptr = skip_space(skip_symbol(ptr));
}
else if (!strcasecmp(statement_table[i].name, "FOR"))
{
char *lvalue;
char *double1;
char *double2;
char *double3 = "1";
// This formula needs to be simplified! Big time...
// FOR <lvalue> = <double> TO <double> [STEP <double>]
// for (%1 = %2;
// %1 != (double)((int)((%3 - %2) / %4)) * %4 + %4 + %2;
// %1 += %4)
lvalue = ptr = skip_space(skip_symbol(ptr));
ptr = skip_space(skip_param(skip_space(skip_symbol(ptr))));
ptr = skip_space(++ptr);
double1 = ptr;
ptr = skip_space(skip_expr(ptr));
ptr = skip_space(skip_symbol(ptr));
double2 = ptr;
ptr = skip_space(skip_expr(ptr));
if (statement_table[i].arg_size == 7)
{
ptr = skip_space(skip_symbol(ptr));
double3 = ptr;
}
fprintf(f, "for (");
translate_variable(f, lvalue);
fprintf(f, " = ");
translate_expr(f, double1);
fprintf(f, "; ");
translate_variable(f, lvalue);
fprintf(f, " != (double)((int)((");
translate_expr(f, double2);
fprintf(f, " - ");
translate_expr(f, double1);
fprintf(f, ") / ");
transla