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 left_int = 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 flg_resuint = 1;
347 break;
348
349 //Операции сравнения чисел
350 case OpGreateq:
351 flg_not = 1;
352 case OpLess:
353 if ( left_numtype )
354 {
355 left_int = left_int < right_int;
356 left_intl = left_long < right_long;
357 left_intf = left_float < right_float;
358 left_intd = left_double < right_double;
359 flg_resuint = 1;
360 break;
361 }
362 goto nosup;
363 case OpLesseq:
364 flg_not = 1;
365 case OpGreater:
366 if ( left_numtype )
367 {
368 left_int = left_int > right_int;
369 left_intl = left_long > right_long;
370 left_intf = left_float > right_float;
371 left_intd = left_double > right_double;
372 flg_resuint = 1;
373 break;
374 }
375 default: goto nosup;
376 }
377 }
378 else //Унарные операции
379 {
380 switch ( stackop_id )
381 {
382 //Арифметические унарные операции
383 case OpPlus:
384 if ( !left_numtype )
385 goto nosup;
386 break;
387 case OpMinus:
388 if ( left_numtype )
389 {
390 left_int = -left_int;
391 left_long = -left_long;
392 left_float = -left_float;
393 left_double = -left_double;
394 break;
395 }
396 goto nosup;
397
398 //Двоичная унарная операция
399 case OpBinnot:
400 switch ( left_numtype )
401 {
402 case TInt:
403 left_int = !left_int;
404 break;
405 case TLong:
406 left_long = !left_long;
407 break;
408 default:
409 goto nosup;
410 }
411 break;
412
413 //Логическая унарная операция
414 case OpLognot:
415 left_int = !left_bvalue;
416 flg_resuint = 1;
417 break;
418
419 default:
420 goto nosup;
421 }
422 }
423
424 //Конец вычисления операции
425
426 switch ( left_numtype )
427 { //Корректировка значений для чисел
428 case TInt:
429 left_bvalue = (tokleft->vallexem.num.vint = left_int) ? 1 : 0;
430 break;
431 case TLong:
432 left_bvalue = (tokleft->vallexem.num.vlong = left_long) ? 1 : 0;
433 left_int = left_intl;
434 break;
435 case TFloat:
436 left_bvalue = (tokleft->vallexem.num.vfloat =
437 left_float) ? 1 : 0;
438 left_int = left_intf;
439 break;
440 case TDouble:
441 left_bvalue = (tokleft->vallexem.num.vdouble =
442 left_double) ? 1 : 0;
443 left_int = left_intd;
444 break;
445 }
446 if ( flg_resuint )
447 { //Результат операции TUint
448 tokleft->vallexem.type = LEXEM_NUMBER;
449 tokleft->vallexem.num.type = TUint;
450 tokleft->vallexem.num.vint = left_bvalue =
451 flg_not ? !left_int : left_int;
452 }
453
454 tokleft->bvalue = left_bvalue;
455 }
456 else
457 {
458 if ( stackop_id == OpComma )
459 {
460 (stackc-1)->left->colpars++;
461 }
462 else
463 if ( ( curop_id == OpRcrbrack && stackop_id == OpCollect ) )
464 {
465 if ( stackc->left != tokc - 1 )
466 {
467 stackc->left->colpars++;
468 }
469 else
470 {
471 laststate = state;
472 }
473 }
474 else
475 {
476 if ( ( stackop_flgs & OPF_OPEN ) && ( stackop != curop - 1 ) )
477 msg( MNotopenbr | MSG_LEXERR , stackc->operlexem );
478 }
479 }
480
481 }
482 if ( flgexp && stackop_after <= curop_before )
483 { //Выход из цикла
484 break;
485 }
486 continue;
487 nosup:
488 msg( MUnsmoper | MSG_LEXNAMEERR, stackc->operlexem );
489 }
490 // Конец цикла выталкивания из стека операций
491
492 // Добавление в стэк последней операций
493 if ( curop_id == OpCollect )
494 {
495 tokc->bvalue = 1;
496 tokc->vallexem = *curlex;
497 tokc->vallexem.type = LEXEM_COLLECT;
498 tokc->colpars = 0;
499 tokc++;
500 }
501 stackc->operid = curop_id;
502 stackc->operlexem = curlex;
503 stackc->left = tokc-1;
504 stackc++;
505 }
506 // Конец обработки системной лексемы
507 else
508 {
509 // Обработка операндов
510 tokc->vallexem = *curlex;
511 state = L_OPERAND;
512 switch ( curlex->type )
513 {
514 case LEXEM_NUMBER://Число
515 switch ( curlex->num.type )
516 {
517 case TUint:
518 case TInt:
519 tokc->bvalue = tokc->vallexem.num.vint ? 1 : 0;
520 break;
521 case TUlong:
522 case TLong:
523 tokc->bvalue = tokc->vallexem.num.vlong ? 1 : 0;
524 break;
525 case TFloat:
526 tokc->bvalue = tokc->vallexem.num.vfloat ? 1 : 0;
527 break;
528 case TDouble:
529 tokc->bvalue = tokc->vallexem.num.vdouble ? 1 : 0;
530 break;
531 }
532 break;
533
534 case LEXEM_STRING://Строка
535 tokc->bvalue = str_len( lexem_getstr( &tokc->vallexem )) ? 1 : 0;
536 break;
537
538 case LEXEM_BINARY://Двоичные данные
539 tokc->bvalue = buf_len( lexem_getstr( &tokc->vallexem )) ? 1 : 0;
540 break;
541
542 case LEXEM_NAME://Идентификатор
543 tokc->bvalue = -1;
544 break;
545
546 case LEXEM_KEYWORD:
547 msg( MNokeyword | MSG_LEXERR, curlex );
548
549 default:
550 msg( MUnsmoper | MSG_LEXNAMEERR, curlex );
551 }
552 tokc++;
553 }
554 // Проверка синтаксиса выражения
555 if ( flgexp )
556 {
557 switch ( laststate )
558 {
559 case L_OPERAND:
560 case L_POST_CLOSE:
561 if ( state & L_OPERAND ||
562 state & L_UNARY_OPEN )
563 {
564 msg( MUnexpoper | MSG_LEXERR, curlex );
565 }
566 break;
567 default:
568 if ( state & L_BINARY ||
569 state & L_POST_CLOSE )
570 {
571 msg( MMustoper | MSG_LEXERR, curlex );
572 }
573 }
574 laststate = state;
575 }
576 else
577 {
578 if ( ( laststate == L_UNARY_OPEN && tokc != tokb ) ||
579 laststate == L_BINARY )
580 msg( MMustoper | MSG_LEXERR, curlex );
581 break;
582 }
583
584 next:
585 curlex = lexem_next( curlex, 0 );
586 if ( curlex > maxlex )
587 msg( MExpmuch | MSG_LEXERR, curlex );
588 }
589
590 //Возврат значения
591 if ( tokb->vallexem.type == LEXEM_COLLECT )
592 {
593 bcol = buf_init( ( pbuf )arr_append( &_compile->binary ));
594 tokb->vallexem.binid = arr_count( &_compile->binary ) - 1;
595 buf_appenduint( bcol, tokb->colpars );
596
597 for ( tokleft = tokb + 1; tokleft < tokc; tokleft++ )
598 {
599
600 switch ( tokleft->vallexem.type )
601 {
602 case LEXEM_NUMBER:
603 buf_appendch( bcol, (ubyte)tokleft->vallexem.num.type );
604 switch ( tokleft->vallexem.num.type )
605 {
606 case TByte:
607 case TUbyte:
608 buf_appendch( bcol, (ubyte)tokleft->vallexem.num.vint );
609 break;
610 case TShort:
611 case TUshort:
612 buf_appendushort( bcol, (ushort)tokleft->vallexem.num.vint );
613 break;
614 case TUlong:
615 case TLong:
616 case TDouble:
617 buf_appendulong( bcol, tokleft->vallexem.num.vlong );
618 break;
619 default:
620 buf_appenduint( bcol, tokleft->vallexem.num.vint );
621 }
622 break;
623
624 case LEXEM_STRING:
625 buf_appendch( bcol, TStr );
626 strt = lexem_getstr( &tokleft->vallexem );
627 buf_append( bcol, strt->data, strt->use );
628 break;
629
630 case LEXEM_BINARY:
631 buf_appendch( bcol, TBuf );
632 buft = lexem_getstr( &tokleft->vallexem );
633 buf_appenduint( bcol, buft->use );
634 buf_append( bcol, buft->data, buft->use );
635 break;
636
637 case LEXEM_COLLECT:
638 buf_appendch( bcol, TCollection );
639 buf_appenduint( bcol, tokleft->colpars );
640 break;
641
642 default:
643 msg( MSyntax | MSG_LEXNAMEERR, &tokleft->vallexem );
644 }
645 }
646 }
647 else
648 if ( tokc != tokb+1 )
649 {
650 msg( MSyntax | MSG_LEXNAMEERR, curlex );
651 }
652
653 *mr = tokb;
654
655 D("Macroexp stop\n" );
656 return curlex;
657 }
658
659
660
661