LogoSearch packages:      

Sourcecode: gambas version File versions

gbc_trans_subr.c

/***************************************************************************

  trans_subr.c

  Subroutine synonymous compiler

  (c) 2000-2004 Benoît 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;


PRIVATE void trans_subr(int subr, int nparam)
{
  static TRANS_SUBR_INFO subr_info[] =
  {
    { "Print" }, { "Input" }, { "Write" }, { "Read" },  { "Open" },
    { "Close" }, { "Seek" }, { "Type" }, { "LineInput" }, { "Flush" },
    { "Exec" }, { "Shell" }, { "Wait" }, { "Kill" }, { "Rename" },
    { "Mkdir" }, { "Rmdir" }, { "Array" }, { "Use" }, { "Copy" },
    { "Link" }, { "Error" }, { "Lock" }, { "Unlock" }
  };

  TRANS_SUBR_INFO *tsi = &subr_info[subr];

  if (tsi->info == NULL)
    tsi->info = SUBR_get(tsi->name);

  CODE_subr(tsi->info->opcode, nparam, tsi->info->optype, FALSE, tsi->info->min_param == tsi->info->max_param);
}


PRIVATE boolean 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
  {
    CODE_push_number(default_stream);
    return TRUE;
  }
}


PUBLIC void TRANS_print(void)
{
  int nparam = 1;
  boolean semicolon = FALSE;

  trans_stream(TS_STDOUT);

  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();
}


PUBLIC 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();
}


PUBLIC void TRANS_input(void)
{
  boolean stream = TRUE;

  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++;
  }
}


PUBLIC 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;
}


PUBLIC 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;

    if (TRANS_is(RS_WRITE))
      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);

  /* handle du fichier */

  TRANS_want(RS_AS, NULL);
  TRANS_ignore(RS_SHARP);

  TRANS_reference();

}


PUBLIC 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();
}


static void trans_lock_unlock(bool unlock)
{
  if (PATTERN_is_newline(*JOB->current))
    THROW(E_SYNTAX);

  TRANS_ignore(RS_SHARP);
  TRANS_expression(FALSE);

  trans_subr(unlock ? TS_SUBR_UNLOCK : TS_SUBR_LOCK, 1);
  CODE_drop();
}


PUBLIC void TRANS_lock(void)
{
  trans_lock_unlock(FALSE);
}


PUBLIC void TRANS_unlock(void)
{
  trans_lock_unlock(TRUE);
}


PUBLIC void TRANS_seek(void)
{
  int nparam;

  if (trans_stream(TS_STDIN))
    THROW("Syntax error. '#' expected");

  TRANS_expression(FALSE);
  nparam = 2;

  /*
  if (TRANS_is(RS_COMMA))
  {
    TRANS_expression(FALSE);
    nparam++;
  }
  */

  trans_subr(TS_SUBR_SEEK, nparam);
  CODE_drop();
}


PUBLIC void TRANS_line_input(void)
{
  trans_stream(TS_STDIN);
  trans_subr(TS_SUBR_LINE_INPUT, 1);
  TRANS_reference();
}


PUBLIC void TRANS_flush(void)
{
  trans_stream(TS_STDOUT);
  trans_subr(TS_SUBR_FLUSH, 1);
  CODE_drop();
}


PUBLIC void TRANS_stop(void)
{
  if (TRANS_is(RS_EVENT))
    CODE_stop_event();
  else
    CODE_stop();
}


PUBLIC void TRANS_quit(void)
{
      CODE_quit();
}


PRIVATE void trans_exec_shell(bool shell)
{
  int mode = 0;
  bool wait = FALSE;

  /* programme à exécuter */
  TRANS_expression(FALSE);

  wait = TRANS_is(RS_WAIT);
  CODE_push_boolean(wait);

  if (TRANS_is(RS_FOR))
  {
    if (wait)
      THROW("Cannot use WAIT with FOR READ / WRITE");
    if (TRANS_is(RS_READ))
      mode |= TS_EXEC_READ;
    if (TRANS_is(RS_WRITE))
      mode |= TS_EXEC_WRITE;
  }

  CODE_push_number(mode);

  trans_subr(shell ? TS_SUBR_SHELL : TS_SUBR_EXEC, 3);

  if (TRANS_is(RS_AS))
    TRANS_reference();
  else
    CODE_drop();
}


PUBLIC void TRANS_exec(void)
{
  trans_exec_shell(FALSE);
}

PUBLIC void TRANS_shell(void)
{
  trans_exec_shell(TRUE);
}


PUBLIC 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();
}


PUBLIC void TRANS_kill(void)
{
  TRANS_expression(FALSE);
  trans_subr(TS_SUBR_KILL, 1);
  CODE_drop();
}

PUBLIC void TRANS_rename(void)
{
  TRANS_expression(FALSE);
  TRANS_want(RS_AS, NULL);
  TRANS_expression(FALSE);
  trans_subr(TS_SUBR_RENAME, 2);
  CODE_drop();
}

PUBLIC void TRANS_copy(void)
{
  TRANS_expression(FALSE);
  TRANS_want(RS_TO, NULL);
  TRANS_expression(FALSE);
  trans_subr(TS_SUBR_COPY, 2);
  CODE_drop();
}

PUBLIC void TRANS_link(void)
{
  TRANS_expression(FALSE);
  TRANS_want(RS_TO, NULL);
  TRANS_expression(FALSE);
  trans_subr(TS_SUBR_LINK, 2);
  CODE_drop();
}

PUBLIC 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();
}

PUBLIC 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();
}


PUBLIC 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;
}

PUBLIC void TRANS_mkdir(void)
{
  TRANS_expression(FALSE);
  trans_subr(TS_SUBR_MKDIR, 1);
  CODE_drop();
}

PUBLIC void TRANS_rmdir(void)
{
  TRANS_expression(FALSE);
  trans_subr(TS_SUBR_RMDIR, 1);
  CODE_drop();
}


PUBLIC void TRANS_use(void)
{
  TRANS_expression(FALSE);
  trans_subr(TS_SUBR_USE, 1);
  CODE_drop();
}


PUBLIC void TRANS_subr(int subr, int nparam)
{
  trans_subr(subr, nparam);
}



Generated by  Doxygen 1.5.1   Back to index