Esempio n. 1
0
/*-----------------------------------------------------------------------------
*
* ID: c_if 08.02.07 0.0.A.
*
* Summary: The if-elif-else processing
*
-----------------------------------------------------------------------------*/
plexem STDCALL c_if( plexem curlex )
{
   uint       jmpnext;     //Смещение в стэке меток - переход к следующему elif, else
   uint       jmpend;      //Смещение в стэке меток - переход к концу
   uint       labend;      //Смещение в стэке меток - метка конца

   D( "If start" );
   jmpend = -1;

   while ( 1 )
   {
      //Обработка логического выражения
      curlex = f_expr( curlex, EXPR_BOOL, 0, 0 );
      //Добавляем переход на следующий
      jmpnext = j_jump( CIfze, LABT_GTVIRT, -1 );
      //Обработка тела
      curlex = f_body( curlex );

      curlex = lexem_next( curlex, LEXNEXT_IGNLINE );
      if ( curlex->type == LEXEM_KEYWORD &&
            ( curlex->key == KEY_ELIF ||
              curlex->key == KEY_ELSE ))
      {
         //Добавляем переход на конец
         jmpend = j_jump( CGoto, LABT_GTVIRT, jmpend );

         //Добавляем метку на следующий, устанавливаем связь с последним переходом
         ((pflabel)( fd.blabels.data + jmpnext ))->link = j_label( LABT_LABELVIRT, -1);
         jmpnext = -1;
         if ( curlex->key == KEY_ELIF )
         {
D( "Elif start\n" );
            curlex = lexem_next( curlex, 0 );
            continue;
         }
D( "Else start\n" );
         curlex = f_body( lexem_next( curlex, LEXNEXT_IGNLINE ) );
         curlex = lexem_next( curlex, LEXNEXT_IGNLINE );
         break;
      }
      break;
   }
   //Добавляем метку на последний
   labend = j_label( LABT_LABELVIRT, -1 );

   //Корректируем все переходы на конец
   j_correct( jmpend, labend );

   //Корректировка, если нет else
   if ( jmpnext != -1 )
      ((pflabel)( fd.blabels.data + jmpnext ))->link = labend;

D( "If stop\n" );
   return curlex;
}
Esempio n. 2
0
/*-----------------------------------------------------------------------------
*
* ID: c_dowhile 09.02.07 0.0.A.
*
* Summary: <do_while> processing
*
-----------------------------------------------------------------------------*/
plexem STDCALL c_dowhile( plexem curlex )
{
   uint       labbeg;          //Метка начало
   uint       labend;          //Метка конец
   uint       labcont;         //Метка продолжить
   uint       fd_offlcbreak;    //Смещение в таблице меток
   uint       fd_offlccontinue; //Смещение в таблице меток

D( "DoWhile start\n" );
   fd.blcycle++;
   //Добавляем метку на начало
   labbeg = j_label( LABT_LABELVIRT, -1 );

   //Сохраняем последние метки цикла
   fd_offlcbreak = fd.offlcbreak;
   fd_offlccontinue = fd.offlccontinue;

   //Добавляем переход на конец
   fd.offlcbreak = -1;
   fd.offlccontinue = -1;

   //Обработка тела
   curlex = f_body( curlex );

   //Проверка ключевого слова while
   curlex = lexem_next( curlex, LEXNEXT_IGNLINE );
   if ( curlex->type != LEXEM_KEYWORD || curlex->key != KEY_WHILE )
      msg( MExpwhile | MSG_LEXERR, curlex );
   curlex = lexem_next( curlex, 0 );
   //Добавляем метку на продолжить
   labcont = j_label( LABT_LABELVIRT, -1 );

   //Обработка логического выражения
   curlex = f_expr( curlex, EXPR_BOOL, 0, 0);
   //Добавляем переход на начало
   j_jump( CIfnze, LABT_GTVIRT, labbeg );

   //Добавляем метку на конец
   labend = j_label( LABT_LABELVIRT, -1 );

   //Цикл установки переходов на конец
   j_correct( fd.offlcbreak, labend );

   //Цикл установки переходов на продолжить
   j_correct( fd.offlccontinue, labcont );

   //Восстановление меток цикла
   fd.offlcbreak = fd_offlcbreak;
   fd.offlccontinue = fd_offlccontinue;
   fd.blcycle--;
D( "DoWhile stop\n" );
   return curlex;
}
void SMSMessageBuilder::initialize()
{
    QString location = QString("");
    QString source = QString("");

    location += (config->getPropertyValue("SMS", "TemplateLocation")).toString();
    source += location;
    source += QString("/");
    source += (config->getPropertyValue("SMS", "TemplateDescription")).toString();

    // Opens a file and sets a document content
    QFile f_document(source);
    QDomDocument d_document;
    QString errorMessage;
    int errorLine;
    int errorColumn;
    d_document.setContent(&f_document, &errorMessage, &errorLine, &errorColumn);

    // Gets the root node
    QDomElement d_description = d_document.namedItem("Description").toElement();

    // Gets a file which contains a message body
    QDomElement d_body = d_description.firstChildElement("body");

    // Reads the message body
    QFile f_body(location + QString("/") + d_body.text().trimmed());
    if (f_body.open(QIODevice::ReadOnly))
    {
        QTextStream stream(&f_body);
        stream.setCodec("UTF-8");
        body = new QString(stream.readAll());
    }

    // Reads tags
    QHash<QString, QString> tags;
    QDomElement d_tags = d_description.firstChildElement("tags");
    QDomNode d_tag = d_tags.firstChild();
    for ( ; !d_tag.isNull(); d_tag = d_tag.nextSibling())
    {
        QDomElement tmp = d_tag.toElement();
        tags[tmp.attribute("key")] = tmp.attribute("value");
    }

    // Replaces tags within the message body
    QList<QString> keys = tags.keys();
    QList<QString>::iterator i;
    for (i = keys.begin(); i != keys.end(); ++i)
    {
        body->replace(QRegExp(*i), tags[*i]);
    }
}
Esempio n. 4
0
/*-----------------------------------------------------------------------------
*
* ID: c_while 09.02.07 0.0.A.
*
* Summary: The while processing
*
-----------------------------------------------------------------------------*/
plexem STDCALL c_while( plexem curlex )
{
   uint       labbeg;          //Метка начало
   uint       labend;          //Метка конец
   uint       offlcbreak;    //Смещение в таблице меток
   uint       offlccontinue; //Смещение в таблице меток

   fd.blcycle++;
D( "While start\n" );
   //Добавляем метку на начало
   labbeg = j_label( LABT_LABELVIRT, -1 );

   //Обработка логического выражения
   curlex = f_expr( curlex, EXPR_BOOL, 0, 0 );

   //Сохраняем последние метки цикла
   offlcbreak = fd.offlcbreak;
   offlccontinue = fd.offlccontinue;

   //Добавляем переход на конец
   fd.offlcbreak = j_jump( CIfze, LABT_GTVIRT, -1);
   fd.offlccontinue = -1;

   //Обработка тела
   curlex = f_body( curlex );

   //Добавляем переход на начало
   j_jump( CGoto, LABT_GTVIRT, labbeg );

   //Добавляем метку на конец
   labend = j_label( LABT_LABELVIRT, -1 );

   //Цикл установки переходов на конец
   j_correct( fd.offlcbreak, labend );

   //Цикл установки переходов на начало
   j_correct( fd.offlccontinue, labbeg );

   //Восстановление меток цикла
   fd.offlcbreak = offlcbreak;
   fd.offlccontinue = offlccontinue;
   fd.blcycle--;
D( "While stop\n" );
   return curlex;
}
Esempio n. 5
0
/*-----------------------------------------------------------------------------
*
* ID: m_func 02.11.06 0.0.A.
*
* Summary: The func, method, operator, property, text processing
*
-----------------------------------------------------------------------------*/
plexem STDCALL m_func( plexem curlex, uint flgextern )
{
#ifdef DOUT
   uint     i;
#endif 


   uint     funckey;  //Вид функции
   uint     flgfunc;  //Флаги функции   

   pflabel  curlabel; // Текущий элемент в таблице меток
   pflabel  endlabel; // Конец таблицы меток
   uint     isreturn; //Есть return

   uint     thistype; //Тип переменной this для методов+
   pubyte   name;     //Имя функции
   plexem   lexname;  //Лексема с именем функции
   plexem   lexprev;

   s_desctype desctype;//Описание типа
   s_descid   descvar; //Описание переменной

   uint off_parcount; //Смещение в заголовке функции на кол. параметров
   uint off_blccount; //Смещение в заголовке функции на кол. блоков

   bcflag     bcf;    //Переменная для получение флагов функции
   pbuf       b;
   pfwith     pwith; 
   pvmobj     funcobj;   
   uint       thisid; //Номер переменной для this в текст функции

D( "Func start\n" );

// Инициализация
   desctype.idtype = 0;
   descvar.idtype = 0;
   descvar.flgdesc = 0;
   mem_zero( &fd, sizeof( fd ) );
   thistype = 0;
   funckey = curlex->key;
   hash_init( &fd.nvars, sizeof( uint ) );
   hash_init( &fd.nlabels, sizeof( uint ) );
   for ( b = &fd.bhead; b <= &fd.bvarsas; b++ )
   {
      buf_init( b );
      buf_reserve( b, 0x200 );
      b->step = 0x200;
   }
   fd.bvars.use = sizeof( fvar );
   fd.blabels.use = sizeof( flabel );
//   _compile->pout = &fd.bhead;   
//   fd.blcount = 0;
//   fd.varcount = 0;
//   fd.curcount = 0;
//   fd.lastcurcount = 0;
//   fd.bllevel = 0;
//   fd.blcycle = 0;
   fd.offlcbreak = -1;
   fd.offlccontinue = -1;   
//   fd.functype = 0;

   switch ( funckey )
   {
      case KEY_METHOD:
         flgfunc = GHBC_METHOD;
         break;
      case KEY_OPERATOR:
         flgfunc = GHBC_OPERATOR;
         break;
      case KEY_PROPERTY:
         flgfunc = GHBC_PROPERTY;
         break;
      case KEY_TEXT:
         flgfunc = GHBC_TEXT;
         break;
      default:
         flgfunc = 0;
   }
   curlex = lexem_next( curlex, LEXNEXT_IGNLINE );

// Получаем тип возвращаемого значения функции/метода если он есть
   if ( curlex->type == LEXEM_NAME )
      curlex = desc_idtype( curlex, &desctype );

   if ( desctype.idtype )
   {
      if ( ( funckey == KEY_METHOD || funckey == KEY_PROPERTY ) &&
           curlex->type == LEXEM_OPER &&
           curlex->oper.operid == OpWith )
      {
         //Возврат на лексему влево текущая лексема тип объекта
         desctype.idtype = 0;
         curlex--;
      }
      else
      {
         fd.functype = desctype.idtype;
         fd.funcoftype = desctype.oftype;
      }
   }
   lexprev = curlex;
   curlex = lexem_next( curlex, LEXNEXT_SKIPLINE );
// Получаем тип объекта для метода
   if ( funckey == KEY_METHOD || funckey == KEY_PROPERTY )
   {
      //Получаем тип объекта
	  if ( curlex->type > 32 )
		 msg( MExptype | MSG_LEXERR, lexprev );
	  if ( thistype = bc_type( curlex ) )
      {
         curlex = lexem_next( curlex, 0 );
         if ( curlex->type == LEXEM_OPER &&
              curlex->oper.operid == OpWith )
         {
            curlex = lexem_next( curlex, 0 );
         }
         else
            msg( MExppoint | MSG_LEXERR, curlex );
      }
      else
         msg( MExptype | MSG_LEXERR, curlex );
   }
// Получение имени функции, метода ...   
   if ( funckey == KEY_OPERATOR )
   {
      if ( curlex->type != LEXEM_OPER )
         msg( MExpoper | MSG_LEXERR, curlex );
      name = ( pubyte )&curlex->oper.name;
   }
   else
   {
      if ( curlex->type != LEXEM_NAME )
         msg( MExpname | MSG_LEXERR, curlex );
      name = lexem_getname( curlex );      
   }
   lexname = curlex;
   _vm.pos = curlex->pos;
   
// Получение списка директив
   curlex = lexem_next( curlex, flgextern ? 0 : LEXNEXT_IGNLINE );   
   curlex = bc_flag( curlex, BFLAG_FUNC, &bcf );   
   flgfunc |= GHCOM_NAME | bcf.value;
   _compile->pout = &fd.bhead;   
   out_head( OVM_BYTECODE, flgfunc, name );

   create_varmode( &fd.bhead, &desctype, 0 );//Возвращаемое значение

   off_parcount = fd.bhead.use;
   out_adduint( 0 );//Количество параметров

   if ( funckey == KEY_METHOD || funckey == KEY_PROPERTY )
   {   //Создание параметра this
      mem_zero( &descvar, sizeof( descvar ));
      descvar.idtype = thistype;
      descvar.name = "this";
      descvar.lex = curlex;
      descvar.flgdesc = DESCID_PARFUNC;

      pwith = ( pfwith )buf_appendtype( &fd.bwith, sizeof( fwith )) ;
      pwith->num = var_checkadd( &descvar );
      pwith->oftype = 0;
      pwith->type = thistype;
   }

//Получение списка параметров
   if ( curlex->type == LEXEM_OPER &&
        curlex->oper.operid == OpLbrack )//Открывающая скобка
   {
      curlex = lexem_next( curlex, LEXNEXT_IGNLINE );
      curlex = var_def( curlex, DESCID_PARFUNC );
      if ( curlex->type != LEXEM_OPER ||//Системная лексема
           curlex->oper.operid != OpRbrack )//Закрывающая скобка
         msg( MExpclosebr | MSG_LEXERR, curlex );

      curlex = lexem_next( curlex, flgextern ? 0 : LEXNEXT_IGNLINE );
   }
   else
   {
      if ( funckey == KEY_OPERATOR )
         msg( MExpopenbr | MSG_LEXERR, curlex );
   }

   fd.flgfunc = flgfunc;
   if ( flgfunc & GHBC_RESULT )
   {   //Создание параметра result
      if ( !fd.functype || fd.functype <= TUlong )
         msg( MResulttype | MSG_LEXERR, curlex );
      mem_zero( &descvar, sizeof( descvar ));
      descvar.idtype = desctype.idtype;
      descvar.oftype = desctype.oftype;
      descvar.flgdesc = DESCID_PARFUNC;
      descvar.name = "result";
      descvar.lex = curlex;
      fd.idresult = var_checkadd( &descvar );
      fd.functype = 0;
   }
   if ( fd.varcount )
   {
      *( puint )( fd.bhead.data + off_parcount ) = fd.varcount;//Кол-во параметров
      if ( flgfunc & ( GHBC_ENTRY | GHBC_MAIN ) )
         msg( MMainpar | MSG_LEXERR, curlex );
      fd.curcount = 0;
   }
   off_blccount = fd.bhead.use;
   out_adduint( 0 );//Количество блоков

   if ( funckey == KEY_PROPERTY )
   {      
      if ( ( fd.functype && fd.varcount > 1 ) ||
           (!fd.functype && fd.varcount != 2 ))
      {
         msg( MProppar | MSG_LEXERR, curlex );//Неверное количество параметров в описании свойства
      }
      if ( type_fieldname( thistype, name ) )
      {
         msg( MPropfield | MSG_LEXERR, curlex );//Свойство совпадает с именем поля
      }
   }
   
   funcobj = load_bytecode( &fd.bhead.data, flgextern ? VMLOAD_EXTERN : VMLOAD_FIRST );   
   if ( bcf.value & GHRT_ALIAS )
   {  
      alias_setid( bcf.alias, funcobj->id );     
   }
   if ( !( flgextern ) )
   {      
      if ( _compile->flag & CMPL_DEBUG )
      {  
         _compile->pout = fd.bout = &fd.bsubout;
         out_adduints( 3,  CDatasize, 
                           str_len( _compile->cur->filename ) + 5,
                           str_pos2line( _compile->cur->src, lexname->pos, 0 ) + 1 );
         out_addptr( str_ptr( _compile->cur->filename ), str_len( _compile->cur->filename ) + 1 );                     
         out_adduint( CDbgFunc );
         _compile->pout = fd.bout = &fd.bfuncout; 
      }
      _compile->pout = fd.bout = &fd.bfuncout;
      if ( funckey == KEY_TEXT )
      {   //Создание параметра this для Text функции
         mem_zero( &descvar, sizeof( descvar ));
         descvar.idtype = TUint;
         descvar.name = "this";
         descvar.lex = curlex;
         descvar.flgdesc = DESCID_VAR;///DESCID_PARFUNC;
         thisid = var_checkadd( &descvar );
         
         /*pwith = ( pfwith )buf_appendtype( &fd.bwith, sizeof( fwith )) ;
         pwith->num = var_checkadd( &descvar );
         //print( "ssssssssss %x %x %x %x", fd.bvars.data, fd.bvars.use, pwith->num, sizeof( fvar ) );
         pwith->oftype = 0;
         pwith->type = TStr;*/
         ((pfvar)(fd.bvars.data + fd.bvars.use - sizeof( fvar )))->type = TStr;
         out_adduints( 4, CVarptrload, thisid, CGetText, CSetI );
         /*buf_appenduint( &fd.bblinit, CVarptrload );
         buf_appenduint( &fd.bblinit, thisid );
         buf_appenduint( &fd.bblinit, CGetText );
         buf_appenduint( &fd.bblinit, CSetI );*/
      }
      curlex = f_body( curlex );
      
      *((puint)(fd.bhead.data+off_blccount)) = fd.blcount;

      curlabel = ( pflabel )( fd.blabels.data ) + 1;
      endlabel = ( pflabel )( fd.blabels.data + fd.blabels.use );
      //Контроль неразрешённых меток и проверка выходов из функции
      isreturn = 0;
      while( curlabel < endlabel )
      {
         if ( curlabel->type & LABT_GT )
         {
            if ( ( curlabel->type & LABT_GTUNDEF ) == LABT_GTUNDEF )
               msg( MUnklabel | MSG_LEXNAMEERR, curlabel->lex );
            *( puint )(fd.bfuncout.data + curlabel->offbout ) = 
                     ((( pflabel )(fd.blabels.data + curlabel->link ))->offbout + 
                      fd.bsubout.use )/sizeof(uint);
            if ( !isreturn )//Помечаем метку как отработавшую (на неё был переход)
               (( pflabel )(fd.blabels.data + curlabel->link ))->type |= LABT_LABELWORK;            
         }
         else
         if ( curlabel->type & LABT_RETURN )
         {
            isreturn = 1;//Устанавливаем флаг
         }
         else
         if ( curlabel->type & LABT_LABELWORK )
            isreturn = 0;//Если была отработавшая метка, то сбрасываем флаг
         curlabel++;
      }
      if ( fd.functype )
      {
         if ( !isreturn )
            msg( MMustret | MSG_LEXNAMEERR, lexname );
      }
      else
         if ( !isreturn )
         {
            if ( fd.flgfunc & GHBC_RESULT )
            {
               out_add2uint( CVarload, fd.idresult );
            }
            out_adduint( CReturn );
         }      
      buf_add( &fd.bhead, &fd.bvardef );
      
      if ( fd.bsubout.use )
      {
         if ( fd.offsubgoto )
         {
            //*((( puint)fd.bsubout.data ) + 1) = fd.bsubout.use/sizeof( uint );
            *( puint )( fd.bsubout.data + fd.offsubgoto ) = fd.bsubout.use / sizeof( uint );
         }
         buf_add( &fd.bhead, &fd.bsubout );
      }
      buf_add( &fd.bhead, &fd.bfuncout );
      _compile->pout = &fd.bhead;
      out_finish();
#ifdef DOUT
   //Тестируемый вывод 
   //if ( name[0] == 'c' && name[1] == 'r' ) getch();
   print( "FUNC OUT %x %s:\n", funcobj->id, name );
   for (i = 0; i < fd.bhead.use ; i++ )
   {
      print( "  %x", fd.bhead.data[i] );
   } 
   print( "\n" );
#endif            
      load_bytecode( &fd.bhead.data, VMLOAD_OK );
    //  print( "funcobjid2 =%x\n", funcobj->id );
   }
   //Очистка памяти
   for ( b = &fd.bhead;/*&fd.bblinit;*/ b <= &fd.bvarsas; b++ )
   {
      buf_delete( b );
   }
   hash_delete( &fd.nvars );
   hash_delete( &fd.nlabels );

D( "Func Stop\n" );
   return curlex;
}
Esempio n. 6
0
/*-----------------------------------------------------------------------------
*
* ID: f_subfunc 02.02.06 0.0.A.
*
* Summary: The subfunc processing
*
-----------------------------------------------------------------------------*/
plexem STDCALL f_subfunc( plexem curlex )
{
   uint       fd_lastcurcount;//Предыдущее значение кол. переменных в верхнем блоке
   uint       fd_functype;  //Текущий тип функции
   uint       fd_funcoftype;  //Текущий подтип функции
   uint       fd_oldoffbvar;//Текущее смещение в стэке локальных переменных
   uint       offbvars;     //Смещение в стэке локальных переменных для подфункции

   pflabel    curlabel;     //Текущий элемент в таблице меток
   pflabel    endlabel;     //Конец таблицы меток
   uint       offblabels;   //Начало подфункции в стэке меток

   uint       addr;         //Адрес подфункции в байткоде
   uint       pars;         //Количество параметров у подфункции
   uint       offbvardef;   //Смещение в буфере описание переменных

   s_desctype desctype;     //Структура для получения типа подфункции
   s_descid   descvar;      //Структура для описания подфункции как локальной переменной
   pfvar      var;          //Указатель на локальную переменную-подфункцию

   uint       isreturn;     //Флаг выхода из функции
   plexem     lexname;      //Лексема с именем функции
   uint       off;          //Временная переменная для смещений

   if ( fd.bllevel > 1 )
      msg( MSublevel | MSG_LEXERR, curlex );

//Инициализация
   desctype.idtype = 0;
   descvar.idtype = 0;
   _compile->pout = fd.bout = &fd.bsubout;

   offblabels  = fd.blabels.use;
   fd_functype = fd.functype;
   fd_funcoftype = fd.funcoftype;

   //if ( !fd.bsubout.use )
   if ( !fd.offsubgoto )
   {
      out_add2uint( CGoto, 0 );
      fd.offsubgoto = fd.bsubout.use - 4;
   }
   addr = fd.bsubout.use/sizeof( uint );

//Тип возвращаемого значения если указан   
   if ( curlex->type == LEXEM_NAME )
      curlex = desc_idtype( curlex, &desctype );
   if ( desctype.idtype )
   {
      fd.functype = desctype.idtype;
      fd.funcoftype = desctype.oftype;
      //Инициализация возврата
      out_add2uint( CSubret, (( povmtype)PCMD( fd.functype ))->stsize );
   }
   else
   {
      fd.functype = 0;
      fd.funcoftype = 0;
   }
//Имя функции
   curlex = lexem_next( curlex, LEXNEXT_SKIPLINE );
   if ( curlex->type != LEXEM_NAME )
      msg( MExpname | MSG_LEXERR, curlex );//Ошибка Должен быть идентификатор
   lexname = curlex;
   offbvars = fd.bvars.use;
   descvar.idtype = fd.functype;
   descvar.oftype = fd.funcoftype;
   descvar.name = lexem_getname( lexname );
   descvar.lex = lexname;
   descvar.flgdesc = DESCID_SUBFUNC;
   var_checkadd( &descvar );

//Список параметров
   curlex = lexem_next( curlex, LEXNEXT_IGNLINE );
   fd_oldoffbvar = fd.oldoffbvar;
   fd.oldoffbvar = fd.bvars.use;
   pars = 0;
   if ( curlex->type == LEXEM_OPER &&
        curlex->oper.operid == OpLbrack )//Открывающая скобка
   {
      curlex = lexem_next( curlex, LEXNEXT_IGNLINE );

      fd_lastcurcount = fd.lastcurcount;
      fd.lastcurcount = fd.curcount;
      fd.curcount = 0;
      offbvardef = fd.bvardef.use;

      curlex = var_def( curlex, DESCID_PARSUBFUNC );

      pars = fd.curcount;
      if ( fd.curcount )
      {
         out_add2uint( CSubpar, fd.blcount - 1 );//Загрузка параметров
         buf_appenduint( &fd.bhead, fd.curcount );
         fd.curcount = 0;
      }
      else
      {
         fd.curcount = fd.lastcurcount;
         fd.lastcurcount = fd_lastcurcount;
      }

      if ( curlex->type != LEXEM_OPER ||
           curlex->oper.operid != OpRbrack )//Закрывающая скобка
         msg( MExpclosebr | MSG_LEXERR, curlex );// Ошибка Ожадается закрывающая скобка
      curlex = lexem_next( curlex, LEXNEXT_IGNLINE );
   }

//Запись подфункции как локальной переменной
   var = (pfvar)( fd.bvars.data + offbvars );
   var->flg  = FVAR_SUBFUNC;
   var->addr = addr;
   var->pars = pars;
   var->offbvardef = offbvardef;

//Обработка тела функции
   curlex = f_body( curlex );

//Очистка параметров из стэка локальных переменных
   off = (uint)fd.bvars.data + fd.oldoffbvar;
   for ( (uint)var = (uint)fd.bvars.data + fd.bvars.use - sizeof( fvar );
         (uint)var >= off; var-- )
   {
      if ( var->hidn )
         var->hidn->val = var->oldoffbvar;
   }
   fd.bvars.use = fd.oldoffbvar;
   fd.oldoffbvar = fd_oldoffbvar;

//Установка переходов, корректировка меток
   isreturn = 0;
   curlabel = ( pflabel )( fd.blabels.data + offblabels );
   endlabel = ( pflabel )( fd.blabels.data + fd.blabels.use );
   while( curlabel < endlabel )
   {
      if ( curlabel->type & LABT_GT )
      {
         if ( ( curlabel->type & LABT_GTUNDEF ) == LABT_GTUNDEF )
            msg( MUnklabel | MSG_LEXNAMEERR, curlabel->lex );

         *( puint )(fd.bsubout.data + curlabel->offbout ) =
               ((( pflabel )(fd.blabels.data + curlabel->link ))->offbout)/sizeof(uint);
         if ( !isreturn )
         {
            //Помечаем метку как отработавшую (на неё был переход)
            (( pflabel )(fd.blabels.data + curlabel->link ))->type |= LABT_LABELWORK;
         }
      }
      else
      if ( curlabel->type & LABT_RETURN )
         isreturn = 1;//Устанавливаем флаг
      else
      if ( curlabel->type & LABT_LABELWORK )
         isreturn = 0;//Если была отработавшая метка, то сбрасываем флаг
      curlabel++;
   }
   fd.blabels.use = offblabels;

//Проверка выходов из функции
   if ( fd.functype )
   {
      if ( !isreturn )
         msg( MMustret | MSG_LEXNAMEERR, lexname );
   }
   else
      if ( !isreturn )
         out_adduint( CSubreturn );
//Восстановление данных
   _compile->pout = fd.bout = &fd.bfuncout;
   fd.functype = fd_functype;
   fd.funcoftype = fd_funcoftype;

   return curlex;
}