1 : /*
2 : * This file is part of MIN Test Framework. Copyright © 2008 Nokia Corporation
3 : * and/or its subsidiary(-ies).
4 : * Contact: Konrad Marek Zapalowicz
5 : * Contact e-mail: DG.MIN-Support@nokia.com
6 : *
7 : * This program is free software: you can redistribute it and/or modify it
8 : * under the terms of the GNU General Public License as published by the Free
9 : * Software Foundation, version 2 of the License.
10 : *
11 : * This program is distributed in the hope that it will be useful, but WITHOUT
12 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 : * more details. You should have received a copy of the GNU General Public
15 : * License along with this program. If not, see
16 : * <http://www.gnu.org/licenses/>.
17 : */
18 :
19 :
20 : /**
21 : * @file min_lego_interface.c
22 : * @version 0.1
23 : * @brief This file contains implementation of MIN Lego Interface.
24 : */
25 :
26 : /* ------------------------------------------------------------------------- */
27 : /* INCLUDE FILES */
28 : #include <min_logger.h>
29 : #include <min_lego_interface.h>
30 :
31 : /* ------------------------------------------------------------------------- */
32 : /* EXTERNAL DATA STRUCTURES */
33 : /* None */
34 :
35 : /* ------------------------------------------------------------------------- */
36 : /* EXTERNAL GLOBAL VARIABLES */
37 : extern DLList *defines;
38 : /* ------------------------------------------------------------------------- */
39 : /* EXTERNAL FUNCTION PROTOTYPES */
40 : /* None */
41 :
42 : /* ------------------------------------------------------------------------- */
43 : /* GLOBAL VARIABLES */
44 : /* None */
45 :
46 : /* ------------------------------------------------------------------------- */
47 : /* CONSTANTS */
48 : /* None */
49 :
50 : /* ------------------------------------------------------------------------- */
51 : /* MACROS */
52 : /* None */
53 :
54 : /* ------------------------------------------------------------------------- */
55 : /* LOCAL GLOBAL VARIABLES */
56 : /* ------------------------------------------------------------------------- */
57 : /** Stack for loop begin pieces, so that we can hande nested loops. */
58 : LOCAL DLList *loopstack = INITPTR;
59 : /** Stack for if block start pieces, so that we can hande nested ifs. */
60 : LOCAL DLList *ifstack = INITPTR;
61 : /** the prepcompilled script that is represented by linked pieces. */
62 : LOCAL LegoBasicType *legosnake = INITPTR;
63 : /* ------------------------------------------------------------------------- */
64 : /* LOCAL CONSTANTS AND MACROS */
65 : /* None */
66 :
67 : /* ------------------------------------------------------------------------- */
68 : /* MODULE DATA STRUCTURES */
69 : /* None */
70 :
71 : /* ------------------------------------------------------------------------- */
72 : /* LOCAL FUNCTION PROTOTYPES */
73 : /* ------------------------------------------------------------------------- */
74 : /** Creates Start piece.
75 : * @return pointer to the allocated Start piece.
76 : */
77 : LOCAL LegoStartType *mli_create_start ();
78 : /* ------------------------------------------------------------------------- */
79 : /** Creates End piece.
80 : * @return pointer to the allocated End piece.
81 : */
82 : LOCAL LegoEndType *mli_create_end ();
83 : /* ------------------------------------------------------------------------- */
84 : /** Creates Passive piece.
85 : * @param keyword [in] the keyword that comes from the script.
86 : * @param mip [in] the script line which includes the keyword.
87 : * @return pointer to the allocated Passive piece.
88 : */
89 : LOCAL LegoPassiveType *mli_create_passive (TScripterKeyword keyword,
90 : MinItemParser * mip);
91 : /* ------------------------------------------------------------------------- */
92 : /** Creates Active piece.
93 : * @param keyword [in] the keyword that comes from the script.
94 : * @param mip [in] the script line which includes the keyword.
95 : * @return pointer to the allocated Active piece.
96 : */
97 : LOCAL LegoActiveType *mli_create_active (TScripterKeyword keyword,
98 : MinItemParser * mip);
99 : /* ------------------------------------------------------------------------- */
100 : /** Creates Start Loop piece.
101 : * @param keyword [in] the keyword that comes from the script.
102 : * @param loops [in] number of times the loop will be executed.
103 : * @param timeout [in] indicates normal loop or timeout loop.
104 : * @return pointer to the allocated Start Loop piece.
105 : *
106 : * NOTE: The loops parameter meaning depends on timeout parameter. If it is
107 : * timeouted loop then loops indicates the time in [ms] otherwise
108 : * loops indicates the number of loop iterations.
109 : *
110 : * NOTE: The created piece is also pushed to the stack. It also handles
111 : * creation of the stack.
112 : */
113 : LOCAL LegoLoopType *mli_create_loop (TScripterKeyword keyword,
114 : unsigned int loops, TSBool timeout);
115 : /* ------------------------------------------------------------------------- */
116 : /** Creates End Loop piece.
117 : * @param keyword [in] the keyword that comes from the script.
118 : * @return pointer to the allocated End Loop piece.
119 : *
120 : * NOTE: The matching Start Loop piece is taken from the stack. It also
121 : * handled destroying of the stack if empty.
122 : */
123 : LOCAL LegoEndloopType *mli_create_endloop (TScripterKeyword keyword);
124 :
125 : /* ------------------------------------------------------------------------- */
126 : /** Creates Break Loop piece.
127 : * @param keyword [in] the keyword that comes from the script.
128 : * @return pointer to the allocated Break Loop piece.
129 : */
130 : LOCAL LegoBreakloopType *mli_create_breakloop (TScripterKeyword keyword);
131 :
132 : /* ------------------------------------------------------------------------- */
133 : /* FORWARD DECLARATIONS */
134 : /* None */
135 :
136 : /* ------------------------------------------------------------------------- */
137 : /* ==================== LOCAL FUNCTIONS ==================================== */
138 : /* ------------------------------------------------------------------------- */
139 : LOCAL LegoStartType *mli_create_start ()
140 48 : {
141 48 : LegoStartType *retval = INITPTR;
142 48 : retval = NEW (LegoStartType);
143 48 : retval->type_ = ELegoStart;
144 48 : retval->next_ = INITPTR;
145 48 : return retval;
146 : }
147 :
148 : /* ------------------------------------------------------------------------- */
149 : LOCAL LegoEndType *mli_create_end ()
150 46 : {
151 46 : LegoEndType *retval = INITPTR;
152 46 : retval = NEW (LegoEndType);
153 46 : retval->type_ = ELegoEnd;
154 46 : retval->next_ = INITPTR;
155 46 : return retval;
156 : }
157 :
158 : /* ------------------------------------------------------------------------- */
159 : LOCAL LegoPassiveType *mli_create_passive (TScripterKeyword keyword,
160 : MinItemParser * mip)
161 48 : {
162 48 : LegoPassiveType *retval = INITPTR;
163 48 : if (mip == INITPTR) {
164 0 : errno = EINVAL;
165 0 : goto EXIT;
166 : }
167 48 : retval = NEW (LegoPassiveType);
168 48 : retval->type_ = ELegoPassive;
169 48 : retval->next_ = INITPTR;
170 48 : retval->keyword_ = keyword;
171 48 : retval->line_ = mip;
172 48 : EXIT:
173 48 : return retval;
174 : }
175 :
176 : /* ------------------------------------------------------------------------- */
177 : LOCAL LegoActiveType *mli_create_active (TScripterKeyword keyword,
178 : MinItemParser * mip)
179 174 : {
180 174 : LegoActiveType *retval = INITPTR;
181 174 : if (mip == INITPTR) {
182 0 : errno = EINVAL;
183 0 : goto EXIT;
184 : }
185 174 : retval = NEW (LegoActiveType);
186 174 : retval->type_ = ELegoActive;
187 174 : retval->next_ = INITPTR;
188 174 : retval->keyword_ = keyword;
189 174 : retval->line_ = mip;
190 174 : EXIT:
191 174 : return retval;
192 : }
193 :
194 : /* ------------------------------------------------------------------------- */
195 : LOCAL LegoLoopType *mli_create_loop (TScripterKeyword keyword,
196 : unsigned int loops, TSBool timeout)
197 39 : {
198 39 : LegoLoopType *retval = INITPTR;
199 39 : retval = NEW (LegoLoopType);
200 39 : retval->type_ = ELegoLoop;
201 39 : retval->next_ = INITPTR;
202 39 : retval->keyword_ = keyword;
203 39 : retval->oryginal_ = loops;
204 39 : retval->timeout_ = timeout;
205 39 : retval->started_ = ESFalse;
206 :
207 39 : retval->oryginal2_.tv_sec = loops/1000;
208 39 : retval->oryginal2_.tv_usec = (loops%1000) *1000;
209 :
210 39 : retval->endtime_.tv_sec = 0;
211 39 : retval->endtime_.tv_usec = 0;
212 :
213 : /* This one is also pushed to the stack */
214 39 : if (loopstack == INITPTR) {
215 31 : loopstack = dl_list_create ();
216 : } else {
217 8 : MIN_DEBUG ("Loopstack already exists");
218 : }
219 39 : dl_list_add (loopstack, (void *)retval);
220 39 : return retval;
221 : }
222 :
223 : /* ------------------------------------------------------------------------- */
224 : LOCAL LegoEndloopType *mli_create_endloop (TScripterKeyword keyword)
225 20 : {
226 20 : DLListIterator it = DLListNULLIterator;
227 20 : LegoEndloopType *retval = INITPTR;
228 20 : retval = NEW (LegoEndloopType);
229 20 : retval->type_ = ELegoEndloop;
230 20 : retval->next_ = INITPTR;
231 20 : retval->keyword_ = keyword;
232 20 : retval->loopback_ = INITPTR;
233 20 : retval->beyondloop_ = INITPTR;
234 20 : retval->oryginal_ = INITPTR;
235 20 : retval->counter_ = 0;
236 20 : retval->timeout_ = ESFalse;
237 20 : retval->oryginal2_ = INITPTR;
238 20 : retval->endtime_ = INITPTR;
239 20 : retval->started_ = INITPTR;
240 :
241 : /* Loopback should point to the LegoLoopType taken from stack. If
242 : * stack becames empty it will be destroyed. */
243 20 : it = dl_list_tail (loopstack);
244 20 : retval->loopback_ = (LegoLoopType *) dl_list_data (it);
245 20 : dl_list_remove_it (it);
246 20 : if (dl_list_tail (loopstack) == DLListNULLIterator) {
247 15 : dl_list_free (&loopstack);
248 : } else {
249 5 : MIN_DEBUG ("Loopstack not empty");
250 : }
251 :
252 : /* Some variables depend on values from LegoLoopType piece. */
253 20 : retval->oryginal_ = &retval->loopback_->oryginal_;
254 20 : retval->timeout_ = retval->loopback_->timeout_;
255 20 : retval->oryginal2_ = &retval->loopback_->oryginal2_;
256 20 : retval->endtime_ = &retval->loopback_->endtime_;
257 20 : retval->started_ = &retval->loopback_->started_;
258 :
259 : /* By default next step will take us to the beginning of the loop */
260 20 : retval->next_ = (LegoBasicType *) retval->loopback_;
261 :
262 20 : return retval;
263 : }
264 : /* ------------------------------------------------------------------------- */
265 : LOCAL LegoBreakloopType *mli_create_breakloop (TScripterKeyword keyword)
266 2 : {
267 2 : LegoBreakloopType *retval = INITPTR;
268 2 : retval = NEW (LegoBreakloopType);
269 2 : retval->type_ = ELegoBreakloop;
270 2 : retval->next_ = INITPTR;
271 2 : retval->keyword_ = keyword;
272 :
273 2 : return retval;
274 : }
275 : /* ------------------------------------------------------------------------- */
276 : LOCAL LegoIfBlockType *mli_create_ifblock (TScripterKeyword keyword,
277 : char *if_condition)
278 5 : {
279 5 : LegoIfBlockType *retval = INITPTR;
280 :
281 5 : retval = NEW (LegoIfBlockType);
282 5 : retval->type_ = ELegoIfBlock;
283 5 : retval->next_ = INITPTR;
284 5 : retval->keyword_ = keyword;
285 :
286 5 : retval->condition_ = NEW2(char, strlen (if_condition) + 1);
287 5 : STRCPY(retval->condition_, if_condition, strlen (if_condition) + 1);
288 5 : retval->else_ = INITPTR;
289 5 : retval->block_end_ = INITPTR;
290 :
291 : /* push to the ifblocks stack */
292 5 : if (ifstack == INITPTR) {
293 4 : ifstack = dl_list_create ();
294 : }
295 :
296 :
297 5 : dl_list_add (ifstack, (void *)retval);
298 :
299 5 : return retval;
300 : }
301 :
302 : /* ------------------------------------------------------------------------- */
303 :
304 : LOCAL LegoElseBlockType *mli_create_else (TScripterKeyword keyword,
305 : LegoBasicType *prev)
306 1 : {
307 1 : DLListIterator it = DLListNULLIterator;
308 1 : LegoIfBlockType *ifblock = INITPTR;
309 1 : LegoElseBlockType *retval = INITPTR;
310 :
311 1 : retval = NEW (LegoElseBlockType);
312 1 : retval->type_ = ELegoElseBlock;
313 1 : retval->next_ = INITPTR;
314 1 : retval->keyword_ = keyword;
315 :
316 1 : it = dl_list_tail (ifstack);
317 1 : if (it == DLListNULLIterator) {
318 0 : MIN_ERROR ("No matching if found for else");
319 0 : return retval;
320 : }
321 1 : ifblock = (LegoIfBlockType *)dl_list_data (it);
322 1 : ifblock->else_ = (LegoBasicType *)retval;
323 :
324 1 : retval->prev_ = prev;
325 :
326 1 : return retval;
327 : }
328 :
329 : /* ------------------------------------------------------------------------- */
330 :
331 : LOCAL LegoEndifBlockType *mli_create_endifblock (TScripterKeyword keyword)
332 5 : {
333 : LegoBasicType *previous;
334 5 : DLListIterator it = DLListNULLIterator;
335 5 : LegoIfBlockType *ifblock = INITPTR;
336 5 : LegoElseBlockType *elseblock = INITPTR;
337 5 : LegoEndifBlockType *retval = INITPTR;
338 :
339 5 : retval = NEW (LegoEndifBlockType);
340 5 : retval->type_ = ELegoEndifBlock;
341 5 : retval->next_ = INITPTR;
342 5 : retval->else_ = INITPTR;
343 5 : retval->keyword_ = keyword;
344 :
345 5 : it = dl_list_tail (ifstack);
346 5 : if (it == DLListNULLIterator) {
347 0 : MIN_ERROR ("No matching if found for endif");
348 0 : return retval;
349 : }
350 5 : ifblock = (LegoIfBlockType *)dl_list_data (it);
351 : /*
352 : ** Now we can set the end pointer for if-block
353 : */
354 5 : ifblock->block_end_ = (LegoBasicType *)retval;
355 5 : elseblock = (LegoElseBlockType *)ifblock->else_;
356 5 : if (elseblock != INITPTR) {
357 : /*
358 : ** Relink the block before else
359 : */
360 1 : previous = elseblock->prev_;
361 1 : previous->next_ = (LegoBasicType *)retval;
362 : /*
363 : ** Backpointer needed in clean up
364 : */
365 1 : retval->else_ = ifblock->else_;
366 : }
367 5 : dl_list_remove_it (it);
368 5 : if (dl_list_tail (ifstack) == DLListNULLIterator) {
369 4 : dl_list_free (&ifstack);
370 : }
371 :
372 5 : return retval;
373 : }
374 :
375 : /* ------------------------------------------------------------------------- */
376 : /* ======================== FUNCTIONS ====================================== */
377 : /* ------------------------------------------------------------------------- */
378 : void mli_create (MinSectionParser * msp)
379 45 : {
380 45 : MinItemParser *mip = INITPTR;
381 45 : char *token = INITPTR;
382 45 : TScripterKeyword keyword = EKeywordUnknown;
383 45 : LegoBasicType *last = INITPTR;
384 45 : LegoBasicType *tmp = INITPTR;
385 45 : int loop_iter = 0;
386 45 : char *loop_param = INITPTR;
387 45 : char *if_condition = INITPTR;
388 45 : TSBool loop_tmout = ESFalse;
389 45 : DLListIterator it = DLListNULLIterator;
390 45 : struct define *def = INITPTR;
391 45 : int ret = 0;
392 :
393 :
394 45 : if (msp == INITPTR) {
395 1 : errno = EINVAL;
396 1 : goto EXIT;
397 : }
398 :
399 : /* 1) Create START piece */
400 44 : last = mli_create_start ();
401 44 : legosnake = last;
402 :
403 : /* 2) Construct the rest of snake */
404 44 : mip = mmp_get_item_line (msp, "", ESNoTag);
405 327 : while (mip != INITPTR) {
406 :
407 : /* first we have to replace possible define labels with
408 : * its value. */
409 239 : it = dl_list_head (defines);
410 478 : while (it != DLListNULLIterator) {
411 0 : def = (struct define *)dl_list_data (it);
412 0 : ret = mip_replace (mip, def->label_, def->value_);
413 :
414 0 : if (ret == -1) {
415 0 : MIN_WARN ("Error when replacing,"
416 : " invalid parameter to mip_replace");
417 : }
418 :
419 0 : it = dl_list_next (it);
420 : }
421 :
422 : /* then we can interprete line */
423 239 : if (token != INITPTR)
424 195 : DELETE (token);
425 239 : mip_get_string (mip, "", &token);
426 239 : keyword = get_keyword (token);
427 :
428 239 : switch (keyword) {
429 : case EKeywordTitle:
430 : case EKeywordSkipIt:
431 44 : tmp =
432 : (LegoBasicType *) mli_create_passive (keyword,
433 : mip);
434 44 : last->next_ = tmp;
435 44 : last = tmp;
436 44 : mip = mmp_get_next_item_line (msp);
437 44 : break;
438 : case EKeywordClassName:
439 : case EKeywordCreate:
440 : case EKeywordDelete:
441 : case EKeywordPause:
442 : case EKeywordPrint:
443 : case EKeywordResume:
444 : case EKeywordCancel:
445 : case EKeywordRelease:
446 : case EKeywordRequest:
447 : case EKeywordRun:
448 : case EKeywordSet:
449 : case EKeywordUnset:
450 : case EKeywordWait:
451 : case EKeywordAllocate:
452 : case EKeywordFree:
453 : case EKeywordInterference:
454 : case EKeywordRemote:
455 : case EKeywordAllowNextResult:
456 : case EKeywordComplete:
457 : case EKeywordCancelIfError:
458 : case EKeywordTimeout:
459 : case EKeywordSleep:
460 : case EKeywordVar:
461 : case EKeywordExpect:
462 : case EKeywordSendreceive:
463 170 : tmp =
464 : (LegoBasicType *) mli_create_active (keyword,
465 : mip);
466 170 : last->next_ = tmp;
467 170 : last = tmp;
468 170 : mip = mmp_get_next_item_line (msp);
469 170 : break;
470 : case EKeywordLoop:
471 : /* Take number of iterations */
472 6 : mip_get_int (mip, "", &loop_iter);
473 : /* Take parameters (msec or passrate) */
474 6 : mip_get_next_string (mip, &loop_param);
475 :
476 6 : if (loop_param != INITPTR) {
477 0 : loop_tmout = ESTrue;
478 : } else {
479 6 : MIN_DEBUG ("No. of iterations: %d",
480 : loop_iter);
481 : }
482 :
483 6 : tmp =
484 : (LegoBasicType *) mli_create_loop (keyword,
485 : loop_iter,
486 : loop_tmout);
487 6 : last->next_ = tmp;
488 6 : last = tmp;
489 6 : mip_destroy (&mip);
490 6 : mip = mmp_get_next_item_line (msp);
491 6 : break;
492 : case EKeywordEndloop:
493 6 : tmp = (LegoBasicType *) mli_create_endloop (keyword);
494 6 : last->next_ = tmp;
495 6 : last = tmp;
496 6 : mip_destroy (&mip);
497 6 : mip = mmp_get_next_item_line (msp);
498 6 : break;
499 : case EKeywordBreakloop:
500 2 : tmp = (LegoBasicType *) mli_create_breakloop (keyword);
501 2 : last->next_ = tmp;
502 2 : last = tmp;
503 2 : mip_destroy (&mip);
504 2 : mip = mmp_get_next_item_line (msp);
505 2 : break;
506 : case EKeywordIf:
507 5 : mip_get_next_string (mip, &if_condition);
508 5 : tmp = (LegoBasicType *)
509 : mli_create_ifblock (keyword,
510 : if_condition);
511 5 : DELETE (if_condition);
512 5 : last->next_ = tmp;
513 5 : last = tmp;
514 5 : mip_destroy (&mip);
515 5 : mip = mmp_get_next_item_line (msp);
516 5 : break;
517 : case EKeywordElse:
518 1 : tmp = (LegoBasicType *)
519 : mli_create_else (keyword, last);
520 1 : last->next_ = tmp;
521 1 : last = tmp;
522 1 : mip_destroy (&mip);
523 1 : mip = mmp_get_next_item_line (msp);
524 1 : break;
525 :
526 : case EKeywordEndif:
527 5 : tmp = (LegoBasicType *)
528 : mli_create_endifblock (keyword);
529 5 : last->next_ = tmp;
530 5 : last = tmp;
531 5 : mip_destroy (&mip);
532 5 : mip = mmp_get_next_item_line (msp);
533 5 : break;
534 :
535 : case EKeywordUnknown:
536 0 : MIN_ERROR ("Unknown keyword [%s]", token);
537 0 : mip_destroy (&mip);
538 0 : mip = mmp_get_next_item_line (msp);
539 0 : break;
540 : default:
541 0 : MIN_ERROR ("Unknown keyword [INITPTR]");
542 0 : mip_destroy (&mip);
543 0 : mip = mmp_get_next_item_line (msp);
544 : break;
545 : }
546 : }
547 44 : if (token != INITPTR)
548 44 : DELETE (token);
549 : /* 3) Add End element */
550 44 : tmp = mli_create_end ();
551 44 : last->next_ = tmp;
552 44 : last = tmp;
553 45 : EXIT:
554 : return;
555 : }
556 :
557 : /* ------------------------------------------------------------------------- */
558 : void mli_destroy ()
559 24 : {
560 24 : LegoBasicType *tmp = INITPTR;
561 24 : LegoBasicType *next = INITPTR;
562 24 : LegoActiveType *lat = INITPTR;
563 24 : LegoLoopType *llt = INITPTR;
564 24 : LegoEndloopType *let = INITPTR;
565 24 : LegoBreakloopType *lbbt = INITPTR;
566 24 : LegoIfBlockType *libt = INITPTR;
567 24 : LegoEndifBlockType *ldbt = INITPTR;
568 24 : LegoElseBlockType *lebt = INITPTR;
569 24 : if (legosnake == INITPTR) {
570 0 : MIN_WARN ("Lego snake does not exist");
571 0 : goto EXIT;
572 : }
573 :
574 24 : tmp = legosnake;
575 :
576 231 : while (tmp != INITPTR) {
577 183 : next = tmp->next_;
578 183 : switch (tmp->type_) {
579 : case ELegoPassive:
580 : case ELegoActive:
581 114 : lat = (LegoActiveType *) tmp;
582 114 : mip_destroy (&lat->line_);
583 114 : DELETE (lat);
584 114 : lat = INITPTR;
585 114 : tmp = INITPTR;
586 114 : break;
587 : case ELegoStart:
588 : case ELegoEnd:
589 48 : DELETE (tmp);
590 48 : tmp = INITPTR;
591 48 : break;
592 : case ELegoLoop:
593 5 : llt = (LegoLoopType *) tmp;
594 5 : DELETE (llt);
595 5 : llt = INITPTR;
596 5 : tmp = INITPTR;
597 5 : break;
598 : case ELegoEndloop:
599 5 : let = (LegoEndloopType *) tmp;
600 5 : DELETE (let);
601 5 : let = INITPTR;
602 5 : tmp = INITPTR;
603 5 : break;
604 : case ELegoBreakloop:
605 1 : lbbt = (LegoBreakloopType *) tmp;
606 1 : DELETE (lbbt);
607 1 : lbbt = INITPTR;
608 1 : tmp = INITPTR;
609 1 : break;
610 : case ELegoIfBlock:
611 4 : libt = (LegoIfBlockType *) tmp;
612 4 : DELETE (libt->condition_);
613 4 : DELETE (libt);
614 4 : break;
615 : case ELegoEndifBlock:
616 5 : ldbt = (LegoEndifBlockType *) tmp;
617 5 : if (ldbt->else_ != INITPTR) {
618 1 : tmp = ldbt->else_;
619 1 : ldbt->else_ = INITPTR;
620 1 : continue;
621 : } else
622 4 : DELETE (ldbt);
623 4 : break;
624 : case ELegoElseBlock:
625 1 : lebt = (LegoElseBlockType *) tmp;
626 1 : DELETE (lebt);
627 1 : break;
628 : default:
629 0 : MIN_WARN ("Unknown Lego piece [%d]", tmp->type_);
630 : }
631 182 : tmp = next;
632 : }
633 24 : EXIT:
634 : return;
635 : }
636 :
637 : /* ------------------------------------------------------------------------- */
638 : LegoBasicType *mli_get_legosnake ()
639 39 : {
640 39 : return legosnake;
641 : }
642 :
643 : /* ------------------------------------------------------------------------- */
644 : /* ================= OTHER EXPORTED FUNCTIONS ============================== */
645 : /* None */
646 :
647 : /* ------------------------------------------------------------------------- */
648 : /* ================= TESTS FOR LOCAL FUNCTIONS ============================= */
649 : #ifdef MIN_UNIT_TEST
650 : #include "min_lego_interface.tests"
651 : #endif /* MIN_UNIT_TEST */
652 : /* End of file */
|