2007-12-30 17:41:49 +01:00
|
|
|
|
/***************************************************************************
|
|
|
|
|
|
2009-08-17 12:41:51 +02:00
|
|
|
|
gb_code_temp.h
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2009-08-17 12:41:51 +02:00
|
|
|
|
(c) 2000-2009 Benoît Minisini <gambas@users.sourceforge.net>
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
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
|
2009-08-17 12:41:51 +02:00
|
|
|
|
the Free Software Foundation; either version 2, or (at your option)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
|
|
//#define DEBUG
|
|
|
|
|
|
|
|
|
|
#define write_Zxxx(code, val) write_short(code | ((short)val & 0x0FFF))
|
|
|
|
|
#define write_Z8xx(code, val) write_short(code | ((short)val & 0x07FF))
|
|
|
|
|
#define write_ZZxx(code, val) write_short(code | ((short)val & 0x00FF))
|
|
|
|
|
|
2010-05-29 23:10:36 +02:00
|
|
|
|
#ifndef PROJECT_EXEC
|
|
|
|
|
#define LAST_CODE \
|
|
|
|
|
{ \
|
|
|
|
|
if (JOB->debug && !JOB->nobreak) \
|
|
|
|
|
CODE_break(); \
|
|
|
|
|
cur_func->last_code2 = cur_func->last_code; \
|
|
|
|
|
cur_func->last_code = cur_func->ncode; \
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
#define LAST_CODE \
|
|
|
|
|
{ \
|
|
|
|
|
cur_func->last_code2 = cur_func->last_code; \
|
|
|
|
|
cur_func->last_code = cur_func->ncode; \
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
short CODE_stack_usage;
|
|
|
|
|
short CODE_stack;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
static bool _ignore_next_stack_usage = FALSE;
|
|
|
|
|
|
|
|
|
|
#ifdef PROJECT_EXEC
|
|
|
|
|
#define cur_func EVAL
|
|
|
|
|
#else
|
|
|
|
|
static FUNCTION *cur_func = NULL;
|
|
|
|
|
static int last_line = 0;
|
|
|
|
|
#endif
|
|
|
|
|
|
2010-05-22 20:02:34 +02:00
|
|
|
|
static void alloc_code(void)
|
|
|
|
|
{
|
|
|
|
|
cur_func->ncode_max += CODE_INSTR_INC;
|
|
|
|
|
if (!cur_func->code)
|
|
|
|
|
ALLOC(&cur_func->code, sizeof(short) * CODE_INSTR_INC, "alloc_code");
|
|
|
|
|
else
|
|
|
|
|
REALLOC(&cur_func->code, sizeof(short) * cur_func->ncode_max, "alloc_code");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//static void INLINE write_short(short value)
|
|
|
|
|
#define write_short(_value) \
|
|
|
|
|
({ \
|
|
|
|
|
if (cur_func->ncode >= cur_func->ncode_max) \
|
|
|
|
|
alloc_code(); \
|
|
|
|
|
\
|
|
|
|
|
cur_func->code[cur_func->ncode] = _value; \
|
|
|
|
|
/*fprintf(stderr, "[%d] %04hX\n", cur_func->ncode, (ushort)value);*/ \
|
|
|
|
|
cur_func->ncode++; \
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
#ifdef PROJECT_COMP
|
|
|
|
|
|
|
|
|
|
static bool _allow_break = FALSE;
|
|
|
|
|
|
|
|
|
|
void CODE_allow_break(void)
|
|
|
|
|
{
|
|
|
|
|
_allow_break = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void CODE_break(void)
|
|
|
|
|
{
|
|
|
|
|
if (!_allow_break)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/*if (last_line < 0)
|
|
|
|
|
{
|
|
|
|
|
if (CODE_get_current_pos())
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (JOB->line == last_line)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
last_line = JOB->line;
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("BREAK\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_short(C_BREAK);
|
|
|
|
|
_allow_break = FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
|
2008-01-05 15:07:21 +01:00
|
|
|
|
static void write_int(int value)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
write_short(value & 0xFFFF);
|
2008-01-05 15:07:21 +01:00
|
|
|
|
write_short((unsigned int)value >> 16);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*static void remove_last(void)
|
|
|
|
|
{
|
|
|
|
|
ARRAY_remove_last(&cur_func->code);
|
|
|
|
|
cur_func->last_code = ARRAY_count(cur_func->code);
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void use_stack(int use)
|
|
|
|
|
{
|
|
|
|
|
if (_ignore_next_stack_usage)
|
|
|
|
|
{
|
|
|
|
|
_ignore_next_stack_usage = FALSE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CODE_stack += use;
|
|
|
|
|
CODE_stack_usage = Max(CODE_stack_usage, CODE_stack);
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("%04ld: %d\n", cur_func->ncode, CODE_stack);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2008-03-17 15:54:17 +01:00
|
|
|
|
static void CODE_undo()
|
|
|
|
|
{
|
|
|
|
|
cur_func->ncode = cur_func->last_code;
|
|
|
|
|
cur_func->last_code = cur_func->last_code2;
|
|
|
|
|
cur_func->last_code2 = (-1);
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
int CODE_get_current_pos(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
return cur_func->ncode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_ignore_next_stack_usage(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
_ignore_next_stack_usage = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef PROJECT_EXEC
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_begin_function()
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
CODE_stack = 0;
|
|
|
|
|
CODE_stack_usage = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_end_function()
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
if (CODE_stack)
|
|
|
|
|
THROW("Internal compiler error: Bad stack usage computed!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_begin_function(FUNCTION *func)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
cur_func = func;
|
|
|
|
|
CODE_stack = 0;
|
|
|
|
|
CODE_stack_usage = 0;
|
|
|
|
|
if (func->start == NULL)
|
|
|
|
|
last_line = (-1);
|
|
|
|
|
else
|
|
|
|
|
last_line = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_end_function(FUNCTION *func)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
if (CODE_stack)
|
|
|
|
|
THROW("Internal compiler error: Bad stack usage computed!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static ushort *get_last_code()
|
|
|
|
|
{
|
|
|
|
|
if (cur_func->last_code < 0)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return &cur_func->code[cur_func->last_code];
|
|
|
|
|
}
|
|
|
|
|
|
2008-03-17 15:54:17 +01:00
|
|
|
|
static ushort *get_last_code2()
|
|
|
|
|
{
|
|
|
|
|
if (cur_func->last_code2 < 0)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return &cur_func->code[cur_func->last_code2];
|
|
|
|
|
}
|
|
|
|
|
|
[DEVELOPMENT ENVIRONMENT]
* BUG: Use TextEdit.RichText insted of TextEdit.Text.
* BUG: END SUB can be the end of a method. The class analyze now takes
that into account.
[HELP]
* BUG: Fixed the generated treeview.
[COMPILER]
* OPT: The NOT operator used just at the beginning of a conditional
expression is optimized. Consequently, an expression like 'IF NOT 2' is
now equivalent to 'IF 2 = 0' and not to 'IF (NOT 2) <> 0' as before. In
other words, the boolean conversion is now done before the NOT, and not
after. The following instructions are concerned: IF, WHILE, UNTIL.
* NEW: BYREF is new keyword that is a more readable synonymous of '@'.
[GB.DB.FORM]
* BUG: Correctly manage data controls inside TabStrip-like containers.
* BUG: Setting the focus on a non-initialized DataControl does not raise
an error anymore.
[GB.GTK]
* BUG: HSplitter.Layout and VSplitter.Layout now work correctly. It is a
list of children widths, hidden children having a zero width.
* BUG: Window arrangement is done before the Open event is raised, as in
gb.qt.
* BUG: Keyboard, focus and mouse events now work correctly on Window and
DrawingArea controls.
[GB.QT]
* BUG: HSplitter.Layout and VSplitter.Layout now work correctly. It is a
list of children widths, hidden children having a zero width.
* BUG: Many warning fixes.
* BUG: Now the Control.Visible property works like in gb.gtk, i.e. it
returns if the control was not explicitely hidden.
git-svn-id: svn://localhost/gambas/trunk@1060 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2008-02-06 01:25:48 +01:00
|
|
|
|
bool CODE_popify_last(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("CODE_is_last_popable ? ");
|
|
|
|
|
if (!last_code) printf("FALSE, last_code = NULL");
|
|
|
|
|
else printf("0x%04hX", *last_code);
|
|
|
|
|
printf("\n");
|
|
|
|
|
#endif
|
|
|
|
|
*/
|
|
|
|
|
unsigned short *last_code, op;
|
|
|
|
|
|
|
|
|
|
last_code = get_last_code();
|
|
|
|
|
if (!last_code)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
op = *last_code & 0xFF00;
|
|
|
|
|
|
|
|
|
|
if ((op >= C_PUSH_LOCAL) && (op <= C_PUSH_UNKNOWN))
|
|
|
|
|
{
|
|
|
|
|
*last_code += 0x0800;
|
|
|
|
|
use_stack(-2);
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("Popify Last\n");
|
|
|
|
|
#endif
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((op & 0xF000) == C_PUSH_DYNAMIC)
|
|
|
|
|
{
|
|
|
|
|
*last_code += 0x1000;
|
|
|
|
|
use_stack(-2);
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("Popify Last\n");
|
|
|
|
|
#endif
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2010-12-21 15:05:42 +01:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
if (*last_code == (C_PUSH_MISC | CPM_LAST))
|
|
|
|
|
{
|
|
|
|
|
*last_code = C_PUSH_MISC | CPM_POP_LAST;
|
|
|
|
|
use_stack(-2);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
*/
|
2007-12-30 17:41:49 +01:00
|
|
|
|
/*
|
|
|
|
|
if (op == C_CALL)
|
|
|
|
|
{
|
|
|
|
|
*last_code = C_CALL_POP | (*last_code & 0xFF);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-05-27 00:34:39 +02:00
|
|
|
|
#ifdef PROJECT_COMP
|
|
|
|
|
|
[DEVELOPMENT ENVIRONMENT]
* BUG: Use TextEdit.RichText insted of TextEdit.Text.
* BUG: END SUB can be the end of a method. The class analyze now takes
that into account.
[HELP]
* BUG: Fixed the generated treeview.
[COMPILER]
* OPT: The NOT operator used just at the beginning of a conditional
expression is optimized. Consequently, an expression like 'IF NOT 2' is
now equivalent to 'IF 2 = 0' and not to 'IF (NOT 2) <> 0' as before. In
other words, the boolean conversion is now done before the NOT, and not
after. The following instructions are concerned: IF, WHILE, UNTIL.
* NEW: BYREF is new keyword that is a more readable synonymous of '@'.
[GB.DB.FORM]
* BUG: Correctly manage data controls inside TabStrip-like containers.
* BUG: Setting the focus on a non-initialized DataControl does not raise
an error anymore.
[GB.GTK]
* BUG: HSplitter.Layout and VSplitter.Layout now work correctly. It is a
list of children widths, hidden children having a zero width.
* BUG: Window arrangement is done before the Open event is raised, as in
gb.qt.
* BUG: Keyboard, focus and mouse events now work correctly on Window and
DrawingArea controls.
[GB.QT]
* BUG: HSplitter.Layout and VSplitter.Layout now work correctly. It is a
list of children widths, hidden children having a zero width.
* BUG: Many warning fixes.
* BUG: Now the Control.Visible property works like in gb.gtk, i.e. it
returns if the control was not explicitely hidden.
git-svn-id: svn://localhost/gambas/trunk@1060 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2008-02-06 01:25:48 +01:00
|
|
|
|
bool CODE_check_statement_last(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
unsigned short op;
|
|
|
|
|
PCODE *last_code;
|
|
|
|
|
|
|
|
|
|
last_code = get_last_code();
|
|
|
|
|
if (!last_code)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
op = *last_code & 0xFF00;
|
|
|
|
|
|
|
|
|
|
if (op == C_CALL)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
op >>= 8;
|
|
|
|
|
|
|
|
|
|
if (op >= CODE_FIRST_SUBR && op <= CODE_LAST_SUBR)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
[DEVELOPMENT ENVIRONMENT]
* BUG: Use TextEdit.RichText insted of TextEdit.Text.
* BUG: END SUB can be the end of a method. The class analyze now takes
that into account.
[HELP]
* BUG: Fixed the generated treeview.
[COMPILER]
* OPT: The NOT operator used just at the beginning of a conditional
expression is optimized. Consequently, an expression like 'IF NOT 2' is
now equivalent to 'IF 2 = 0' and not to 'IF (NOT 2) <> 0' as before. In
other words, the boolean conversion is now done before the NOT, and not
after. The following instructions are concerned: IF, WHILE, UNTIL.
* NEW: BYREF is new keyword that is a more readable synonymous of '@'.
[GB.DB.FORM]
* BUG: Correctly manage data controls inside TabStrip-like containers.
* BUG: Setting the focus on a non-initialized DataControl does not raise
an error anymore.
[GB.GTK]
* BUG: HSplitter.Layout and VSplitter.Layout now work correctly. It is a
list of children widths, hidden children having a zero width.
* BUG: Window arrangement is done before the Open event is raised, as in
gb.qt.
* BUG: Keyboard, focus and mouse events now work correctly on Window and
DrawingArea controls.
[GB.QT]
* BUG: HSplitter.Layout and VSplitter.Layout now work correctly. It is a
list of children widths, hidden children having a zero width.
* BUG: Many warning fixes.
* BUG: Now the Control.Visible property works like in gb.gtk, i.e. it
returns if the control was not explicitely hidden.
git-svn-id: svn://localhost/gambas/trunk@1060 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2008-02-06 01:25:48 +01:00
|
|
|
|
bool CODE_check_pop_local_last(short *local)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
PCODE *last_code;
|
|
|
|
|
|
|
|
|
|
last_code = get_last_code();
|
|
|
|
|
if (!last_code)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if ((*last_code & 0xFF00) == C_POP_LOCAL)
|
|
|
|
|
{
|
|
|
|
|
*local = *last_code & 0xFF;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
[DEVELOPMENT ENVIRONMENT]
* BUG: Use TextEdit.RichText insted of TextEdit.Text.
* BUG: END SUB can be the end of a method. The class analyze now takes
that into account.
[HELP]
* BUG: Fixed the generated treeview.
[COMPILER]
* OPT: The NOT operator used just at the beginning of a conditional
expression is optimized. Consequently, an expression like 'IF NOT 2' is
now equivalent to 'IF 2 = 0' and not to 'IF (NOT 2) <> 0' as before. In
other words, the boolean conversion is now done before the NOT, and not
after. The following instructions are concerned: IF, WHILE, UNTIL.
* NEW: BYREF is new keyword that is a more readable synonymous of '@'.
[GB.DB.FORM]
* BUG: Correctly manage data controls inside TabStrip-like containers.
* BUG: Setting the focus on a non-initialized DataControl does not raise
an error anymore.
[GB.GTK]
* BUG: HSplitter.Layout and VSplitter.Layout now work correctly. It is a
list of children widths, hidden children having a zero width.
* BUG: Window arrangement is done before the Open event is raised, as in
gb.qt.
* BUG: Keyboard, focus and mouse events now work correctly on Window and
DrawingArea controls.
[GB.QT]
* BUG: HSplitter.Layout and VSplitter.Layout now work correctly. It is a
list of children widths, hidden children having a zero width.
* BUG: Many warning fixes.
* BUG: Now the Control.Visible property works like in gb.gtk, i.e. it
returns if the control was not explicitely hidden.
git-svn-id: svn://localhost/gambas/trunk@1060 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2008-02-06 01:25:48 +01:00
|
|
|
|
bool CODE_check_jump_not(void)
|
|
|
|
|
{
|
|
|
|
|
ushort op;
|
|
|
|
|
PCODE *last_code = get_last_code();
|
|
|
|
|
|
|
|
|
|
if (!last_code)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
op = *last_code & 0xFF00;
|
|
|
|
|
if (op != C_NOT)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2008-03-17 15:54:17 +01:00
|
|
|
|
CODE_undo();
|
[DEVELOPMENT ENVIRONMENT]
* BUG: Use TextEdit.RichText insted of TextEdit.Text.
* BUG: END SUB can be the end of a method. The class analyze now takes
that into account.
[HELP]
* BUG: Fixed the generated treeview.
[COMPILER]
* OPT: The NOT operator used just at the beginning of a conditional
expression is optimized. Consequently, an expression like 'IF NOT 2' is
now equivalent to 'IF 2 = 0' and not to 'IF (NOT 2) <> 0' as before. In
other words, the boolean conversion is now done before the NOT, and not
after. The following instructions are concerned: IF, WHILE, UNTIL.
* NEW: BYREF is new keyword that is a more readable synonymous of '@'.
[GB.DB.FORM]
* BUG: Correctly manage data controls inside TabStrip-like containers.
* BUG: Setting the focus on a non-initialized DataControl does not raise
an error anymore.
[GB.GTK]
* BUG: HSplitter.Layout and VSplitter.Layout now work correctly. It is a
list of children widths, hidden children having a zero width.
* BUG: Window arrangement is done before the Open event is raised, as in
gb.qt.
* BUG: Keyboard, focus and mouse events now work correctly on Window and
DrawingArea controls.
[GB.QT]
* BUG: HSplitter.Layout and VSplitter.Layout now work correctly. It is a
list of children widths, hidden children having a zero width.
* BUG: Many warning fixes.
* BUG: Now the Control.Visible property works like in gb.gtk, i.e. it
returns if the control was not explicitely hidden.
git-svn-id: svn://localhost/gambas/trunk@1060 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2008-02-06 01:25:48 +01:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
|
#endif
|
|
|
|
|
|
2008-01-19 02:36:38 +01:00
|
|
|
|
bool CODE_check_varptr(void)
|
|
|
|
|
{
|
|
|
|
|
unsigned short op;
|
|
|
|
|
PCODE *last_code;
|
|
|
|
|
|
|
|
|
|
last_code = get_last_code();
|
|
|
|
|
if (!last_code)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
op = *last_code;
|
|
|
|
|
if (!((op & 0xFF00) == C_PUSH_LOCAL || (op & 0xFF00) == C_PUSH_PARAM || (op & 0xF800) == C_PUSH_STATIC || (op & 0xF800) == C_PUSH_DYNAMIC))
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
*last_code = C_PUSH_INTEGER;
|
|
|
|
|
write_short((short)op);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_push_number(int value)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
|
|
|
|
|
if (value >= -2048L && value < 2048L)
|
|
|
|
|
{
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH QUICK %ld\n", value);
|
|
|
|
|
#endif
|
|
|
|
|
write_Zxxx(C_PUSH_QUICK, value);
|
|
|
|
|
}
|
|
|
|
|
else if (value >= -32768L && value < 32768L)
|
|
|
|
|
{
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH INTEGER %ld\n", value);
|
|
|
|
|
#endif
|
|
|
|
|
write_short(C_PUSH_INTEGER);
|
|
|
|
|
write_short((short)value);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH LONG %ld\n", value);
|
|
|
|
|
#endif
|
|
|
|
|
write_short(C_PUSH_LONG);
|
2008-01-05 15:07:21 +01:00
|
|
|
|
write_int(value);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-12-20 04:56:43 +01:00
|
|
|
|
void CODE_push_const(ushort value)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH CONST %d %s\n", value, TABLE_get_symbol_name(JOB->class->table, JOB->class->constant[value].index));
|
|
|
|
|
#endif
|
2010-12-20 04:56:43 +01:00
|
|
|
|
|
|
|
|
|
if (value < 0xF00)
|
|
|
|
|
write_Zxxx(C_PUSH_CONST, value);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
write_Zxxx(C_PUSH_CONST, 0xF00);
|
|
|
|
|
write_short((short)value);
|
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_push_local(short num)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
if (num >= 0)
|
|
|
|
|
printf("PUSH LOCAL %d\n", num);
|
|
|
|
|
else
|
|
|
|
|
printf("PUSH PARAM %d\n", (-1) - num);
|
|
|
|
|
#endif
|
|
|
|
|
if (num >= 0)
|
|
|
|
|
write_ZZxx(C_PUSH_LOCAL, num);
|
|
|
|
|
else
|
|
|
|
|
write_ZZxx(C_PUSH_PARAM, num);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef PROJECT_COMP
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_pop_local(short num)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(-1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
if (num >= 0)
|
|
|
|
|
printf("POP LOCAL #%d\n", num);
|
|
|
|
|
else
|
|
|
|
|
printf("POP PARAM #%d\n", (-1) - num);
|
|
|
|
|
#endif
|
|
|
|
|
if (num >= 0)
|
|
|
|
|
write_ZZxx(C_POP_LOCAL, num);
|
|
|
|
|
else
|
|
|
|
|
write_ZZxx(C_POP_PARAM, num);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_pop_ctrl(short num)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(-1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("POP CTRL #%d\n", num);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_POP_CTRL, num);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_pop_optional(short num)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(-1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("POP OPTIONAL #%d\n", (-1) - num);
|
|
|
|
|
#endif
|
|
|
|
|
write_ZZxx(C_POP_OPTIONAL, num);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* PROJECT_COMP */
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_push_array(short nparam)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1 - nparam);
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_PUSH_ARRAY, nparam);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-07-08 21:57:50 +02:00
|
|
|
|
void CODE_push_global(short global, bool is_static, bool is_function)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH %s %d\n", is_static ? "STATIC" : "DYNAMIC", global);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (is_function)
|
|
|
|
|
write_Z8xx(C_PUSH_FUNCTION, global);
|
|
|
|
|
else if (is_static)
|
|
|
|
|
write_Z8xx(C_PUSH_STATIC, global);
|
|
|
|
|
else
|
|
|
|
|
write_Z8xx(C_PUSH_DYNAMIC, global);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef PROJECT_COMP
|
|
|
|
|
|
2009-07-08 21:57:50 +02:00
|
|
|
|
void CODE_pop_global(short global, bool is_static)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(-1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("POP %s %d\n", is_static ? "STATIC" : "DYNAMIC", global);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (is_static)
|
|
|
|
|
write_Z8xx(C_POP_STATIC, global);
|
|
|
|
|
else
|
|
|
|
|
write_Z8xx(C_POP_DYNAMIC, global);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_push_symbol(short symbol)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(0);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH SYMBOL %s\n", TABLE_get_symbol_name(JOB->class->table, symbol));
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_short(C_PUSH_SYMBOL);
|
|
|
|
|
write_short(symbol);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_pop_symbol(short symbol)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(-2);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("POP SYMBOL %s\n", TABLE_get_symbol_name(JOB->class->table, symbol));
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_short(C_POP_SYMBOL);
|
|
|
|
|
write_short(symbol);
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_push_unknown(short symbol)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(0);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH UNKNOWN %s\n", TABLE_get_symbol_name(JOB->class->table, symbol));
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_short(C_PUSH_UNKNOWN);
|
|
|
|
|
write_short(symbol);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef PROJECT_COMP
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_pop_unknown(short symbol)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(-2);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("POP UNKNOWN %s\n", TABLE_get_symbol_name(JOB->class->table, symbol));
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_short(C_POP_UNKNOWN);
|
|
|
|
|
write_short(symbol);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_push_class(short class)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH CLASS %d\n", class);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_Z8xx(C_PUSH_CLASS, class);
|
|
|
|
|
|
|
|
|
|
#ifdef PROJECT_COMP
|
|
|
|
|
JOB->class->class[class].used = TRUE;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef PROJECT_COMP
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_jump()
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("JUMP\n");
|
|
|
|
|
#endif
|
|
|
|
|
write_short(C_JUMP);
|
|
|
|
|
/**pos = CODE_get_current_pos();*/
|
|
|
|
|
write_short(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_jump_if_true()
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
ushort *last_code = get_last_code();
|
|
|
|
|
ushort op;
|
|
|
|
|
|
|
|
|
|
if (last_code && PCODE_is(*last_code, C_NOT))
|
|
|
|
|
{
|
|
|
|
|
remove_last();
|
|
|
|
|
op = C_JUMP_IF_FALSE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
op = C_JUMP_IF_TRUE;
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
use_stack(-1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("JUMP IF TRUE\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
write_short(C_JUMP_IF_TRUE);
|
|
|
|
|
/**pos = CODE_get_current_pos();*/
|
|
|
|
|
write_short(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_jump_if_false()
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
ushort *last_code = get_last_code();
|
|
|
|
|
ushort op;
|
|
|
|
|
|
|
|
|
|
if (last_code && PCODE_is(*last_code, C_NOT))
|
|
|
|
|
{
|
|
|
|
|
remove_last();
|
|
|
|
|
op = C_JUMP_IF_TRUE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
op = C_JUMP_IF_FALSE;
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
use_stack(-1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("JUMP IF FALSE\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
write_short(C_JUMP_IF_FALSE);
|
|
|
|
|
/**pos = CODE_get_current_pos();*/
|
|
|
|
|
write_short(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_jump_first(short local)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(-2);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("JUMP FIRST LOCAL %d\n", local);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_JUMP_FIRST, local);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_jump_next(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("JUMP NEXT\n");
|
|
|
|
|
#endif
|
|
|
|
|
write_short(C_JUMP_NEXT);
|
|
|
|
|
/**pos = CODE_get_current_pos();*/
|
|
|
|
|
write_short(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_jump_length(short src, short dst)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
if (src < 0 || src >= (cur_func->ncode - 1))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
if (dst < 0 || dst > (ARRAY_length(cur_func->code)))
|
|
|
|
|
return;
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (cur_func->code[src] == C_BREAK)
|
|
|
|
|
cur_func->code[src + 2] = dst - (src + 2) - 1;
|
|
|
|
|
else
|
|
|
|
|
cur_func->code[src + 1] = dst - (src + 1) - 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_first(short local)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(-1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("ENUM FIRST LOCAL %d\n", local);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_FIRST, local);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_next(bool drop)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(drop ? 0 : 1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("ENUM NEXT%s\n", drop ? " DROP" : "");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_NEXT, drop ? 1 : 0);
|
|
|
|
|
write_short(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* PROJECT_COMP */
|
|
|
|
|
|
2009-09-27 11:28:52 +02:00
|
|
|
|
void CODE_op(short op, short subcode, short nparam, bool fixed)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
if (op == C_ADD || op == C_SUB)
|
|
|
|
|
{
|
2008-03-17 15:54:17 +01:00
|
|
|
|
PCODE *last_code;
|
|
|
|
|
short value, value2;
|
|
|
|
|
|
|
|
|
|
last_code = get_last_code();
|
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
|
if (last_code && ((*last_code & 0xF000) == C_PUSH_QUICK))
|
|
|
|
|
{
|
2008-03-17 15:54:17 +01:00
|
|
|
|
value = *last_code & 0xFFF;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
if (value >= 0x800) value |= 0xF000;
|
|
|
|
|
if (op == C_SUB) value = (-value);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("ADD QUICK %d\n", value);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
*last_code = C_ADD_QUICK | (value & 0x0FFF);
|
|
|
|
|
|
|
|
|
|
use_stack(1 - nparam);
|
2008-03-17 15:54:17 +01:00
|
|
|
|
|
|
|
|
|
// Now, look if we are PUSH QUICK then ADD QUICK
|
|
|
|
|
|
|
|
|
|
last_code = get_last_code2();
|
|
|
|
|
if (last_code && ((*last_code & 0xF000) == C_PUSH_QUICK))
|
|
|
|
|
{
|
|
|
|
|
value2 = *last_code & 0xFFF;
|
|
|
|
|
if (value2 >= 0x800) value2 |= 0xF000;
|
|
|
|
|
value += value2;
|
|
|
|
|
|
|
|
|
|
if (value >= -2048L && value < 2048L)
|
|
|
|
|
{
|
|
|
|
|
*last_code = C_PUSH_QUICK | (value & 0x0FFF);
|
|
|
|
|
CODE_undo();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1 - nparam);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("OP %d (%d)\n", op, nparam);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (fixed)
|
2009-09-27 11:28:52 +02:00
|
|
|
|
write_ZZxx(op, subcode);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
else
|
|
|
|
|
write_ZZxx(op, nparam);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_push_me(bool debug)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH ME\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_PUSH_ME, debug ? 1 : 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_push_super(bool debug)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH SUPER\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_PUSH_ME, debug ? 3 : 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_push_last()
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH LAST\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_PUSH_MISC, CPM_LAST);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_push_null()
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH NULL\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_PUSH_MISC, CPM_NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-09-17 22:58:27 +02:00
|
|
|
|
void CODE_push_void_string()
|
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH VOID STRING\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_PUSH_MISC, CPM_STRING);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
|
/*
|
2009-07-08 21:57:50 +02:00
|
|
|
|
static bool change_last_call(ushort flag)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
ushort *last_code = get_last_code();
|
|
|
|
|
|
|
|
|
|
if (!last_code)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if ((*last_code & 0xFF00) == C_CALL)
|
|
|
|
|
{
|
|
|
|
|
*last_code = *last_code | flag;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if ((ushort)((*last_code) & 0xFF00) >= (ushort)CODE_FIRST_SUBR)
|
|
|
|
|
{
|
|
|
|
|
*last_code = *last_code | flag;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if (((*last_code & 0xFF00) == C_DROP) && flag == CODE_CALL_DROP)
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_dup(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("DUP\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_short(C_DUP);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_return(int return_value)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
if (return_value)
|
|
|
|
|
{
|
|
|
|
|
use_stack(-1);
|
|
|
|
|
write_ZZxx(C_RETURN, return_value);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
write_ZZxx(C_RETURN, 0);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("RETURN (%d)\n", return_value ? 1 : 0);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef PROJECT_COMP
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_quit(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("QUIT\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_QUIT, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_stop(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("STOP\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_QUIT, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* PROJECT_COMP */
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_push_char(char car)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
write_ZZxx(C_PUSH_CHAR, car);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH CHAR %d\n", car);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_push_zero(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
write_short(C_PUSH_ZERO);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH ZERO\n");
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_push_void(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
write_ZZxx(C_PUSH_MISC, CPM_VOID);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH VOID\n");
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef PROJECT_COMP
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
/*void CODE_event(bool on)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_EVENT, on ? 1 : 0);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("EVENT %s\n", on ? "ON" : "OFF");
|
|
|
|
|
#endif
|
|
|
|
|
}*/
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_stop_event(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
2010-06-18 02:14:53 +02:00
|
|
|
|
write_ZZxx(C_QUIT, 2);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("STOP EVENT\n");
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
2009-07-08 21:57:50 +02:00
|
|
|
|
void CODE_subr(short subr, short nparam, short optype, bool output, bool fixed)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
if (output)
|
|
|
|
|
use_stack(0);
|
|
|
|
|
else
|
|
|
|
|
use_stack(1 - nparam);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("SUBR %s %d (%d)\n", output ? "OUTPUT" : "", subr, nparam);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (optype == 0)
|
|
|
|
|
{
|
|
|
|
|
if (fixed)
|
|
|
|
|
nparam = 0;
|
|
|
|
|
|
|
|
|
|
/*if (output)
|
|
|
|
|
nparam |= CODE_CALL_OUTPUT;*/
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
nparam = optype;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
subr += CODE_FIRST_SUBR;
|
|
|
|
|
write_short(((subr & 0xFF) << 8) | (nparam & 0xFF));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_subr_output(short subr, short nparam, int output)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(output - nparam);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("SUBR OUTPUT %d %d (%d)\n", output, subr, nparam);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
subr += CODE_FIRST_SUBR;
|
|
|
|
|
write_short(((subr & 0xFF) << 8) | (nparam & 0xFF));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_call(short nparam)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
/* Une case de pile de moins, car la valeur de retour
|
|
|
|
|
est stock<EFBFBD> <EFBFBD>la place de la fonction <EFBFBD>appeler */
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
use_stack(-nparam);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("CALL %s ( %d )\n", output ? "OUTPUT" : "", nparam);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_CALL, nparam);
|
2008-01-19 18:52:05 +01:00
|
|
|
|
}
|
|
|
|
|
|
2008-02-24 17:29:02 +01:00
|
|
|
|
void CODE_byref(uint64_t byref)
|
2008-01-19 18:52:05 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
2008-03-11 14:29:47 +01:00
|
|
|
|
int n;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("BYREF\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (byref >> 48)
|
|
|
|
|
n = 3;
|
|
|
|
|
else if (byref >> 32)
|
|
|
|
|
n = 2;
|
|
|
|
|
else if (byref >> 16)
|
|
|
|
|
n = 1;
|
|
|
|
|
else
|
|
|
|
|
n = 0;
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_BYREF, n);
|
|
|
|
|
while (n >= 0)
|
|
|
|
|
{
|
|
|
|
|
write_short(byref & 0xFFFF);
|
|
|
|
|
byref >>= 16;
|
|
|
|
|
n--;
|
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
2008-02-24 17:29:02 +01:00
|
|
|
|
void CODE_call_byref(short nparam, uint64_t byref)
|
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
int i, n;
|
|
|
|
|
|
|
|
|
|
use_stack(-nparam);
|
|
|
|
|
|
|
|
|
|
n = 0;
|
|
|
|
|
for (i = 0; i < nparam; i++)
|
|
|
|
|
{
|
|
|
|
|
if (byref & (1 << i))
|
|
|
|
|
n++;
|
|
|
|
|
}
|
|
|
|
|
use_stack(n);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("CALL ( %d )\n"nparam);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_CALL, nparam);
|
|
|
|
|
CODE_byref(byref);
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
/*void CODE_push_return(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
write_short(C_PUSH_RETURN);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH RETURN\n");
|
|
|
|
|
#endif
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef PROJECT_COMP
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_try(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
write_short(C_TRY);
|
|
|
|
|
write_short(0);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("TRY\n");
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_end_try(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
write_short(C_END_TRY);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("END TRY\n");
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_catch(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
write_short(C_CATCH);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("CATCH\n");
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_drop(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
2010-06-18 02:14:53 +02:00
|
|
|
|
//ushort *last_code = get_last_code();
|
|
|
|
|
//ushort subr;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
use_stack(-1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("DROP\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
2010-06-18 02:14:53 +02:00
|
|
|
|
/*if (last_code)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
switch(*last_code & 0xFF00)
|
|
|
|
|
{
|
|
|
|
|
case C_DROP:
|
|
|
|
|
*last_code = (*last_code & 0xFF00) + (*last_code & 0xFF) + 1;
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case C_CALL:
|
|
|
|
|
*last_code |= CODE_CALL_VOID;
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
subr = (*last_code) >> 8;
|
|
|
|
|
if (subr >= CODE_FIRST_SUBR && subr <= CODE_LAST_SUBR && (!(*last_code & CODE_CALL_VOID)))
|
|
|
|
|
{
|
|
|
|
|
*last_code |= CODE_CALL_VOID;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-06-18 02:14:53 +02:00
|
|
|
|
}*/
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-06-06 22:43:13 +02:00
|
|
|
|
//THROW("Internal compiler error: Bad stack drop!");
|
2010-06-05 01:48:53 +02:00
|
|
|
|
|
2010-06-06 22:43:13 +02:00
|
|
|
|
LAST_CODE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-06-06 22:43:13 +02:00
|
|
|
|
write_ZZxx(C_DROP, 1);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
/*void CODE_push_special(short spec)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(0);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH SPECIAL %d\n", spec);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_PUSH_SPECIAL, spec);
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifdef PROJECT_COMP
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_push_event(short event)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH EVENT %d\n", event);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_PUSH_EVENT, event);
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_push_extern(short index)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH EXTERN %d\n", index);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_PUSH_EXTERN, index);
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-08 21:57:50 +02:00
|
|
|
|
void CODE_new(ushort nparam, bool array, bool event)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1 - nparam);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("NEW %s (%d)\n", (array ? "ARRAY" : (event ? "EVENT" : "")), nparam);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (array)
|
|
|
|
|
nparam |= CODE_NEW_ARRAY;
|
|
|
|
|
|
|
|
|
|
if (event)
|
|
|
|
|
nparam |= CODE_NEW_EVENT;
|
|
|
|
|
|
|
|
|
|
write_ZZxx(C_NEW, nparam);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_push_boolean(bool value)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
LAST_CODE;
|
|
|
|
|
|
|
|
|
|
use_stack(1);
|
|
|
|
|
write_ZZxx(C_PUSH_MISC, value ? CPM_TRUE : CPM_FALSE);
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("PUSH %s\n", value ? "TRUE" : "FALSE");
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef CODE_DUMP
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
void CODE_dump(PCODE *code, int count)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < count;)
|
|
|
|
|
i += PCODE_dump(stdout, i, &code[i]);
|
|
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
|
/* void CODE_case(short local) */
|
2007-12-30 17:41:49 +01:00
|
|
|
|
/* { */
|
|
|
|
|
/* LAST_CODE; */
|
|
|
|
|
/* */
|
|
|
|
|
/* use_stack(0); */
|
|
|
|
|
/* */
|
|
|
|
|
/* #ifdef DEBUG */
|
|
|
|
|
/* printf("CASE (%d)\n", local); */
|
|
|
|
|
/* #endif */
|
|
|
|
|
/* */
|
|
|
|
|
/* write_ZZxx(C_CASE, local); */
|
|
|
|
|
/* } */
|