⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gbc_trans_ctrl.c

📁 Gambas is a graphical development environment based on a Basic interpreter, like Visual Basic. It us
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************  trans_ctrl.c  Control structures compiler  (c) 2000-2004 Beno� 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_CTRL_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*//*#define DEBUG_GOTO*/PRIVATE int ctrl_level;PRIVATE int ctrl_id;PRIVATE int ctrl_local;PRIVATE TRANS_CTRL ctrl_data[MAX_CTRL_LEVEL];PRIVATE TRANS_CTRL *current_ctrl;PRIVATE TRANS_GOTO *goto_info;PRIVATE TRANS_LABEL *label_info;PRIVATE short *ctrl_parent;PRIVATE void control_set_value(long value){  if (ctrl_level <= 0)    return;  current_ctrl->value = value;}PRIVATE long control_get_value(){  if (ctrl_level <= 0)    return 0;  return current_ctrl->value;}PRIVATE void control_add_pos(short **tab_pos, short pos){  if (!(*tab_pos))    ARRAY_create(tab_pos);  *((short *)ARRAY_add(tab_pos)) = pos;}PRIVATE void control_add_current_pos(){  control_add_pos(&current_ctrl->pos, CODE_get_current_pos());}PRIVATE void control_jump_each_pos_with(short *tab_pos){  int i;  if (!tab_pos)    return;  for (i = 0; i < ARRAY_count(tab_pos); i++)    CODE_jump_length(tab_pos[i], CODE_get_current_pos());}PRIVATE void control_jump_each_pos(){  control_jump_each_pos_with(current_ctrl->pos);}PRIVATE TRANS_CTRL *control_get_inner(void){  int level = ctrl_level;  TRANS_CTRL *ctrl_look;  for(;;)  {    if (!level)      return NULL;    level--;    ctrl_look = &ctrl_data[level];    if ((ctrl_look->type == RS_DO)        || (ctrl_look->type == RS_WHILE)        || (ctrl_look->type == RS_REPEAT)        || (ctrl_look->type == RS_FOR)        || (ctrl_look->type == RS_EACH))      return ctrl_look;  }}PRIVATE TRANS_CTRL *control_get_inner_with(void){  int level = ctrl_level;  TRANS_CTRL *ctrl_look;  for(;;)  {    if (!level)      return NULL;    level--;    ctrl_look = &ctrl_data[level];    if (ctrl_look->type == RS_WITH)      return ctrl_look;  }}PRIVATE void add_goto(long index){  TRANS_GOTO *info;  if (goto_info == NULL)    ARRAY_create(&goto_info);  info = ARRAY_add(&goto_info);  info->index = index;  info->pos = CODE_get_current_pos();  info->ctrl_id = (ctrl_level == 0) ? 0 : current_ctrl->id;  info->line = JOB->line;  #ifdef DEBUG_GOTO    printf("add_goto: ctrl_id = %d (%ld)\n", info->ctrl_id, ARRAY_count(goto_info));  #endif  CODE_jump();}PRIVATE void control_enter(long type){  short *parent;  if (ctrl_level >= MAX_CTRL_LEVEL)    THROW("Too many nested control structures.");  ctrl_id++;  current_ctrl = &ctrl_data[ctrl_level];  current_ctrl->type = type;  current_ctrl->value = 0;  current_ctrl->pos = NULL;  current_ctrl->state = 0;  current_ctrl->local = ctrl_local;  current_ctrl->id = ctrl_id;  current_ctrl->loop_var = -1;  parent = ARRAY_add(&ctrl_parent);  if (ctrl_level == 0)    *parent = 0;  else    *parent = ctrl_data[ctrl_level - 1].id;  switch (type)  {    case RS_FOR:    case RS_EACH:      ctrl_local += 2;      break;    case RS_SELECT:    case RS_WITH:      ctrl_local += 1;      break;  }  JOB->func->nctrl = Max(JOB->func->nctrl, ctrl_local - JOB->func->nlocal);  ctrl_level++;}PRIVATE void control_leave(){  control_jump_each_pos_with(current_ctrl->pos_break);  ARRAY_delete(&current_ctrl->pos);  ARRAY_delete(&current_ctrl->pos_break);  ARRAY_delete(&current_ctrl->pos_continue);  ctrl_local = current_ctrl->local;  ctrl_level--;  if (ctrl_level > 0)    current_ctrl = &ctrl_data[ctrl_level - 1];  else    current_ctrl = NULL;}PRIVATE void control_check(long type, const char *msg1, const char *msg2){  if (ctrl_level <= 0)    THROW(msg1);  if (current_ctrl->type != type)    THROW(msg2);}PRIVATE void control_check_two(long type1, long type2, const char *msg1, const char *msg2){  if (ctrl_level <= 0)    THROW(msg1);  if (current_ctrl->type != type1 && current_ctrl->type != type2)    THROW(msg2);}static void control_check_loop_var(short var){	int i;	for (i = 0; i < (ctrl_level - 1); i++)	{		if (ctrl_data[i].loop_var == var)			THROW("Loop variable already in use");	}	current_ctrl->loop_var = var;}PUBLIC void TRANS_control_init(){  ctrl_level = 0;  ctrl_id = 0;  current_ctrl = NULL;  goto_info = NULL;  label_info = NULL;  ctrl_local = JOB->func->nlocal;  JOB->func->nctrl = 0;  ARRAY_create(&ctrl_parent);}PUBLIC void TRANS_control_exit(){  int i;  CLASS_SYMBOL *sym;  long line;  TRANS_LABEL *label;  short id;  /* R�olution des GOTO */  if (goto_info)  {    line = JOB->line;    for (i = 0; i < ARRAY_count(goto_info); i++)    {      JOB->line = goto_info[i].line;      /*printf("%d\n", JOB->line);*/      sym = CLASS_get_symbol(JOB->class, goto_info[i].index);      if (TYPE_get_kind(sym->local.type) != TK_LABEL)        THROW("Label '&1' not declared", TABLE_get_symbol_name(JOB->class->table, goto_info[i].index));      label = &label_info[sym->local.value];      id = goto_info[i].ctrl_id;      for(;;)      {        if (label->ctrl_id == id)          break;        if (id == 0)          THROW("Forbidden GOTO");        #ifdef DEBUG_GOTO          printf("id = %d ctrl_parent[id - 1] = %d (%ld)\n", id, ctrl_parent[id - 1], ARRAY_count(ctrl_parent));        #endif        id = ctrl_parent[id - 1];      }      CODE_jump_length(goto_info[i].pos, label->pos);    }    JOB->line = line;  }  /* Remove previously declared labels */  if (label_info)  {    for (i = 0; i < ARRAY_count(label_info); i++)    {      sym = CLASS_get_symbol(JOB->class, label_info[i].index);      TYPE_clear(&sym->local.type);    }  }  ARRAY_delete(&goto_info);  ARRAY_delete(&ctrl_parent);  ARRAY_delete(&label_info);  /* On ne doit pas laisser une structure de controle ouverte */  if (ctrl_level == 0) return;  switch (ctrl_data[ctrl_level - 1].type)  {    case RS_IF:      THROW("ENDIF missing");    case RS_FOR:    case RS_EACH:      THROW("NEXT missing");    case RS_DO:      THROW("LOOP missing");    case RS_REPEAT:      THROW("UNTIL missing");    case RS_WHILE:      THROW("WEND missing");    case RS_SELECT:      THROW("END SELECT missing");    case RS_WITH:      THROW("END WITH missing");  }}PUBLIC void TRANS_if(){  control_enter(RS_IF);  TRANS_expression(FALSE);  if (!PATTERN_is(*JOB->current, RS_THEN))    THROW("Syntax error. THEN expected");  JOB->current++;  control_set_value(CODE_get_current_pos());  CODE_jump_if_false();  if (PATTERN_is_newline(*JOB->current))    return;  TRANS_statement();  TRANS_endif();}PUBLIC void TRANS_else(){  control_check(RS_IF, "ELSE without IF", "Unexpected ELSE");  if (current_ctrl->state)    THROW("Unexpected ELSE");  control_add_current_pos();  CODE_jump();  CODE_jump_length(control_get_value(), CODE_get_current_pos());  if (PATTERN_is(*JOB->current, RS_IF))  {    JOB->current++;    TRANS_expression(FALSE);    if (!PATTERN_is(*JOB->current, RS_THEN))      THROW("Syntax error. THEN expected");    JOB->current++;    control_set_value(CODE_get_current_pos());    CODE_jump_if_false();  }  else    current_ctrl->state = 1;}PUBLIC void TRANS_endif(){  control_check(RS_IF, "ENDIF without IF", "Unexpected ENDIF");  if (current_ctrl->state == 0)    CODE_jump_length(control_get_value(), CODE_get_current_pos());  control_jump_each_pos();  control_leave();}PUBLIC void TRANS_goto(){  long index;  if (!PATTERN_is_identifier(*JOB->current))    THROW(E_SYNTAX);  index = PATTERN_index(*JOB->current);  JOB->current++;  add_goto(index);}PUBLIC void TRANS_do(PATTERN type){  boolean is_until;  control_enter(type);  control_set_value(CODE_get_current_pos());  if (type == RS_REPEAT)    return;  is_until = PATTERN_is(*JOB->current, RS_UNTIL);  if (PATTERN_is(*JOB->current, RS_WHILE)      || is_until)  {    JOB->current++;    TRANS_expression(FALSE);    control_add_current_pos();    if (is_until)      CODE_jump_if_true();    else      CODE_jump_if_false();  }}PUBLIC void TRANS_loop(PATTERN type){  short pos;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -