gambas-source-code/main/gbc/gbc_trans_subr.c
Benoît Minisini 9ccbaac697 [INTERPRETER]
* NEW: New API for returning the parent (event observer) of an object.

[COMPILER]
* BUG: Setting a property without having to use ME is possible now, if the
  property is defined in the same file of course.
* NEW: Mid$() can be used on the left side of an assignment.

[GB.FORM]
* BUG: ValueBox now reformats its contents after its Value property has 
  been set.

[GB.GTK]
* BUG: Composed keys are correctly handled again by KeyPress events, but
  the SCIM input method does not work yet.
* BUG: Form are their own event observer only if no event observer is 
  defined at form instanciation.
* BUG: The default tray icon is the same as gb.qt now.

[GB.QT]
* BUG: TrayIcon objects are correctly destroyed at program exit.
* BUG: Form are their own event observer only if no event observer is 
  defined at form instanciation.
* BUG: TrayIcon Width, Height, ScreenX and ScreenY properties do not crash
  anymore when the tray icon is hidden. They return zero instead.
  

git-svn-id: svn://localhost/gambas/trunk@1187 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2008-03-17 14:54:17 +00:00

821 lines
13 KiB
C
Raw Blame History

/***************************************************************************
trans_subr.c
Subroutine synonymous compiler
(c) 2000-2007 Benoit Minisini <gambas@users.sourceforge.net>
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
the Free Software Foundation; either version 1, or (at your option)
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 _TRANS_SUBR_C
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "gb_common.h"
#include "gb_error.h"
#include "gbc_compile.h"
#include "gbc_trans.h"
#include "gb_code.h"
#include "gb_limit.h"
/*#define DEBUG*/
typedef
struct {
char *name;
SUBR_INFO *info;
}
TRANS_SUBR_INFO;
static void trans_subr(int subr, int nparam)
{
static TRANS_SUBR_INFO subr_info[] =
{
{ ".Print" }, { ".Input" }, { ".Write" }, { ".Read" }, { ".Open" },
{ ".Close" }, { "Seek" }, { ".LineInput" }, { ".Flush" }, { ".Exec" },
{ ".Shell" }, { ".Wait" }, { ".Kill" }, { ".Move" }, { ".Mkdir" },
{ ".Rmdir" }, { ".Array" }, { ".Copy" }, { ".Link" }, { ".Error" },
{ ".Lock" }, { ".Unlock" }, { ".InputFrom" }, { ".OutputTo" }, { ".Debug" },
{ ".Sleep" }, { ".Randomize" }, { ".ErrorTo" },
{ "Left" }, { "Mid" }
};
TRANS_SUBR_INFO *tsi = &subr_info[subr];
if (tsi->info == NULL)
{
tsi->info = SUBR_get(tsi->name);
if (!tsi->info)
ERROR_panic("Unknown intern subroutine: %s", tsi->name);
}
CODE_subr(tsi->info->opcode, nparam, tsi->info->optype, FALSE, tsi->info->min_param == tsi->info->max_param);
}
static bool trans_stream(int default_stream)
{
if (TRANS_is(RS_SHARP))
{
TRANS_expression(FALSE);
if (PATTERN_is(*JOB->current, RS_COMMA))
{
JOB->current++;
if (PATTERN_is_newline(*JOB->current))
THROW(E_SYNTAX);
}
return FALSE;
}
else
{
if (default_stream == TS_NONE)
THROW("Syntax error. '#' expected");
CODE_push_number(default_stream);
return TRUE;
}
}
static void trans_print_debug(void)
{
int nparam = 1;
boolean semicolon = FALSE;
for(;;)
{
if (PATTERN_is_newline(*JOB->current))
break;
TRANS_expression(FALSE);
nparam++;
semicolon = FALSE;
if (PATTERN_is_newline(*JOB->current))
break;
if (TRANS_is(RS_SCOLON))
{
if (TRANS_is(RS_SCOLON))
{
CODE_push_char(' ');
nparam++;
}
semicolon = TRUE;
}
else if (TRANS_is(RS_COMMA))
{
CODE_push_char('\t');
nparam++;
semicolon = FALSE;
}
else
THROW(E_SYNTAX);
}
if (!semicolon)
{
CODE_push_char('\n');
nparam++;
}
trans_subr(TS_SUBR_PRINT, nparam);
CODE_drop();
}
void TRANS_print(void)
{
trans_stream(TS_STDOUT);
trans_print_debug();
}
void TRANS_debug(void)
{
if (!JOB->debug)
{
while (!PATTERN_is_newline(*JOB->current))
JOB->current++;
return;
}
trans_subr(TS_SUBR_DEBUG, 0);
CODE_drop();
CODE_push_number(2); // stderr
trans_print_debug();
}
void TRANS_error(void)
{
if (TRANS_is(RS_TO))
{
if (TRANS_is(RS_DEFAULT))
CODE_push_null();
else
trans_stream(TS_NONE);
trans_subr(TS_SUBR_ERROR_TO, 1);
if (TRANS_in_affectation == 0)
CODE_drop();
}
else
{
CODE_push_number(2); // stderr
trans_print_debug();
}
}
void TRANS_write(void)
{
int nparam = 1;
trans_stream(TS_STDOUT);
TRANS_expression(FALSE);
nparam++;
if (TRANS_is(RS_COMMA))
{
TRANS_expression(FALSE);
nparam++;
}
trans_subr(TS_SUBR_WRITE, nparam);
CODE_drop();
}
void TRANS_output_to()
{
TRANS_want(RS_TO, NULL);
if (TRANS_is(RS_DEFAULT))
CODE_push_null();
else
trans_stream(TS_NONE);
trans_subr(TS_SUBR_OUTPUT_TO, 1);
if (TRANS_in_affectation == 0)
CODE_drop();
}
void TRANS_input_from()
{
if (TRANS_is(RS_DEFAULT))
CODE_push_null();
else
trans_stream(TS_NONE);
trans_subr(TS_SUBR_INPUT_FROM, 1);
if (TRANS_in_affectation == 0)
CODE_drop();
}
void TRANS_input(void)
{
boolean stream = TRUE;
if (TRANS_is(RS_FROM))
{
TRANS_input_from();
return;
}
trans_stream(TS_STDIN);
for(;;)
{
trans_subr(TS_SUBR_INPUT, (stream ? 1 : 0));
stream = FALSE;
TRANS_reference();
if (PATTERN_is_newline(*JOB->current))
break;
if (!PATTERN_is(*JOB->current, RS_COMMA)
&& !PATTERN_is(*JOB->current, RS_SCOLON))
THROW(E_SYNTAX);
JOB->current++;
}
}
void TRANS_read(void)
{
int nparam = 2;
PATTERN *save_return;
PATTERN *save_current;
trans_stream(TS_STDIN);
save_return = JOB->current;
TRANS_expression(FALSE);
/*trans_calc_type();*/
if (TRANS_is(RS_COMMA))
{
TRANS_expression(FALSE);
nparam++;
}
trans_subr(TS_SUBR_READ, nparam);
save_current = JOB->current;
JOB->current = save_return;
TRANS_reference();
JOB->current = save_current;
}
void TRANS_open(void)
{
int mode = TS_MODE_READ;
/* Nom du fichier */
TRANS_expression(FALSE);
/* mode d'ouverture */
if (TRANS_is(RS_FOR))
{
if (TRANS_is(RS_READ))
mode |= TS_MODE_READ | TS_MODE_DIRECT;
else if (TRANS_is(RS_INPUT))
mode |= TS_MODE_READ;
if (TRANS_is(RS_WRITE))
mode |= TS_MODE_WRITE | TS_MODE_DIRECT;
else if (TRANS_is(RS_OUTPUT))
mode |= TS_MODE_WRITE;
if (TRANS_is(RS_CREATE))
mode |= TS_MODE_CREATE;
else if (TRANS_is(RS_APPEND))
mode |= TS_MODE_APPEND;
//if (TRANS_is(RS_DIRECT))
// mode |= TS_MODE_DIRECT;
if (TRANS_is(RS_WATCH))
mode |= TS_MODE_WATCH;
/*if (TRANS_is(RS_BIG))
mode |= TS_MODE_BIG;
else if (TRANS_is(RS_LITTLE))
mode |= TS_MODE_LITTLE;*/
/*JOB->current--;
if (PATTERN_is(*JOB->current, RS_FOR))
THROW("Syntax error in file open mode");
JOB->current++;*/
}
CODE_push_number(mode);
trans_subr(TS_SUBR_OPEN, 2);
if (TRANS_in_affectation == 0)
{
//CODE_drop();
/* handle du fichier */
TRANS_want(RS_AS, NULL);
TRANS_ignore(RS_SHARP);
TRANS_reference();
}
}
void TRANS_pipe(void)
{
int mode = TS_MODE_READ;
/* Nom du fichier */
TRANS_expression(FALSE);
/* mode d'ouverture */
if (TRANS_is(RS_FOR))
{
if (TRANS_is(RS_READ))
mode |= TS_MODE_READ | TS_MODE_DIRECT;
else if (TRANS_is(RS_INPUT))
mode |= TS_MODE_READ;
if (TRANS_is(RS_WRITE))
mode |= TS_MODE_WRITE | TS_MODE_DIRECT;
else if (TRANS_is(RS_OUTPUT))
mode |= TS_MODE_WRITE;
/*if (TRANS_is(RS_CREATE))
mode |= TS_MODE_CREATE;
else if (TRANS_is(RS_APPEND))
mode |= TS_MODE_APPEND;*/
//if (TRANS_is(RS_DIRECT))
// mode |= TS_MODE_DIRECT;
if (TRANS_is(RS_WATCH))
mode |= TS_MODE_WATCH;
/*if (TRANS_is(RS_BIG))
mode |= TS_MODE_BIG;
else if (TRANS_is(RS_LITTLE))
mode |= TS_MODE_LITTLE;*/
/*JOB->current--;
if (PATTERN_is(*JOB->current, RS_FOR))
THROW("Syntax error in file open mode");
JOB->current++;*/
}
CODE_push_number(mode | TS_MODE_PIPE);
trans_subr(TS_SUBR_OPEN, 2);
if (TRANS_in_affectation == 0)
{
//CODE_drop();
/* handle du fichier */
TRANS_want(RS_AS, NULL);
TRANS_ignore(RS_SHARP);
TRANS_reference();
}
}
void TRANS_close(void)
{
if (PATTERN_is_newline(*JOB->current))
THROW(E_SYNTAX);
TRANS_ignore(RS_SHARP);
TRANS_expression(FALSE);
trans_subr(TS_SUBR_CLOSE, 1);
CODE_drop();
}
void TRANS_lock(void)
{
if (PATTERN_is_newline(*JOB->current))
THROW(E_SYNTAX);
if (!TRANS_in_affectation)
THROW("Useless LOCK");
TRANS_expression(FALSE);
trans_subr(TS_SUBR_LOCK, 1);
}
void TRANS_unlock(void)
{
if (PATTERN_is_newline(*JOB->current))
THROW(E_SYNTAX);
TRANS_ignore(RS_SHARP);
TRANS_expression(FALSE);
trans_subr(TS_SUBR_UNLOCK, 1);
CODE_drop();
}
void TRANS_seek(void)
{
int nparam;
trans_stream(TS_NONE);
TRANS_expression(FALSE);
nparam = 2;
/*
if (TRANS_is(RS_COMMA))
{
TRANS_expression(FALSE);
nparam++;
}
*/
trans_subr(TS_SUBR_SEEK, nparam);
CODE_drop();
}
void TRANS_line_input(void)
{
if (TRANS_is(RS_INPUT))
{
trans_stream(TS_STDIN);
trans_subr(TS_SUBR_LINE_INPUT, 1);
TRANS_reference();
}
else
THROW(E_SYNTAX);
}
void TRANS_flush(void)
{
trans_stream(TS_STDOUT);
trans_subr(TS_SUBR_FLUSH, 1);
CODE_drop();
}
void TRANS_stop(void)
{
if (TRANS_is(RS_EVENT))
CODE_stop_event();
else
CODE_stop();
}
void TRANS_quit(void)
{
CODE_quit();
}
void TRANS_randomize(void)
{
if (PATTERN_is_newline(*JOB->current))
{
trans_subr(TS_SUBR_RANDOMIZE, 0);
}
else
{
TRANS_expression(FALSE);
trans_subr(TS_SUBR_RANDOMIZE, 1);
}
CODE_drop();
}
static void trans_exec_shell(bool shell)
{
int mode = TS_EXEC_NONE;
bool wait;
bool as = FALSE;
/* programme <20>ex<65>uter */
TRANS_expression(FALSE);
wait = TRANS_is(RS_WAIT);
if (TRANS_is(RS_FOR))
{
if (TRANS_is(RS_READ))
mode |= TS_EXEC_READ;
if (TRANS_is(RS_WRITE))
mode |= TS_EXEC_WRITE;
if (mode == 0)
{
mode |= TS_EXEC_TERM;
if (TRANS_is(RS_INPUT))
mode |= TS_EXEC_READ;
if (TRANS_is(RS_OUTPUT))
mode |= TS_EXEC_WRITE;
}
as = TRUE;
}
else if (TRANS_is(RS_TO))
{
if (TRANS_in_affectation)
THROW("Syntax error. Cannot use this syntax in affectation.");
mode = TS_EXEC_STRING;
wait = TRUE;
}
CODE_push_boolean(wait);
CODE_push_number(mode);
if (as && TRANS_is(RS_AS))
TRANS_expression(FALSE);
else
CODE_push_null();
trans_subr(shell ? TS_SUBR_SHELL : TS_SUBR_EXEC, 4);
if (mode == TS_EXEC_STRING)
TRANS_reference();
else if (TRANS_in_affectation == 0)
CODE_drop();
}
void TRANS_exec(void)
{
trans_exec_shell(FALSE);
}
void TRANS_shell(void)
{
trans_exec_shell(TRUE);
}
void TRANS_wait(void)
{
int nparam = 0;
if (!PATTERN_is_newline(*JOB->current))
{
TRANS_expression(FALSE);
nparam = 1;
}
trans_subr(TS_SUBR_WAIT, nparam);
CODE_drop();
}
void TRANS_sleep(void)
{
TRANS_expression(FALSE);
trans_subr(TS_SUBR_SLEEP, 1);
CODE_drop();
}
void TRANS_kill(void)
{
TRANS_expression(FALSE);
trans_subr(TS_SUBR_KILL, 1);
CODE_drop();
}
void TRANS_move(void)
{
TRANS_expression(FALSE);
TRANS_want(RS_TO, NULL);
TRANS_expression(FALSE);
trans_subr(TS_SUBR_MOVE, 2);
CODE_drop();
}
void TRANS_copy(void)
{
TRANS_expression(FALSE);
TRANS_want(RS_TO, NULL);
TRANS_expression(FALSE);
trans_subr(TS_SUBR_COPY, 2);
CODE_drop();
}
void TRANS_link(void)
{
TRANS_expression(FALSE);
TRANS_want(RS_TO, NULL);
TRANS_expression(FALSE);
trans_subr(TS_SUBR_LINK, 2);
CODE_drop();
}
void TRANS_inc(void)
{
PATTERN *save = JOB->current;
TRANS_expression(FALSE);
CODE_push_number(1);
CODE_op(C_ADD, 2, TRUE);
JOB->current = save;
TRANS_reference();
}
void TRANS_dec(void)
{
PATTERN *save = JOB->current;
TRANS_expression(FALSE);
CODE_push_number(1);
CODE_op(C_SUB, 2, TRUE);
JOB->current = save;
TRANS_reference();
}
void TRANS_swap(void)
{
PATTERN *sa;
PATTERN *sb;
PATTERN *current;
sa = JOB->current;
TRANS_expression(FALSE);
TRANS_want(RS_COMMA, "Comma");
sb = JOB->current;
TRANS_expression(FALSE);
current = JOB->current;
JOB->current = sa;
TRANS_reference();
JOB->current = sb;
TRANS_reference();
JOB->current = current;
}
void TRANS_mkdir(void)
{
TRANS_expression(FALSE);
trans_subr(TS_SUBR_MKDIR, 1);
CODE_drop();
}
void TRANS_rmdir(void)
{
TRANS_expression(FALSE);
trans_subr(TS_SUBR_RMDIR, 1);
CODE_drop();
}
void TRANS_mid()
{
PATTERN *str;
PATTERN *pos;
PATTERN *len;
PATTERN *save;
TRANS_want(RS_LBRA, "Left brace");
str = JOB->current;
TRANS_expression(FALSE);
TRANS_want(RS_COMMA, "Comma");
pos = JOB->current;
TRANS_expression(FALSE);
CODE_push_number(1);
CODE_op(C_SUB, 2, TRUE);
TRANS_subr(TS_SUBR_LEFT, 2);
if (TRANS_is(RS_COMMA))
{
len = JOB->current;
TRANS_ignore_expression();
}
else
{
len = NULL;
}
TRANS_want(RS_RBRA, "Right brace");
TRANS_want(RS_EQUAL, "Equal");
TRANS_expression(FALSE);
save = JOB->current;
if (len)
{
JOB->current = str;
TRANS_expression(FALSE);
JOB->current = pos;
TRANS_expression(FALSE);
JOB->current = len;
TRANS_expression(FALSE);
CODE_op(C_ADD, 2, TRUE);
TRANS_subr(TS_SUBR_MID, 2);
}
CODE_op(C_CAT, len ? 3 : 2, FALSE);
JOB->current = str;
TRANS_reference();
JOB->current = save;
}
#if 0
void TRANS_scan(void)
{
PATTERN *save;
int noutput = 0;
TRANS_expression(FALSE);
TRANS_want(RS_WITH, NULL);
TRANS_expression(FALSE);
TRANS_want(RS_TO, NULL);
save = JOB->current;
for(;;)
{
TRANS_expression(FALSE);
noutput++;
if (!TRANS_is(RS_COMMA))
break;
}
JOB->current = save;
trans_subr_output(TSO_SUBR_SCAN, 2 + noutput, noutput);
for(;;)
{
TRANS_reference();
if (!TRANS_is(RS_COMMA))
break;
}
}
#endif
void TRANS_subr(int subr, int nparam)
{
trans_subr(subr, nparam);
}