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

📄 gbc_header.c

📁 Gambas is a graphical development environment based on a Basic interpreter, like Visual Basic. It us
💻 C
字号:
/***************************************************************************  header.c  Analyzing class description  (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_HEADER_C#include <stdlib.h>#include <string.h>#include <stdio.h>#include "gb_common.h"#include "gb_error.h"#include "gb_str.h"#include "gb_file.h"#include "gb_table.h"#include "gbc_compile.h"#include "gbc_trans.h"#include "gbc_header.h"/*#define DEBUG*/PRIVATE char *get_num_desc(int num){  static char *num_desc[3] = { "first", "second", "third" };  static char desc[6];  if (num < 1)    return NULL;  if (num < 4)    return num_desc[num - 1];  sprintf(desc, "%dth", num);  return desc;}PRIVATE void analyze_function_desc(TRANS_FUNC *func, int flag){  PATTERN *look = JOB->current;  TRANS_PARAM *param;  bool is_output;  bool is_optional = FALSE;  TRANS_DECL ttyp;  if (!PATTERN_is_identifier(*look))    THROW("Syntax error. Invalid identifier in function name");  func->index = PATTERN_index(*look);  look++;  if (flag & HF_EVENT)    TABLE_copy_symbol_with_prefix(JOB->class->table, func->index, ':', NULL, &func->index);  if (!PATTERN_is(*look, RS_LBRA))    THROW("Syntax error. Missing '('");  look++;  func->nparam = 0;  for(;;)  {    param = &func->param[func->nparam];    if (PATTERN_is(*look, RS_RBRA))    {      look++;      break;    }    if (func->nparam > 0)    {      if (!PATTERN_is(*look, RS_COMMA))        THROW("Syntax error. Missing ','");      look++;    }    if (PATTERN_is(*look, RS_3PTS))    {      param->type = TYPE_make(T_NULL, 0, 0);      look++;      if (!PATTERN_is(*look, RS_RBRA))        THROW("Syntax error. '...' must be the last parameter", get_num_desc(func->nparam + 1));      look++;      break;    }    is_output = FALSE;    /* Pas de param鑤re en sortie pour l'instant !    if (PATTERN_is(*look, RS_AT))    {      is_output = TRUE;      look++;    }    */    if (!(flag & HF_NO_OPT))    {      if (PATTERN_is(*look, RS_OPTIONAL))      {        look++;        is_optional = TRUE;      }    }    if (!PATTERN_is_identifier(*look))      THROW("Syntax error. The &1 parameter is not a valid identifier", get_num_desc(func->nparam + 1));    param->index = PATTERN_index(*look);    look++;    JOB->current = look;    if (!TRANS_type(TT_NOTHING, &ttyp))      THROW("Syntax error. Invalid type description of &1 parameter", get_num_desc(func->nparam + 1));    param->type = ttyp.type;    /*    if (is_output)      TYPE_set_flag(&param->type, TF_OUTPUT);    */    look = JOB->current;    if (is_optional)    {      param->optional = look;      for(;;)      {        if (PATTERN_is(*look, RS_COMMA) || PATTERN_is(*look, RS_RBRA) || PATTERN_is_newline(*look))          break;        look++;      }      JOB->current = look;    }    func->nparam++;  }  JOB->current = look;}PRIVATE void header_module_type(void){  const char *ext;  /*JOB->class->name = STR_copy(FILE_get_name(JOB->name));*/  ext = FILE_get_ext(JOB->name);  if (strcasecmp(ext, "module") == 0)  {    JOB->is_module = TRUE;    JOB->is_form = FALSE;  }  else if (strcasecmp(ext, "class") == 0)  {    JOB->is_module = FALSE;    JOB->is_form = FALSE;  }  else if (strcasecmp(ext, "form") == 0)  {    JOB->is_module = FALSE;    JOB->is_form = TRUE;  }  else    THROW("Unknown file extension");  JOB->declared = TRUE;}PRIVATE bool header_event(TRANS_EVENT *event){  PATTERN *look = JOB->current;  TRANS_DECL ttyp;  if (!PATTERN_is(*look, RS_EVENT))    return FALSE;  CLEAR(event);  if (JOB->is_module)    THROW("A module cannot raise events");  JOB->current++;  analyze_function_desc((TRANS_FUNC *)event, HF_NORMAL);  if (PATTERN_is(*JOB->current, RS_AS))  {    if (!TRANS_type(TT_CAN_SQUARE, &ttyp))      THROW("Syntax error in return type");    event->type = ttyp.type;  }  TYPE_set_kind(&event->type, TK_EVENT);  TYPE_set_flag(&event->type, TF_PUBLIC);  return TRUE;}PRIVATE bool header_property(TRANS_PROPERTY *prop){  TRANS_DECL ptype;  PATTERN *look = JOB->current;  bool is_static = FALSE;  bool is_public = TRUE;  CLEAR(prop);  /* static */  if (JOB->is_module)  {    is_static = TRUE;  }  else if (PATTERN_is(*look, RS_STATIC))  {    is_static = TRUE;    look++;  }  /* public */  if (PATTERN_is(*look, RS_PUBLIC) || PATTERN_is(*look, RS_PRIVATE))  {    is_public = PATTERN_is(*look, RS_PUBLIC);    look++;  }  if (!PATTERN_is(*look, RS_PROPERTY))    return FALSE;  look++;  JOB->current = look;  if (!is_public)    THROW("A property must be public");  /* read-only property */  if (PATTERN_is(*JOB->current, RS_READ))  {    prop->read = TRUE;    JOB->current++;  }  else    prop->read = FALSE;  /* property name */  if (!PATTERN_is_identifier(*JOB->current))    THROW("Syntax error. Invalid identifier in property name");  prop->index = PATTERN_index(*JOB->current);  JOB->current++;  if (!TRANS_type(TT_CAN_SQUARE, &ptype))    THROW("Syntax error. Bad property type");  prop->type = ptype.type;  prop->line = JOB->line;  TYPE_set_kind(&prop->type, TK_PROPERTY);  if (is_static)    TYPE_set_flag(&prop->type, TF_STATIC);  TYPE_set_flag(&prop->type, TF_PUBLIC);  return TRUE;}PRIVATE bool header_extern(TRANS_EXTERN *trans){  PATTERN *look = JOB->current;  TRANS_DECL ttyp;  CLEAR(trans);  if (!PATTERN_is(*look, RS_EXTERN))    return FALSE;  JOB->current++;  analyze_function_desc((TRANS_FUNC *)trans, HF_NO_3PTS);  if (PATTERN_is(*JOB->current, RS_AS))  {    if (!TRANS_type(TT_CAN_SQUARE, &ttyp))      THROW("Syntax error in return type");    trans->type = ttyp.type;  }  if (!PATTERN_is(*JOB->current, RS_IN))    THROW("IN missing");  JOB->current++;  if (!PATTERN_is_string(*JOB->current))    THROW("Syntax error in library name");  trans->library = PATTERN_index(*JOB->current);  JOB->current++;  TYPE_set_kind(&trans->type, TK_EXTERN);  return TRUE;}PRIVATE bool header_class(TRANS_DECL *decl){  if (!PATTERN_is(*JOB->current, RS_CLASS))    return FALSE;  JOB->current++;  if (!PATTERN_is_identifier(*JOB->current))    THROW("Syntax error. CLASS needs an identifier");  decl->index = PATTERN_index(*JOB->current);  JOB->current++;  return TRUE;}PRIVATE bool header_declaration(TRANS_DECL *decl){  PATTERN *look = JOB->current;  bool is_static = FALSE;  bool is_public = FALSE;  bool is_const = FALSE;  /*bool other = FALSE;*/  CLEAR(decl);  /* static ! */  if (JOB->is_module)  {    is_static = TRUE;  }  else if (PATTERN_is(*look, RS_STATIC))  {    is_static = TRUE;    look++;  }  /* public ou private ? */  is_public = JOB->is_module;  if (PATTERN_is(*look, RS_PUBLIC))  {    is_public = TRUE;    look++;  }  else if (PATTERN_is(*look, RS_PRIVATE))  {    is_public = FALSE;    look++;  }  /* const ? */  is_const = FALSE;  if (PATTERN_is(*look, RS_CONST))  {    /* static const <=> const */    /*    if (is_static)      return FALSE;    */    is_const = TRUE;    look++;  }  if (!PATTERN_is_identifier(*look))    return FALSE;  decl->index = PATTERN_index(*look);  look++;  JOB->current = look;  if (!TRANS_type(((!is_const && !is_public) ? (TT_CAN_SQUARE  | TT_CAN_ARRAY) : 0) | TT_CAN_NEW, decl))    return FALSE;  if (is_static) TYPE_set_flag(&decl->type, TF_STATIC);  if (is_public) TYPE_set_flag(&decl->type, TF_PUBLIC);  if (is_const)    TYPE_set_kind(&decl->type, TK_CONST);  else    TYPE_set_kind(&decl->type, TK_VARIABLE);  look = JOB->current;  if (is_const)  {    if (!PATTERN_is(*look, RS_EQUAL))      THROW("Syntax error. Missing '='");    look++;    /*    if ((!PATTERN_IS_STRING(*look)) && (!PATTERN_IS_NUMBER(*look)))      THROW("Syntax error in constant declaration");    */    TRANS_get_constant_value(decl, *look);    look++;  }  JOB->current = look;  return TRUE;}PRIVATE bool header_function(TRANS_FUNC *func){  static HEADER_SPECIAL spec[] =  {    { "_init",      HS_PUBLIC + HS_STATIC + HS_PROCEDURE },    { "_exit",      HS_PUBLIC + HS_STATIC + HS_PROCEDURE },    { "_new",       HS_PUBLIC + HS_DYNAMIC + HS_PROCEDURE },    { "_free",      HS_PUBLIC + HS_DYNAMIC + HS_PROCEDURE },    { "_call",      HS_PUBLIC },    { "_get",       HS_ERROR },    { "_put",       HS_ERROR },    { "_first",     HS_ERROR },    { "_next",      HS_ERROR },    { "_unknown",   HS_ERROR },    { NULL, 0 }  };  PATTERN *look = JOB->current;  PATTERN pat;  TRANS_DECL ttyp;  SYMBOL *sym;  HEADER_SPECIAL *hsp;  bool is_proc = FALSE;  bool is_static = FALSE;  bool is_public = FALSE;  CLEAR(func);  /* static ? */  if (JOB->is_module)  {    is_static = TRUE;  }  else if (PATTERN_is(*look, RS_STATIC))  {    is_static = TRUE;    look++;  }  /* public ou private ? */  is_public = JOB->is_module;  if (PATTERN_is(*look, RS_PUBLIC))  {    is_public = TRUE;    look++;  }  else if (PATTERN_is(*look, RS_PRIVATE))  {    is_public = FALSE;    look++;  }  if (PATTERN_is(*look, RS_PROCEDURE) || PATTERN_is(*look, RS_SUB))    is_proc = TRUE;  else if (!PATTERN_is(*look, RS_FUNCTION))    return FALSE;  look++;  JOB->current = look;  analyze_function_desc(func, HF_NORMAL);  if (!is_proc)  {    if (!TRANS_type(TT_CAN_SQUARE, &ttyp))      THROW("Syntax error. Invalid return type");    func->type = ttyp.type;  }  TYPE_set_kind(&func->type, TK_FUNCTION);  if (is_static) TYPE_set_flag(&func->type, TF_STATIC);  if (is_public) TYPE_set_flag(&func->type, TF_PUBLIC);  /* On v閞ifie les m閠hodes sp閏iales */  sym = TABLE_get_symbol(JOB->class->table, func->index);  if (*sym->name == '_')  {    for (hsp = spec; hsp->name; hsp++)    {      if (sym->len != strlen(hsp->name))        continue;      if (strncmp(sym->name, hsp->name, sym->len))        continue;      if (hsp->flag == HS_ERROR)        THROW("The special method &1 cannot be implemented", hsp->name);      if ((hsp->flag & HS_PUBLIC) && !is_public)        THROW("The special method &1 must be public", hsp->name);      if ((hsp->flag & HS_STATIC) && !is_static)        THROW("The special method &1 must be static", hsp->name);      if ((hsp->flag & HS_DYNAMIC) && is_static)        THROW("The special method &1 cannot be static", hsp->name);      if ((hsp->flag & HS_PROCEDURE) && !is_proc)        THROW("The special method &1 cannot be a function", hsp->name);      break;    }  }  /* on saute le corps de la fonction */  if (!PATTERN_is_newline(*(JOB->current)))    THROW("Syntax error after function declaration");  func->line = PATTERN_index(*(JOB->current)) + 1; /* 鏰 commence 

⌨️ 快捷键说明

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