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: expmacro 18.10.06 0.0.A.
11 *
12 * Author: Alexander Krivonogov ( algen )
13 *
14 * Summary: Обработка макро выражений
15 *
16 ******************************************************************************/
17
18 #include "macroexp.h"
19
20 /*-----------------------------------------------------------------------------
21 *
22 * ID: macroepr 18.10.06 0.0.A.
23 *
24 * Summary: The macro expression processing
25 *
26 -----------------------------------------------------------------------------*/
27 /*Возможны операции
28 с целыми числами + - +ун -ун * / ! && || & | ~ > < >= <= == !=
29 с дробными числами + - +ун -ун * / ! && || > < >= <= == !=
30 со строками и буфером ! && ||(Длина) == != (значения)
31 */
32 plexem STDCALL macroexpr( plexem curlex, pmacrores * mr )
33 {
34 psoper curop; //Текущая операция
35 psoper stackop; //Оператор из стэка
36
37 uint bropen; //Количество открытых скобок ( и [
38 uint flgexp; //Флаг определяющий конец разбора
39 uint state; //Флаг типа текущей лексемы L_*
40 uint laststate; //Флаг типа предыдущей лексемы L_*
41
42 pmacrooper stackb; //Указатель на начало стэка операций
43 pmacrooper stackc; //Указатель на следующий элемент стэка операций
44
45 pmacrores tokb; //Указатель на начало таблицы
46 pmacrores tokc; //Указатель на следующий элемент таблицы
47 pmacrores tokleft; //Указатель на левый операнд для IFDEF
48 pmacrores tokright; //Указатель на правый операнд для IFDEF
49 plexem maxlex;
50
51 pbuf bcol; //Буфер с коллекцией
52 pstr strt; //Указатель на строку
53 pbuf buft; //Указатель на бинарные данные
54
55 uint curop_flgs;
56 uint curop_before;
57 uint curop_id;
58 uint stackop_flgs;
59 uint stackop_after;
60 uint stackop_id;
61
62 uint left_type, flg_resuint, flg_not;
63 uint left_numtype, right_numtype;
64 uint left_bvalue, right_bvalue;
65 int left_int, right_int;
66 int left_intl, left_intf, left_intd;
67 long64 left_long, right_long;
68 float left_float, right_float;
69 double left_double, right_double;
70
71 // Инициализация
72 stackb = _compile->stkmopers;//Стэк операций
73 stackc = stackb;
74 tokb = _compile->stkmops;//Стэк операндов
75 tokc = tokb;
76 flgexp = 1;
77 bropen = 0;
78 laststate = L_UNARY_OPEN;
79 maxlex = curlex + min( STACK_OPERS / sizeof( macrooper ), STACK_OPS / sizeof( macrores ) );
80 D("Macroexp start\n" );
81
82 //Цикл формирования байткода
83 while ( 1 )
84 {
85 // Обработка системной лексемы
86 if ( curlex->type == LEXEM_OPER )
87 {
88 curop_id = curlex->oper.operid;
89 curop = (psoper)&opers[curop_id];
90 curop_flgs = curop->flgs;
91
92 // Первичная обработка
93 if ( curop_flgs & OPF_OPEN )//Открывающие скобки
94 {
95 if ( curop_id == OpLcrbrack )
96 flgexp = 0;//Если в конце выражения откр. фиг. скобка, то выходим из цикла
97 else
98 {
99 state = L_UNARY_OPEN;
100 bropen++;
101 }
102 }
103 else
104 if ( curop_flgs & OPF_CLOSE )//Закрывающие скобки
105 {
106 if ( bropen )
107 {
108 state = L_POST_CLOSE;
109 bropen--;
110 }
111 else
112 {
113 if ( curop_id == OpRcrbrack ||
114 ( stackc != stackb ||
115 tokc != tokb ))
116 flgexp = 0;//Непарная скобка
117 else
118 msg( MSyntax | MSG_LEXNAMEERR, curlex );
119 }
120 }
121 else
122 if ( curop_id == OpLine ) // ; - Точка с запятой - Перенос строки
123 {
124 if ( laststate & L_BINARY || bropen > 0 )
125 goto next;
126 flgexp = 0;
127 }
128 else
129 if ( curop_id == OpComma )//, - Запятая
130 {
131 if ( !bropen )
132 {
133 flgexp = 0;
134 }
135 }
136 else
137 if ( curop_flgs & OPF_UNDEF ) //Неопределённый оператор
138 {
139 if ( laststate & ( L_OPERAND | L_POST_CLOSE ))
140 {
141 curop = ( psoper )&opers[curop_id = ++curlex->oper.operid];
142 curop_flgs = curop->flgs;
143 }
144 }
145
146 // Дополнительная обработка
147 if ( curop_flgs & OPF_BINARY )
148 {
149 state = L_BINARY;
150 }
151 else
152 if ( curop_flgs & OPF_UNARY )
153 {
154 state = L_UNARY_OPEN;
155 }
156 else
157 if ( curop_flgs & OPF_POST )
158 {
159 state = L_POST_CLOSE;
160 }
161 curop_before = curop->before;
162 // Цикл выталкивания из стека операций
163 while ( stackc != stackb )
164 {
165 stackop_id = (stackc-1)->operid;
166 stackop = (psoper)&opers[stackop_id];
167 stackop_after = stackop->after;
168 stackop_flgs = stackop->flgs;
169 flg_not = 0;
170 flg_resuint = 0;
171 if ( !flgexp || stackop_after >= curop_before )
172 {
173 stackc--;
174 if ( !( stackop_flgs & ( OPF_OPEN | OPF_CLOSE ) ||
175 stackop_id == OpComma ) )
176 {
177 if ( stackop_flgs & OPF_BINARY )
178 {
179 tokleft = tokc - 2;
180 tokright = tokc - 1;
181 tokc--;
182 }
183 else
184 {
185 tokleft = tokc - 1;
186 tokright = 0;
187 }
188 if ( tokright && tokright < tokb + 1 )
189 msg( MSyntax | MSG_LEXNAMEERR, curlex );
190
191 left_type = tokleft->vallexem.type;
192 if ( left_type == LEXEM_NUMBER )
193 {
194 left_numtype = tokleft->vallexem.num.type;
195 if ( left_numtype == TUint )
196 left_numtype = TInt;
197 else if ( left_numtype == TUlong )
198 left_numtype = TLong;
199 left_int = tokleft->vallexem.num.vint;
200 left_long = tokleft->vallexem.num.vlong;
201 left_float = tokleft->vallexem.num.vfloat;
202 left_double = tokleft->vallexem.num.vdouble;
203 }
204 else left_numtype = 0;
205 left_bvalue = tokleft->bvalue;
206 if ( tokright )//Бинарная операция
207 {
208 right_bvalue = tokright->bvalue;
209 if ( stackop_id != OpLogand && stackop_id != OpLogor )
210 {
211 if ( left_type != tokright->vallexem.type )
212 goto nosup;
213 if ( left_numtype )
214 {
215 right_numtype = tokright->vallexem.num.type;
216 if ( right_numtype == TUint )
217 right_numtype = TInt;
218 else if ( right_numtype == TUlong )
219 right_numtype = TLong;
220 if ( left_numtype != right_numtype )
221 goto nosup;
222 right_int = tokright->vallexem.num.vint;
223 right_long = tokright->vallexem.num.vlong;
224 right_float = tokright->vallexem.num.vfloat;
225 right_double = tokright->vallexem.num.vdouble;
226 }
227 }
228 if ( left_bvalue == -1 || right_bvalue == -1 )
229 goto nosup;
230 switch ( stackop_id )
231 {
232 //Арифметические операции
233 case OpAdd:
234 if ( left_numtype )
235 {
236 left_int += right_int;
237 left_long += right_long;
238 left_float += right_float;
239 left_double += right_double;
240 break;
241 }
242 goto nosup;
243 case OpSub:
244 if ( left_numtype )
245 {
246 left_int -= right_int;
247 left_long -= right_long;
248 left_float -= right_float;
249 left_double -= right_double;
250 break;
251 }
252 goto nosup;
253 case OpMul:
254 if ( left_numtype )
255 {
256 left_int *= right_int;
257 left_long *= right_long;
258 left_float *= right_float;
259 left_double *= right_double;
260 break;
261 }
262 goto nosup;
263 case OpDiv:
264 if ( left_numtype )
265 {
266 left_int /= right_int;
267 left_long /= right_long;
268 left_float /= right_float;
269 left_double /= right_double;
270 break;
271 }
272 goto nosup;
273
274 //Двоичные операции
275 case OpBinand:
276 switch ( left_numtype )
277 {
278 case TInt:
279 left_int &= right_int;
280 break;
281 case TLong:
282 left_long &= right_long;
283 break;
284 default: goto nosup;
285 }
286 break;
287 case OpBinor:
288 switch ( left_numtype )
289 {
290 case TInt:
291 left_int |= right_int;
292 break;
293 case TLong:
294 left_long |= right_long;
295 break;
296 default: goto nosup;
297 }
298 break;
299 case OpBinxor:
300 switch ( left_numtype )
301 {
302 case TInt:
303 left_int ^= right_int;
304 break;
305 case TLong:
306 left_long ^= right_long;
307 break;
308 default: goto nosup;
309 }
310 break;
311
312 //Логические операции
313 case OpLogand:
314 left_int = ( left_bvalue && right_bvalue ) ? 1 : 0;
315 flg_resuint = 1;
316 break;
317 case OpLogor:
318 left_int = ( left_bvalue || right_bvalue ) ? 1 : 0;
319 flg_resuint = 1;
320 break;
321
322 //Операции равенства
323 case OpNoteq:
324 flg_not = 1;
325 case OpEq:
326 if ( left_type == LEXEM_STRING || left_type == LEXEM_BINARY )
327 {
328 buf_isequal(
329 (pstr)lexem_getstr( &tokleft->vallexem ),
330 (pstr)lexem_getstr( &tokright->vallexem ));
331 }
332 /*else if ( left_type == LEXEM_BINARY )
333 {
334 buf_isequal(
335 (pbuf)lexem_getstr( &tokleft->vallexem ),
336 (pbuf)lexem_getstr( &tokright->vallexem ));
337 }*/
338 else if ( left_numtype )
339 {
340 left_int = left_int == right_int;
341 left_intl = left_long == right_long;
342 left_intf = left_float == right_float;
343 left_intd = left_double == right_double;
344 }
345 else goto nosup;
346 break;
347
348 //Операции сравнения чисел
349 case OpGreateq:
350 flg_not = 1;
351 case OpLess:
352 if ( left_numtype )
353 {
354 left_int = left_int < right_int;
355 left_intl = left_long < right_long;
356 left_intf = left_float < right_float;
357 left_intd = left_double < right_double;
358 flg_resuint = 1;
359 break;
360 }
361 goto nosup;
362 case OpLesseq:
363 flg_not = 1;
364 case OpGreater:
365 if ( left_numtype )
366 {
367 left_int = left_int > right_int;
368 left_intl = left_long > right_long;
369 left_intf = left_float > right_float;
370 left_intd = left_double > right_double;
371 flg_resuint = 1;
372 break;
373 }
374 default: goto nosup;
375 }
376 }
377 else //Унарные операции
378 {
379 switch ( stackop_id )
380 {
381 //Арифметические унарные операции
382 case OpPlus:
383 if ( !left_numtype )
384 goto nosup;
385 break;
386 case OpMinus:
387 if ( left_numtype )
388 {
389 left_int = -left_int;
390 left_long = -left_long;
391 left_float = -left_float;
392 left_double = -left_double;
393 break;
394 }
395 goto nosup;
396
397 //Двоичная унарная операция
398 case OpBinnot:
399 switch ( left_numtype )
400 {
401 case TInt:
402 left_int = !left_int;
403 break;
404 case TLong:
405 left_long = !left_long;
406 break;
407 default:
408 goto nosup;
409 }
410 break;
411
412 //Логическая унарная операция
413 case OpLognot:
414 left_int = !left_bvalue;
415 flg_resuint = 1;
416 break;
417
418 default:
419 goto nosup;
420 }
421 }
422
423 //Конец вычисления операции
424
425 switch ( left_numtype )
426 { //Корректировка значений для чисел
427 case TInt:
428 left_bvalue = (tokleft->vallexem.num.vint = left_int) ? 1 : 0;
429 break;
430 case TLong:
431 left_bvalue = (tokleft->vallexem.num.vlong = left_long) ? 1 : 0;
432 left_int = left_intl;
433 break;
434 case TFloat:
435 left_bvalue = (tokleft->vallexem.num.vfloat =
436 left_float) ? 1 : 0;
437 left_int = left_intf;
438 break;
439 case TDouble:
440 left_bvalue = (tokleft->vallexem.num.vdouble =
441 left_double) ? 1 : 0;
442 left_int = left_intd;
443 break;
444 }
445 if ( flg_resuint )
446 { //Результат операции TUint
447 tokleft->vallexem.type = LEXEM_NUMBER;
448 tokleft->vallexem.num.type = TUint;
449 tokleft->vallexem.num.vint = left_bvalue =
450 flg_not ? !left_int : left_int;
451 }
452
453 tokleft->bvalue = left_bvalue;
454 }
455 else
456 {
457 if ( stackop_id == OpComma )
458 {
459 (stackc-1)->left->colpars++;
460 }
461 else
462 if ( ( curop_id == OpRcrbrack && stackop_id == OpCollect ) )
463 {
464 if ( stackc->left != tokc - 1 )
465 {
466 stackc->left->colpars++;
467 }
468 else
469 {
470 laststate = state;
471 }
472 }
473 else
474 {
475 if ( ( stackop_flgs & OPF_OPEN ) && ( stackop != curop - 1 ) )
476 msg( MNotopenbr | MSG_LEXERR , stackc->operlexem );
477 }
478 }
479
480 }
481 if ( flgexp && stackop_after <= curop_before )
482 { //Выход из цикла
483 break;
484 }
485 continue;
486 nosup:
487 msg( MUnsmoper | MSG_LEXNAMEERR, stackc->operlexem );
488 }
489 // Конец цикла выталкивания из стека операций
490
491 // Добавление в стэк последней операций
492 if ( curop_id == OpCollect )
493 {
494 tokc->bvalue = 1;
495 tokc->vallexem = *curlex;
496 tokc->vallexem.type = LEXEM_COLLECT;
497 tokc->colpars = 0;
498 tokc++;
499 }
500 stackc->operid = curop_id;
501 stackc->operlexem = curlex;
502 stackc->left = tokc-1;
503 stackc++;
504 }
505 // Конец обработки системной лексемы
506 else
507 {
508 // Обработка операндов
509 tokc->vallexem = *curlex;
510 state = L_OPERAND;
511 switch ( curlex->type )
512 {
513 case LEXEM_NUMBER://Число
514 switch ( curlex->num.type )
515 {
516 case TUint:
517 case TInt:
518 tokc->bvalue = tokc->vallexem.num.vint ? 1 : 0;
519 break;
520 case TUlong:
521 case TLong:
522 tokc->bvalue = tokc->vallexem.num.vlong ? 1 : 0;
523 break;
524 case TFloat:
525 tokc->bvalue = tokc->vallexem.num.vfloat ? 1 : 0;
526 break;
527 case TDouble:
528 tokc->bvalue = tokc->vallexem.num.vdouble ? 1 : 0;
529 break;
530 }
531 break;
532
533 case LEXEM_STRING://Строка
534 tokc->bvalue = str_len( lexem_getstr( &tokc->vallexem )) ? 1 : 0;
535 break;
536
537 case LEXEM_BINARY://Двоичные данные
538 tokc->bvalue = buf_len( lexem_getstr( &tokc->vallexem )) ? 1 : 0;
539 break;
540
541 case LEXEM_NAME://Идентификатор
542 tokc->bvalue = -1;
543 break;
544
545 case LEXEM_KEYWORD:
546 msg( MNokeyword | MSG_LEXERR, curlex );
547
548 default:
549 msg( MUnsmoper | MSG_LEXNAMEERR, curlex );
550 }
551 tokc++;
552 }
553 // Проверка синтаксиса выражения
554 if ( flgexp )
555 {
556 switch ( laststate )
557 {
558 case L_OPERAND:
559 case L_POST_CLOSE:
560 if ( state & L_OPERAND ||
561 state & L_UNARY_OPEN )
562 {
563 msg( MUnexpoper | MSG_LEXERR, curlex );
564 }
565 break;
566 default:
567 if ( state & L_BINARY ||
568 state & L_POST_CLOSE )
569 {
570 msg( MMustoper | MSG_LEXERR, curlex );
571 }
572 }
573 laststate = state;
574 }
575 else
576 {
577 if ( ( laststate == L_UNARY_OPEN && tokc != tokb ) ||
578 laststate == L_BINARY )
579 msg( MMustoper | MSG_LEXERR, curlex );
580 break;
581 }
582
583 next:
584 curlex = lexem_next( curlex, 0 );
585 if ( curlex > maxlex )
586 msg( MExpmuch | MSG_LEXERR, curlex );
587 }
588
589 //Возврат значения
590 if ( tokb->vallexem.type == LEXEM_COLLECT )
591 {
592 bcol = buf_init( ( pbuf )arr_append( &_compile->binary ));
593 tokb->vallexem.binid = arr_count( &_compile->binary ) - 1;
594 buf_appenduint( bcol, tokb->colpars );
595
596 for ( tokleft = tokb + 1; tokleft < tokc; tokleft++ )
597 {
598
599 switch ( tokleft->vallexem.type )
600 {
601 case LEXEM_NUMBER:
602 buf_appendch( bcol, (ubyte)tokleft->vallexem.num.type );
603 switch ( tokleft->vallexem.num.type )
604 {
605 case TByte:
606 case TUbyte:
607 buf_appendch( bcol, (ubyte)tokleft->vallexem.num.vint );
608 break;
609 case TShort:
610 case TUshort:
611 buf_appendushort( bcol, (ushort)tokleft->vallexem.num.vint );
612 break;
613 case TUlong:
614 case TLong:
615 case TDouble:
616 buf_appendulong( bcol, tokleft->vallexem.num.vlong );
617 break;
618 default:
619 buf_appenduint( bcol, tokleft->vallexem.num.vint );
620 }
621 break;
622
623 case LEXEM_STRING:
624 buf_appendch( bcol, TStr );
625 strt = lexem_getstr( &tokleft->vallexem );
626 buf_append( bcol, strt->data, strt->use );
627 break;
628
629 case LEXEM_BINARY:
630 buf_appendch( bcol, TBuf );
631 buft = lexem_getstr( &tokleft->vallexem );
632 buf_appenduint( bcol, buft->use );
633 buf_append( bcol, buft->data, buft->use );
634 break;
635
636 case LEXEM_COLLECT:
637 buf_appendch( bcol, TCollection );
638 buf_appenduint( bcol, tokleft->colpars );
639 break;
640
641 default:
642 msg( MSyntax | MSG_LEXNAMEERR, &tokleft->vallexem );
643 }
644 }
645 }
646 else
647 if ( tokc != tokb+1 )
648 {
649 msg( MSyntax | MSG_LEXNAMEERR, curlex );
650 }
651
652 *mr = tokb;
653
654 D("Macroexp stop\n" );
655 return curlex;
656 }
657
658
659