1 /******************************************************************************
2 *
3 * Copyright (C) 2006, The Gentee Group. All rights reserved.
4 * This file is part of the Gentee open source project - http://www.gentee.com.
5 *
6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
8 * ACCEPTANCE OF THE AGREEMENT.
9 *
10 * ID: subfunc 02.02.06 0.0.A.
11 *
12 * Author: Alexander Krivonogov ( algen )
13 *
14 * Summary: Обработка подфункции
15 *
16 ******************************************************************************/
17
18 #include "func.h"
19
20 /*-----------------------------------------------------------------------------
21 *
22 * ID: f_subfunc 02.02.06 0.0.A.
23 *
24 * Summary: The subfunc processing
25 *
26 -----------------------------------------------------------------------------*/
27 plexem STDCALL f_subfunc( plexem curlex )
28 {
29 uint fd_lastcurcount;//Предыдущее значение кол. переменных в верхнем блоке
30 uint fd_functype; //Текущий тип функции
31 uint fd_funcoftype; //Текущий подтип функции
32 uint fd_oldoffbvar;//Текущее смещение в стэке локальных переменных
33 uint offbvars; //Смещение в стэке локальных переменных для подфункции
34
35 pflabel curlabel; //Текущий элемент в таблице меток
36 pflabel endlabel; //Конец таблицы меток
37 uint offblabels; //Начало подфункции в стэке меток
38
39 uint addr; //Адрес подфункции в байткоде
40 uint pars; //Количество параметров у подфункции
41 uint offbvardef; //Смещение в буфере описание переменных
42
43 s_desctype desctype; //Структура для получения типа подфункции
44 s_descid descvar; //Структура для описания подфункции как локальной переменной
45 pfvar var; //Указатель на локальную переменную-подфункцию
46
47 uint isreturn; //Флаг выхода из функции
48 plexem lexname; //Лексема с именем функции
49 uint off; //Временная переменная для смещений
50
51 if ( fd.bllevel > 1 )
52 msg( MSublevel | MSG_LEXERR, curlex );
53
54 //Инициализация
55 desctype.idtype = 0;
56 descvar.idtype = 0;
57 _compile->pout = fd.bout = &fd.bsubout;
58
59 offblabels = fd.blabels.use;
60 fd_functype = fd.functype;
61 fd_funcoftype = fd.funcoftype;
62
63 //if ( !fd.bsubout.use )
64 if ( !fd.offsubgoto )
65 {
66 out_add2uint( CGoto, 0 );
67 fd.offsubgoto = fd.bsubout.use - 4;
68 }
69 addr = fd.bsubout.use/sizeof( uint );
70
71 //Тип возвращаемого значения если указан
72 if ( curlex->type == LEXEM_NAME )
73 curlex = desc_idtype( curlex, &desctype );
74 if ( desctype.idtype )
75 {
76 fd.functype = desctype.idtype;
77 fd.funcoftype = desctype.oftype;
78 //Инициализация возврата
79 out_add2uint( CSubret, (( povmtype)PCMD( fd.functype ))->stsize );
80 }
81 else
82 {
83 fd.functype = 0;
84 fd.funcoftype = 0;
85 }
86 //Имя функции
87 curlex = lexem_next( curlex, LEXNEXT_SKIPLINE );
88 if ( curlex->type != LEXEM_NAME )
89 msg( MExpname | MSG_LEXERR, curlex );//Ошибка Должен быть идентификатор
90 lexname = curlex;
91 offbvars = fd.bvars.use;
92 descvar.idtype = fd.functype;
93 descvar.oftype = fd.funcoftype;
94 descvar.name = lexem_getname( lexname );
95 descvar.lex = lexname;
96 descvar.flgdesc = DESCID_SUBFUNC;
97 var_checkadd( &descvar );
98
99 //Список параметров
100 curlex = lexem_next( curlex, LEXNEXT_IGNLINE );
101 fd_oldoffbvar = fd.oldoffbvar;
102 fd.oldoffbvar = fd.bvars.use;
103 pars = 0;
104 if ( curlex->type == LEXEM_OPER &&
105 curlex->oper.operid == OpLbrack )//Открывающая скобка
106 {
107 curlex = lexem_next( curlex, LEXNEXT_IGNLINE );
108
109 fd_lastcurcount = fd.lastcurcount;
110 fd.lastcurcount = fd.curcount;
111 fd.curcount = 0;
112 offbvardef = fd.bvardef.use;
113
114 curlex = var_def( curlex, DESCID_PARSUBFUNC );
115
116 pars = fd.curcount;
117 if ( fd.curcount )
118 {
119 out_add2uint( CSubpar, fd.blcount - 1 );//Загрузка параметров
120 buf_appenduint( &fd.bhead, fd.curcount );
121 fd.curcount = 0;
122 }
123 else
124 {
125 fd.curcount = fd.lastcurcount;
126 fd.lastcurcount = fd_lastcurcount;
127 }
128
129 if ( curlex->type != LEXEM_OPER ||
130 curlex->oper.operid != OpRbrack )//Закрывающая скобка
131 msg( MExpclosebr | MSG_LEXERR, curlex );// Ошибка Ожадается закрывающая скобка
132 curlex = lexem_next( curlex, LEXNEXT_IGNLINE );
133 }
134
135 //Запись подфункции как локальной переменной
136 var = (pfvar)( fd.bvars.data + offbvars );
137 var->flg = FVAR_SUBFUNC;
138 var->addr = addr;
139 var->pars = pars;
140 var->offbvardef = offbvardef;
141
142 //Обработка тела функции
143 curlex = f_body( curlex );
144
145 //Очистка параметров из стэка локальных переменных
146 off = (uint)fd.bvars.data + fd.oldoffbvar;
147 for ( (uint)var = (uint)fd.bvars.data + fd.bvars.use - sizeof( fvar );
148 (uint)var >= off; var-- )
149 {
150 if ( var->hidn )
151 var->hidn->val = var->oldoffbvar;
152 }
153 fd.bvars.use = fd.oldoffbvar;
154 fd.oldoffbvar = fd_oldoffbvar;
155
156 //Установка переходов, корректировка меток
157 isreturn = 0;
158 curlabel = ( pflabel )( fd.blabels.data + offblabels );
159 endlabel = ( pflabel )( fd.blabels.data + fd.blabels.use );
160 while( curlabel < endlabel )
161 {
162 if ( curlabel->type & LABT_GT )
163 {
164 if ( ( curlabel->type & LABT_GTUNDEF ) == LABT_GTUNDEF )
165 msg( MUnklabel | MSG_LEXNAMEERR, curlabel->lex );
166
167 *( puint )(fd.bsubout.data + curlabel->offbout ) =
168 ((( pflabel )(fd.blabels.data + curlabel->link ))->offbout)/sizeof(uint);
169 if ( !isreturn )
170 {
171 //Помечаем метку как отработавшую (на неё был переход)
172 (( pflabel )(fd.blabels.data + curlabel->link ))->type |= LABT_LABELWORK;
173 }
174 }
175 else
176 if ( curlabel->type & LABT_RETURN )
177 isreturn = 1;//Устанавливаем флаг
178 else
179 if ( curlabel->type & LABT_LABELWORK )
180 isreturn = 0;//Если была отработавшая метка, то сбрасываем флаг
181 curlabel++;
182 }
183 fd.blabels.use = offblabels;
184
185 //Проверка выходов из функции
186 if ( fd.functype )
187 {
188 if ( !isreturn )
189 msg( MMustret | MSG_LEXNAMEERR, lexname );
190 }
191 else
192 if ( !isreturn )
193 out_adduint( CSubreturn );
194 //Восстановление данных
195 _compile->pout = fd.bout = &fd.bfuncout;
196 fd.functype = fd_functype;
197 fd.funcoftype = fd_funcoftype;
198
199 return curlex;
200 }