root/trunk/lib/ubasic/ubasic.c

Revision 959, 65.7 KB (checked in by rudi_de, 3 months ago)

Wieder angleichen von CHDK und CHDK-DE (Teil 6)

Betrifft alle
* ubasic TOKENIZER_IS_PRESSED: von is_clicked() mit is_pressed() getauscht
* kosmetische Korrekturen
* Definition von CAM_DRIVE_MODE_FROM_TIMER_MODE auf 1 gesetzt

  • Property svn:eol-style set to native
Line 
1/*
2 * Copyright (c) 2006, Adam Dunkels
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30
31#if DEBUG
32#define DEBUG_PRINTF(...)  printf(__VA_ARGS__)
33#else
34#define DEBUG_PRINTF(...)
35#endif
36
37#ifdef UBASIC_TEST
38#include "../../include/ubasic.h"
39#include "../../include/platform.h"
40#include "../../include/script.h"
41#include "../../include/shot_histogram.h"
42#include "../../include/levent.h"
43#include "../../include/console.h"
44#include <string.h>
45#include <time.h>
46#include <fcntl.h>
47#include <io.h>
48#include <stdlib.h> /* rand,srand */
49#include "camera_functions.h"
50#else
51#include "ubasic.h"
52#include "platform.h"
53#include "script.h"
54#include "camera.h"
55#include "shot_histogram.h"
56#include "stdlib.h"
57#include "levent.h"
58#include "console.h"
59#include "../../core/motion_detector.h"
60#endif
61#include "../../core/action_stack.h"
62#include "tokenizer.h"
63
64#include "../../include/conf.h"
65
66#define INCLUDE_OLD_GET__SYNTAX
67
68#ifdef DEBUG
69#include <stdio.h>
70#endif
71
72static char const *program_ptr;
73#define MAX_STRINGLEN 40
74static char string[MAX_STRINGLEN];
75
76#define MAX_GOSUB_STACK_DEPTH 10
77static short gosub_stack[MAX_GOSUB_STACK_DEPTH];
78static int gosub_stack_ptr;
79
80#define MAX_IF_STACK_DEPTH 4
81static short if_stack[MAX_IF_STACK_DEPTH];
82static int if_stack_ptr;
83
84struct select_state {
85  int select_value;
86  short case_run;
87};
88#define MAX_SELECT_STACK_DEPTH 4
89static struct select_state select_stack[MAX_SELECT_STACK_DEPTH];
90static int select_stack_ptr;
91
92#define MAX_WHILE_STACK_DEPTH 4
93static short while_stack[MAX_WHILE_STACK_DEPTH];
94static int while_stack_ptr;
95
96#define MAX_DO_STACK_DEPTH 4
97static short do_stack[MAX_DO_STACK_DEPTH];
98static int do_stack_ptr;
99
100struct for_state {
101  short line_after_for;
102  short for_variable;
103  int to;
104  int step;
105};
106#define MAX_FOR_STACK_DEPTH 4
107static struct for_state for_stack[MAX_FOR_STACK_DEPTH];
108static int for_stack_ptr;
109
110#define MAX_VARNUM 52
111static int variables[MAX_VARNUM];
112
113static int ended;
114
115static int ubasic_md_ret_var_num;
116
117static int expr(void);
118static void line_statement(void);
119static void statement(void);
120static int relation(void);
121
122/*
123ubasic scheduling controls
124ubasic returns control to kbd_task as soon as either of the following is is exceeded
125defaults is 1 ubasic line per kbd_task cycle, mimicing old behavior
126*/
127#define YIELD_MAX_LINES_DEFAULT 1
128#define YIELD_MAX_MS_DEFAULT 10
129// maximum number lines before yielding (labels, blank lines and REMs excluded)
130static unsigned yield_max_lines;
131// maximum number of ticks before yielding
132static unsigned yield_max_ms;
133// set flag to immediately transfer execution flow to main CHDK to process external action
134// TODO a better approach to this might be to check if AS_RUN is on top of the action_stack
135static int flag_yield;
136
137int ubasic_error;
138const char *ubasic_errstrings[UBASIC_E_ENDMARK] =
139{
140    "No err",
141    "Parse err",
142    "Unk stmt",
143    "Unk key",
144    "Unk label",
145    "gosub: Stack ful",
146    "bad return",
147    "if: Stack ful",
148    "bad endif",
149    "select: Stack ful",
150    "bad end_select",
151    "for: Stack ful",
152    "bad next",
153    "do: Stack ful",
154    "bad until",
155    "while: Stack ful",
156    "bad wend",
157    "Unk err"
158};
159
160/*---------------------------------------------------------------------------*/
161int
162ubasic_linenumber()
163{
164  return tokenizer_line_number();
165}
166
167/*---------------------------------------------------------------------------*/
168void
169ubasic_init(const char *program)
170{
171  program_ptr = program;
172  flag_yield = 0;
173  for_stack_ptr = gosub_stack_ptr = while_stack_ptr = do_stack_ptr = if_stack_ptr = select_stack_ptr = 0;
174  tokenizer_init(program);
175  ended = 0;
176  ubasic_error = UBASIC_E_NONE;
177  yield_max_lines = YIELD_MAX_LINES_DEFAULT;
178  yield_max_ms = YIELD_MAX_MS_DEFAULT;
179}
180/*---------------------------------------------------------------------------*/
181// read a key name and return key id,
182// set error and return 0 if key invalid
183static int ubasic_get_key_arg() {
184  int k;
185  tokenizer_string(string, sizeof(string));
186  tokenizer_next();
187  k = script_keyid_by_name(string);
188  if (k <= 0)
189    ubasic_error = UBASIC_E_UNK_KEY;
190  return k;
191}
192/*---------------------------------------------------------------------------*/
193static void
194accept(int token)
195{
196  if(token != tokenizer_token()) {
197    DEBUG_PRINTF("Token not what was expected (expected %d, got %d)\n",
198                 token, tokenizer_token());
199    tokenizer_error_print();
200     tokenizer_next();
201     ended = 1;
202     ubasic_error = UBASIC_E_PARSE;
203     return;
204  }
205  DEBUG_PRINTF("Expected %d, got it\n", token);
206  tokenizer_next();
207}
208/*---------------------------------------------------------------------------*/
209static void
210accept_cr()
211{
212    while(tokenizer_token() != TOKENIZER_CR &&
213            tokenizer_token() != TOKENIZER_ENDOFINPUT)
214      tokenizer_next();
215    accept(TOKENIZER_CR);
216}
217/*---------------------------------------------------------------------------*/
218static int
219varfactor(void)
220{
221  int r;
222  DEBUG_PRINTF("varfactor: obtaining %d from variable %d\n", variables[tokenizer_variable_num()], tokenizer_variable_num());
223  r = ubasic_get_variable(tokenizer_variable_num());
224  accept(TOKENIZER_VARIABLE);
225  return r;
226}
227/*---------------------------------------------------------------------------*/
228static int
229factor(void)
230{
231  int r = 0;
232  tConfigVal configVal;
233
234  DEBUG_PRINTF("factor: token %d\n", tokenizer_token());
235  switch(tokenizer_token()) {
236  case TOKENIZER_NUMBER:
237    r = tokenizer_num();
238    DEBUG_PRINTF("factor: number %d\n", r);
239    accept(TOKENIZER_NUMBER);
240    break;
241  case TOKENIZER_LEFTPAREN:
242    accept(TOKENIZER_LEFTPAREN);
243    r = relation();
244    accept(TOKENIZER_RIGHTPAREN);
245    break;
246  case TOKENIZER_PLUS:
247    accept(TOKENIZER_PLUS);
248    r = factor();
249    break;
250  case TOKENIZER_MINUS:
251    accept(TOKENIZER_MINUS);
252    r = - factor();
253    break;
254  case TOKENIZER_LNOT:
255    accept(TOKENIZER_LNOT);
256    r = ! relation();
257    break;
258  case TOKENIZER_GET_VBATT:
259    accept(TOKENIZER_GET_VBATT);
260    r = (unsigned short) stat_get_vbatt();
261    break;
262  case TOKENIZER_GET_DAY_SECONDS:
263    accept(TOKENIZER_GET_DAY_SECONDS);
264    r = shooting_get_day_seconds();
265    break;
266  case TOKENIZER_GET_TICK_COUNT:
267    accept(TOKENIZER_GET_TICK_COUNT);
268    r = shooting_get_tick_count();     
269    break;
270  case TOKENIZER_GET_MODE:
271    accept(TOKENIZER_GET_MODE);
272    int m=mode_get()&MODE_SHOOTING_MASK;
273    int mode_video=MODE_IS_VIDEO(m);
274    if ((mode_get()&MODE_MASK) != MODE_PLAY) r = 0;
275    if ((mode_get()&MODE_MASK) == MODE_PLAY) r = 1;
276    if (((mode_get()&MODE_MASK) != MODE_PLAY) && mode_video) r = 2;
277  break;
278  case TOKENIZER_GET_RAW_NR:
279    accept(TOKENIZER_GET_RAW_NR);
280    r = camera_get_nr();     
281    break;
282  case TOKENIZER_IS_KEY:
283    accept(TOKENIZER_IS_KEY);
284    r = script_key_is_clicked(ubasic_get_key_arg());
285    break;
286  case TOKENIZER_SCRIPT_AUTOSTARTED:
287    accept(TOKENIZER_SCRIPT_AUTOSTARTED);
288    r = camera_get_script_autostart();
289    break;
290  case TOKENIZER_GET_SCRIPT_AUTOSTART:
291    accept(TOKENIZER_GET_SCRIPT_AUTOSTART);
292#ifdef UBASIC_TEST
293    r = 0;
294#else
295    r = conf.script_startup;
296#endif
297    break;
298  case TOKENIZER_GET_USB_POWER:
299    accept(TOKENIZER_GET_USB_POWER);
300    r = get_usb_power(0);     
301    break;
302  case TOKENIZER_GET_EXP_COUNT:
303    accept(TOKENIZER_GET_EXP_COUNT);
304    r = get_exposure_counter();
305    break;
306  case TOKENIZER_IS_PRESSED:
307    accept(TOKENIZER_IS_PRESSED);
308    r = script_key_is_pressed(ubasic_get_key_arg());
309    break;
310  case TOKENIZER_RANDOM:
311    accept(TOKENIZER_RANDOM);
312    int min = expr();
313    int max = expr();
314    // shouldn't srand every time...
315    srand((int)shooting_get_bv96()+(unsigned short)stat_get_vbatt()+get_tick_count());
316    // wtf
317    action_push_delay(rand()%10);
318    flag_yield=1;
319    r = min + rand()%(max-min+1);
320  break;
321  case TOKENIZER_GET_MOVIE_STATUS:
322    accept(TOKENIZER_GET_MOVIE_STATUS);
323    r = movie_status;
324    break;
325  case TOKENIZER_GET_PLATFORM_ID:
326    accept(TOKENIZER_GET_PLATFORM_ID);
327    r = PLATFORMID;
328    break;
329  case TOKENIZER_GET_DRIVE_MODE:
330    accept(TOKENIZER_GET_DRIVE_MODE);
331    r = shooting_get_drive_mode();
332    break;
333   case TOKENIZER_GET_FOCUS_MODE:
334    accept(TOKENIZER_GET_FOCUS_MODE);
335    r = shooting_get_real_focus_mode();
336    break;
337  case TOKENIZER_GET_FOCUS_STATE:
338    accept(TOKENIZER_GET_FOCUS_STATE);
339    r = shooting_get_focus_state();
340    break;
341  case TOKENIZER_GET_FOCUS_OK:
342    accept(TOKENIZER_GET_FOCUS_OK);
343    r = shooting_get_focus_ok();
344    break;
345  case TOKENIZER_GET_DISPLAY_MODE:
346    accept(TOKENIZER_GET_DISPLAY_MODE);
347    r = shooting_get_prop(PROPCASE_DISPLAY_MODE);
348    break;
349  case TOKENIZER_GET_FLASH_MODE:
350    accept(TOKENIZER_GET_FLASH_MODE);
351    r = shooting_get_prop(PROPCASE_FLASH_MODE);
352    break;
353  case TOKENIZER_GET_SHOOTING:
354    accept(TOKENIZER_GET_SHOOTING);
355    r = shooting_get_prop(PROPCASE_SHOOTING);
356    break;
357  case TOKENIZER_GET_FLASH_READY:
358    accept(TOKENIZER_GET_FLASH_READY);
359    r = shooting_get_prop(PROPCASE_IS_FLASH_READY);
360    break;
361  case TOKENIZER_GET_IS_MODE:
362    accept(TOKENIZER_GET_IS_MODE);
363    r = shooting_get_prop(PROPCASE_IS_MODE);
364    break;
365  case TOKENIZER_GET_EV:
366    accept(TOKENIZER_GET_EV);
367    r = shooting_get_prop(PROPCASE_EV_CORRECTION_1);
368    break;
369  case TOKENIZER_GET_RESOLUTION:
370    accept(TOKENIZER_GET_RESOLUTION);
371    r = shooting_get_prop(PROPCASE_RESOLUTION);
372    break;
373  case TOKENIZER_GET_QUALITY:
374    accept(TOKENIZER_GET_QUALITY);
375    r = shooting_get_prop(PROPCASE_QUALITY);
376    break;
377  case TOKENIZER_GET_ORIENTATION_SENSOR:
378    accept(TOKENIZER_GET_ORIENTATION_SENSOR);
379    r = shooting_get_prop(PROPCASE_ORIENTATION_SENSOR);
380    break;
381  case TOKENIZER_GET_ZOOM_STEPS:
382    accept(TOKENIZER_GET_ZOOM_STEPS);
383    r = zoom_points;
384    break;
385  case TOKENIZER_GET_ND_PRESENT:
386    accept(TOKENIZER_GET_ND_PRESENT);
387    #if !CAM_HAS_ND_FILTER
388    r = 0;
389    #endif
390    #if CAM_HAS_ND_FILTER && !CAM_HAS_IRIS_DIAPHRAGM
391    r = 1;
392    #endif
393    #if CAM_HAS_ND_FILTER && CAM_HAS_IRIS_DIAPHRAGM
394    r = 2;
395    #endif
396    break;
397  case TOKENIZER_GET_PROPSET:
398    accept(TOKENIZER_GET_PROPSET);
399    r = CAM_PROPSET;
400    break;
401  case TOKENIZER_GET_TV96:
402    accept(TOKENIZER_GET_TV96);
403    r = shooting_get_tv96();
404    break;
405  case TOKENIZER_GET_USER_TV96:
406    accept(TOKENIZER_GET_USER_TV96);
407    r = shooting_get_user_tv96();
408    break;   
409  case TOKENIZER_GET_USER_TV_ID:
410    accept(TOKENIZER_GET_USER_TV_ID);
411    r = shooting_get_user_tv_id();
412    break;
413  case TOKENIZER_GET_AV96:
414    accept(TOKENIZER_GET_AV96);
415    r = shooting_get_av96();
416    break; 
417  case TOKENIZER_GET_USER_AV96:
418    accept(TOKENIZER_GET_USER_AV96);
419    r = shooting_get_user_av96();
420    break;   
421  case TOKENIZER_GET_USER_AV_ID:
422    accept(TOKENIZER_GET_USER_AV_ID);
423    r = shooting_get_user_av_id();
424    break;
425  case TOKENIZER_GET_ZOOM:
426    accept(TOKENIZER_GET_ZOOM);
427    r = shooting_get_zoom();
428    break;
429  case TOKENIZER_GET_FOCUS:
430    accept(TOKENIZER_GET_FOCUS);
431    r = shooting_get_subject_distance();
432    break;
433  case TOKENIZER_GET_NEAR_LIMIT:
434    accept(TOKENIZER_GET_NEAR_LIMIT);
435    r = shooting_get_near_limit_of_acceptable_sharpness();
436    break;
437  case TOKENIZER_GET_FAR_LIMIT:
438    accept(TOKENIZER_GET_FAR_LIMIT);
439    r = shooting_get_far_limit_of_acceptable_sharpness();
440    break; 
441   case TOKENIZER_GET_DOF:
442    accept(TOKENIZER_GET_DOF);
443    r = shooting_get_depth_of_field();
444    break;
445  case TOKENIZER_GET_HYPERFOCAL_DIST:
446    accept(TOKENIZER_GET_HYPERFOCAL_DIST);
447    r = shooting_get_hyperfocal_distance();
448    break; 
449  case TOKENIZER_GET_ISO_MARKET:
450    accept(TOKENIZER_GET_ISO_MARKET);
451    r = (int)shooting_get_iso_market();
452    break;
453  case TOKENIZER_GET_ISO_REAL:
454    accept(TOKENIZER_GET_ISO_REAL);
455    r = (int)shooting_get_iso_real();
456    break;
457  case TOKENIZER_GET_BV96:
458    accept(TOKENIZER_GET_BV96);
459    r = (int)shooting_get_bv96();
460    break; 
461  case TOKENIZER_GET_SV96:
462    accept(TOKENIZER_GET_SV96);
463    r = (int)shooting_get_sv96();
464    break;   
465  case TOKENIZER_GET_ISO_MODE:
466    accept(TOKENIZER_GET_ISO_MODE);
467    r = shooting_get_iso_mode();
468    break;
469  case TOKENIZER_GET_DISK_SIZE:
470    accept(TOKENIZER_GET_DISK_SIZE);
471    r = GetTotalCardSpaceKb();
472    break;
473  case TOKENIZER_GET_FREE_DISK_SPACE:
474    accept(TOKENIZER_GET_FREE_DISK_SPACE);
475    r = GetFreeCardSpaceKb();
476    break;
477  case TOKENIZER_GET_JPG_COUNT:
478    accept(TOKENIZER_GET_JPG_COUNT);
479    r = GetJpgCount();
480    break;
481  case TOKENIZER_GET_VIDEO_BUTTON:
482    accept(TOKENIZER_GET_VIDEO_BUTTON);
483    #if CAM_HAS_VIDEO_BUTTON
484    r = 1;
485    #else
486    r = 0;
487    #endif
488    break;
489  case TOKENIZER_GET_RAW_COUNT:
490    accept(TOKENIZER_GET_RAW_COUNT);
491    r = GetRawCount();
492    break;
493  case TOKENIZER_GET_PROP:
494    accept(TOKENIZER_GET_PROP);
495    int var = expr();
496    r = shooting_get_prop(var);
497    break;
498  case TOKENIZER_GET_HISTO_RANGE:
499    accept(TOKENIZER_GET_HISTO_RANGE);
500    int from = expr();
501    int to = expr();
502    if (shot_histogram_isenabled()) r = (unsigned short)shot_histogram_get_range(from, to);
503    else r = -1;
504    break;
505  case TOKENIZER_GET_TEMPERATURE:
506    accept(TOKENIZER_GET_TEMPERATURE);
507    int temp = expr();
508    switch (temp)
509    {
510    case 0:
511      r = get_optical_temp();
512      break;
513    case 1:
514      r = get_ccd_temp();
515      break;
516    case 2:
517      r = get_battery_temp();
518      break;
519    default: // do something sane if given a bad index
520      r = 0;
521    }
522    break;
523  case TOKENIZER_GET_TIME:
524    accept(TOKENIZER_GET_TIME);
525    unsigned long t2 = time(NULL);
526    int tmode = expr();
527    static struct tm *ttm;
528    ttm = localtime(&t2);
529    if (tmode==0) r = ttm->tm_sec;
530    else if (tmode==1) r = ttm->tm_min;
531    else if (tmode==2) r = ttm->tm_hour;
532    else if (tmode==3) r = ttm->tm_mday;
533    else if (tmode==4) r = ttm->tm_mon+1;
534    else if (tmode==5) r = 1900+ttm->tm_year;
535    break;
536  case TOKENIZER_GET_RAW:
537    accept(TOKENIZER_GET_RAW);
538#ifdef UBASIC_TEST
539    r = 1;
540#else
541    r = conf.save_raw;
542#endif   
543    break;
544  // get CHDK capture mode value, or 0 if in playback or unknown (broken modemap)
545  // NOTE: different from get_mode, since this returns the actual value
546  case TOKENIZER_GET_CAPTURE_MODE:
547    accept(TOKENIZER_GET_CAPTURE_MODE);
548    r = mode_get();
549    if ( (r&MODE_MASK) == MODE_REC)
550      r &= MODE_SHOOTING_MASK;
551    else
552      r = 0;
553    break;
554  // check if CHDK capture mode exists in modemap of this camera
555  case TOKENIZER_IS_CAPTURE_MODE_VALID:
556    accept(TOKENIZER_IS_CAPTURE_MODE_VALID);
557    int modenum = expr();
558    if (shooting_mode_chdk2canon(modenum) == -1)
559      r = 0;
560    else
561      r = 1;
562    break;
563  case TOKENIZER_GET_FOCAL_LENGTH:
564    accept(TOKENIZER_GET_FOCAL_LENGTH);
565    r = get_focal_length(lens_get_zoom_point());
566    break;
567  case TOKENIZER_GET_MIN_STACK_DIST:
568    accept(TOKENIZER_GET_MIN_STACK_DIST);
569    r = shooting_get_min_stack_distance();
570    break;
571  case TOKENIZER_GET_CONFIG_VALUE:
572    accept(TOKENIZER_GET_CONFIG_VALUE);
573    int var1 = expr();
574    int var2 = expr();
575    if( conf_getValue(var1, &configVal) == CONF_VALUE) r = configVal.numb; else r = var2;
576    break;
577#ifdef CAM_MULTIPART
578  case TOKENIZER_SWAP_PARTITIONS:
579    accept(TOKENIZER_SWAP_PARTITIONS);
580    int partNr = expr();
581    r = swap_partitions(partNr);
582    break;
583#endif
584  default:
585    r = varfactor();
586    break;
587  }
588  return r;
589}
590/*---------------------------------------------------------------------------*/
591static int
592term(void)
593{
594  int f1, f2;
595  int op;
596
597  f1 = factor();
598  op = tokenizer_token();
599  DEBUG_PRINTF("term: token %d\n", op);
600  while(op == TOKENIZER_ASTR ||
601        op == TOKENIZER_SLASH ||
602        op == TOKENIZER_LT ||
603        op == TOKENIZER_GT ||
604        op == TOKENIZER_GE ||
605        op == TOKENIZER_LE ||
606        op == TOKENIZER_NE ||
607        op == TOKENIZER_EQ ||
608        op == TOKENIZER_XOR ||
609        op == TOKENIZER_OR ||
610        op == TOKENIZER_MOD) {
611    tokenizer_next();
612    f2 = factor();
613    DEBUG_PRINTF("term: %d %d %d\n", f1, op, f2);
614    switch(op) {
615    case TOKENIZER_ASTR:
616      f1 = f1 * f2;
617      break;
618    case TOKENIZER_SLASH:
619      f1 = f1 / f2;
620      break;
621    case TOKENIZER_MOD:
622      f1 = f1 % f2;
623      break;
624    case TOKENIZER_LT:
625      f1 = f1 < f2;
626      break;
627    case TOKENIZER_GT:
628      f1 = f1 > f2;
629      break;
630    case TOKENIZER_EQ:
631      f1 = f1 == f2;
632      break;
633    case TOKENIZER_NE:
634      f1 = f1 != f2;
635      break;
636    case TOKENIZER_LE:
637      f1 = f1 <= f2;
638      break;
639    case TOKENIZER_GE:
640      f1 = f1 >= f2;
641      break;
642    case TOKENIZER_OR:
643      f1 = f1 | f2;
644      break;
645    case TOKENIZER_XOR:
646      f1 = f1 ^ f2;
647      break;
648    }
649    op = tokenizer_token();
650  }
651  DEBUG_PRINTF("term: %d\n", f1);
652  return f1;
653}
654/*---------------------------------------------------------------------------*/
655static int
656expr(void)
657{
658  int t1, t2;
659  int op;
660 
661  t1 = term();
662  op = tokenizer_token();
663  DEBUG_PRINTF("expr: token %d\n", op);
664  while(op == TOKENIZER_PLUS ||
665        op == TOKENIZER_MINUS ||
666        op == TOKENIZER_AND ||
667        op == TOKENIZER_LOR ||
668        op == TOKENIZER_XOR) {
669    tokenizer_next();
670    t2 = term();
671    DEBUG_PRINTF("expr: %d %d %d\n", t1, op, t2);
672    switch(op) {
673    case TOKENIZER_PLUS:
674      t1 = t1 + t2;
675      break;
676    case TOKENIZER_MINUS:
677      t1 = t1 - t2;
678      break;
679    case TOKENIZER_AND:
680      t1 = t1 & t2;
681      break;
682    case TOKENIZER_LOR:
683      t1 = t1 || t2;
684      break;
685    }
686    op = tokenizer_token();
687  }
688  DEBUG_PRINTF("expr: %d\n", t1);
689  return t1;
690}
691/*---------------------------------------------------------------------------*/
692static int
693relation(void)
694{
695  int r1, r2;
696  int op;
697 
698  r1 = expr();
699  op = tokenizer_token();
700  DEBUG_PRINTF("relation: token %d\n", op);
701  while(op == TOKENIZER_LAND) {
702    tokenizer_next();
703    r2 = expr();
704    DEBUG_PRINTF("relation: %d %d %d\n", r1, op, r2);
705    switch(op) {
706    case TOKENIZER_LAND:
707      r1 = r1 && r2;
708      break;
709    }
710    op = tokenizer_token();
711  }
712  return r1;
713}
714
715#if 0
716/*---------------------------------------------------------------------------*/
717static void
718jump_linenum(int linenum)
719{
720  tokenizer_init(program_ptr);
721  while(tokenizer_num() != linenum) {
722    do {
723      do {
724        tokenizer_next();
725      } while(tokenizer_token() != TOKENIZER_CR &&
726              tokenizer_token() != TOKENIZER_ENDOFINPUT);
727      if(tokenizer_token() == TOKENIZER_CR) {
728        tokenizer_next();
729      }
730    } while(tokenizer_token() != TOKENIZER_NUMBER);
731    DEBUG_PRINTF("jump_linenum: Found line %d\n", tokenizer_num());
732  }
733}
734#endif
735
736/*---------------------------------------------------------------------------*/
737static void
738jump_line(int linenum)
739{
740  tokenizer_init(program_ptr);
741  while(tokenizer_line_number() != linenum) {
742    tokenizer_next();
743  }
744  /* swallow the CR that would be read next */
745  accept(TOKENIZER_CR);
746
747}
748/*---------------------------------------------------------------------------*/
749// TODO: error handling?
750int
751jump_label(char * label)
752{
753  char currLabel[MAX_STRINGLEN];
754  tokenizer_init(program_ptr);
755  currLabel[0] = 0;
756  while(tokenizer_token() != TOKENIZER_ENDOFINPUT) {
757    tokenizer_next();
758    if (tokenizer_token() == TOKENIZER_LABEL) {
759      tokenizer_label(currLabel, sizeof(currLabel));
760      tokenizer_next();
761      if(strcmp(label, currLabel) == 0) {
762        accept(TOKENIZER_CR);
763        DEBUG_PRINTF("jump_linenum: Found line %d\n", tokenizer_line_number());
764        break;
765      }
766    }
767  }
768  if (tokenizer_token() == TOKENIZER_ENDOFINPUT) {
769    if (state_kbd_script_run == 1) { 
770      DEBUG_PRINTF("Label %s not found", label);
771      ubasic_error = UBASIC_E_UNK_LABEL;
772    }
773      return 0;
774  } else {
775      return 1;
776  }
777}
778/*---------------------------------------------------------------------------*/
779static void
780goto_statement(void)
781{
782  accept(TOKENIZER_GOTO);
783  if(tokenizer_token() == TOKENIZER_STRING) {
784    tokenizer_string(string, sizeof(string));
785    tokenizer_next();
786    jump_label(string);
787  } else {
788    DEBUG_PRINTF("ubasic.c: goto_statement(): no label specified\n");
789    ended = 1;
790    ubasic_error = UBASIC_E_UNK_LABEL;
791  }
792}
793/*---------------------------------------------------------------------------*/
794static void
795print_statement(void)
796{
797  static char buf[128];
798
799  buf[0]=0;
800  accept(TOKENIZER_PRINT);
801  do {
802    DEBUG_PRINTF("Print loop\n");
803    if(tokenizer_token() == TOKENIZER_STRING) {
804      tokenizer_string(string, sizeof(string));
805      sprintf(buf+strlen(buf), "%s", string);
806      tokenizer_next();
807    } else if(tokenizer_token() == TOKENIZER_COMMA) {
808      strcat(buf, " ");
809      tokenizer_next();
810    } else if(tokenizer_token() == TOKENIZER_SEMICOLON) {
811      tokenizer_next();
812    } else {
813      sprintf(buf+strlen(buf), "%d", expr());
814    }
815  } while(tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ENDOFINPUT && tokenizer_token() != TOKENIZER_ELSE);
816  script_console_add_line(buf);
817  DEBUG_PRINTF("End of print\n");
818  accept_cr();
819}
820/*---------------------------------------------------------------------------*/
821/* IF-STATEMENT                                                              */
822
823static void
824endif_statement(void)
825{
826  if(if_stack_ptr > 0) {
827    accept(TOKENIZER_ENDIF);
828    accept(TOKENIZER_CR);
829    if_stack_ptr--;
830  } else {
831    DEBUG_PRINTF("ubasic.c: endif_statement(): endif without if-statement\n");
832    ended = 1;
833    ubasic_error = UBASIC_E_UNMATCHED_IF;
834  }
835}
836/*---------------------------------------------------------------------------*/
837static void
838if_statement(void)
839{
840  int r, else_cntr,endif_cntr,f_nt,f_sl;
841 
842  accept(TOKENIZER_IF);
843  DEBUG_PRINTF("if_statement: get_relation\n");
844  r = relation();
845  DEBUG_PRINTF("if_statement: relation %d\n", r);
846  accept(TOKENIZER_THEN);
847  if (ended) {
848    return;
849  }
850
851  if (tokenizer_token() == TOKENIZER_CR) {
852    // CR after then -> multiline IF-Statement
853    if(if_stack_ptr < MAX_IF_STACK_DEPTH) {
854      if_stack[if_stack_ptr] = r;
855      if_stack_ptr++;
856    } else {
857      DEBUG_PRINTF("if_statement: IF-stack depth exceeded\n");
858      ended = 1;
859      ubasic_error = UBASIC_E_IF_STACK_EXHAUSTED;
860      return;
861    }
862    DEBUG_PRINTF("if_statement: stack_ptr %d\n", if_stack_ptr);
863    accept(TOKENIZER_CR);
864    if(r) {
865      DEBUG_PRINTF("if_statement: result true\n");
866      return;
867    }else {
868      DEBUG_PRINTF("if_statement: result false\n");
869
870      else_cntr=endif_cntr=0; // number of else/endif possible in current nesting
871      f_nt=f_sl=0; // f_nt flag for additional next token, f_fs flag single line
872
873      while(((tokenizer_token() != TOKENIZER_ELSE &&  tokenizer_token() != TOKENIZER_ENDIF)
874           || else_cntr || endif_cntr) && tokenizer_token() != TOKENIZER_ENDOFINPUT){
875        f_nt=0;
876        // nested if
877        if( tokenizer_token() == TOKENIZER_IF) {
878          else_cntr+=1;
879          endif_cntr+=1;
880          f_sl=0;
881          DEBUG_PRINTF("IF: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
882        }
883        if( tokenizer_token() == TOKENIZER_THEN) {
884          f_nt=1;
885          tokenizer_next();
886          DEBUG_PRINTF("THEN: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
887          if (tokenizer_token() != TOKENIZER_CR) { f_sl=1; }
888          DEBUG_PRINTF("THEN_SL: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
889        }
890        if(tokenizer_token() == TOKENIZER_ELSE) {
891          else_cntr--;
892          DEBUG_PRINTF("ELSE: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
893          if (else_cntr<0) {
894            DEBUG_PRINTF("ubasic.c: if_statement(): else without if-statement\n");
895            ended = 1;
896            ubasic_error = UBASIC_E_UNMATCHED_IF;
897            return;
898          }
899        }
900        if(!f_sl && (tokenizer_token() == TOKENIZER_ENDIF)) {
901          endif_cntr--;
902          if (endif_cntr != else_cntr) else_cntr--;
903          DEBUG_PRINTF("ENDIF: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
904        } else {
905          if (f_sl && (tokenizer_token() == TOKENIZER_CR))  {
906            f_sl=0;
907            endif_cntr--;
908            if (endif_cntr != else_cntr) else_cntr--;
909            DEBUG_PRINTF("ENDIF_SL: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
910          }else{
911            if (tokenizer_token()==TOKENIZER_ENDIF){
912              DEBUG_PRINTF("ubasic.c: if_statement(): endif in singleline if-statement\n");
913              ended = 1;
914              ubasic_error = UBASIC_E_PARSE;
915              return;
916            }
917          }
918        }
919        if (!f_nt) { tokenizer_next(); }
920      }
921      if(tokenizer_token() == TOKENIZER_ELSE) { return; }
922    }
923    endif_statement();
924  }else {
925  // Singleline IF-Statement
926    if(r) {
927      statement();
928    } else {
929      do {
930        tokenizer_next();
931      } while(tokenizer_token() != TOKENIZER_ELSE &&
932        tokenizer_token() != TOKENIZER_CR &&
933        tokenizer_token() != TOKENIZER_ENDOFINPUT);
934      if(tokenizer_token() == TOKENIZER_ELSE) {
935        accept(TOKENIZER_ELSE);
936        statement();
937      } else {
938        accept(TOKENIZER_CR);
939      }
940    }
941  }
942}
943/*---------------------------------------------------------------------------*/
944static void
945else_statement(void)
946{
947  int r=0, endif_cntr, f_nt;
948 
949  accept(TOKENIZER_ELSE);
950  if(if_stack_ptr > 0) {
951    r = if_stack[if_stack_ptr-1];
952  }
953  else{
954    DEBUG_PRINTF("ubasic.c: else_statement(): else without if-statement\n");
955    ended = 1;
956    ubasic_error = UBASIC_E_PARSE;
957    return;
958  }
959  DEBUG_PRINTF("else_statement: relation %d\n", r);
960 
961  if (tokenizer_token() == TOKENIZER_CR) {
962          accept(TOKENIZER_CR);
963          if(!r) {
964      DEBUG_PRINTF("else_statement: result true\n");
965      return;
966    } else {
967      DEBUG_PRINTF("else_statement: result false\n");
968      endif_cntr=0;
969      while(((tokenizer_token() != TOKENIZER_ENDIF )
970           || endif_cntr) && tokenizer_token() != TOKENIZER_ENDOFINPUT){
971        f_nt=0;
972        if( tokenizer_token() == TOKENIZER_IF) {
973          endif_cntr+=1;
974        }
975        if( tokenizer_token() == TOKENIZER_THEN) {
976          tokenizer_next();
977          // then followed by CR -> multi line
978          if (tokenizer_token() == TOKENIZER_CR) {
979            f_nt=1;
980          } else { // single line
981            endif_cntr--;
982            while(tokenizer_token() != TOKENIZER_ENDIF && tokenizer_token() != TOKENIZER_CR
983                 && tokenizer_token() != TOKENIZER_ENDOFINPUT){
984              tokenizer_next();
985            }
986            if (tokenizer_token()==TOKENIZER_ENDIF){
987              DEBUG_PRINTF("ubasic.c: else_statement(): endif in singleline if-statement\n");
988              ended = 1;
989              ubasic_error = UBASIC_E_PARSE;
990              return;
991            }
992          }
993        }
994        if( tokenizer_token() == TOKENIZER_ENDIF)  { endif_cntr--; }
995        if (!f_nt) { tokenizer_next(); }
996      }
997    }
998    endif_statement();
999  }else{
1000    DEBUG_PRINTF("ubasic.c: else_statement(): CR after ELSE expected\n");
1001    ended = 1;
1002    ubasic_error = UBASIC_E_PARSE;
1003  }
1004}
1005/*---------------------------------------------------------------------------*/
1006
1007/*---------------------------------------------------------------------------*/
1008/* SELECT-STATEMENT                                                          */
1009
1010static void
1011dec_select_stack(void)
1012{
1013  if(select_stack_ptr > 0) {
1014      select_stack_ptr--;
1015  } else {
1016    DEBUG_PRINTF("select_statement: SELECT-Stack fail\n");
1017    ended = 1;
1018    ubasic_error = UBASIC_E_UNMATCHED_END_SELECT;
1019  }
1020}
1021/*---------------------------------------------------------------------------*/
1022static void
1023end_select_statement(void)
1024{
1025  if(select_stack_ptr > 0) {
1026    accept(TOKENIZER_END_SELECT);
1027    accept(TOKENIZER_CR);
1028    dec_select_stack();
1029  } else {
1030    DEBUG_PRINTF("ubasic.c: end_select_statement(): end_select without select-statement\n");
1031    ended = 1;
1032    ubasic_error = UBASIC_E_UNMATCHED_END_SELECT;
1033  }
1034}
1035/*---------------------------------------------------------------------------*/
1036static void
1037case_statement(void)
1038{
1039  int select_value, case_value_1, case_value_2, case_value_eq;
1040  short case_run, case_goto = 0, case_gosub = 0;
1041  int cur_ln, gosub_ln = 0;
1042 
1043  accept(TOKENIZER_CASE);
1044  if(select_stack_ptr > 0) {
1045    select_value = select_stack[select_stack_ptr - 1].select_value;
1046    case_run = select_stack[select_stack_ptr - 1].case_run;
1047 
1048    if (!case_run) {
1049      case_value_1 = expr();
1050      case_value_eq = (select_value == case_value_1);
1051      if (case_value_eq) { DEBUG_PRINTF("case_statement: case_value_eq %d, case_value %d\n", case_value_eq, case_value_1); } 
1052
1053      if(tokenizer_token() == TOKENIZER_TO) {
1054        accept(TOKENIZER_TO);
1055        case_value_2 = expr();
1056        if (case_value_1 < case_value_2) {
1057          case_value_eq = ((select_value >= case_value_1) && (select_value <= case_value_2));
1058          DEBUG_PRINTF("case_statement: case_value %d to %d\n", case_value_1, case_value_2);
1059        } else {
1060          case_value_eq = ((select_value >= case_value_2) && (select_value <= case_value_1));
1061          DEBUG_PRINTF("case_statement: case_value %d to %d\n", case_value_2, case_value_1);
1062        }
1063      } else if (tokenizer_token() == TOKENIZER_COMMA) {
1064        do {
1065          accept(TOKENIZER_COMMA);
1066          if (case_value_eq) {
1067            case_value_2 = expr();
1068          } else {
1069            case_value_1 = expr();
1070            case_value_eq = (select_value == case_value_1);
1071          }
1072        } while (tokenizer_token() == TOKENIZER_COMMA);
1073        DEBUG_PRINTF("case_statement: case_value_eq %d, case_value_comma %d\n", case_value_eq, case_value_1);
1074      }
1075     
1076      accept(TOKENIZER_SEMICOLON);
1077      if (case_value_eq) {
1078        case_goto = (tokenizer_token() == TOKENIZER_GOTO);
1079        case_gosub = (tokenizer_token() == TOKENIZER_GOSUB);
1080//GOSUB - save curr linenumber
1081        cur_ln = tokenizer_line_number();
1082//GOSUB
1083        statement();
1084//GOSUB  - save new linenumber, reset to curr linenumber
1085      if (case_gosub) {
1086        gosub_ln = tokenizer_line_number();
1087        jump_line(cur_ln+1);
1088        DEBUG_PRINTF("case_statement: GOSUB: toLN=%d, nextLN=%d\n", gosub_ln, cur_ln+1);
1089      }
1090//GOSUB
1091        DEBUG_PRINTF("case_statement: case execute\n");
1092        case_run = 1;
1093        select_stack[select_stack_ptr - 1].case_run = case_run;
1094      } else {
1095        DEBUG_PRINTF("case_statement: case jump; case_run: %d\n", case_run);
1096        accept_cr();
1097      }
1098    } else {accept_cr();}
1099//REM
1100    while ((tokenizer_token() == TOKENIZER_REM) && (!case_goto)) {statement();}
1101//REM
1102    if (case_goto) { dec_select_stack(); } else {
1103      if ((tokenizer_token() != TOKENIZER_CASE) && (tokenizer_token() != TOKENIZER_CASE_ELSE) &&
1104         (tokenizer_token() != TOKENIZER_END_SELECT)) {
1105         DEBUG_PRINTF("ubasic.c: select_statement(): don't found case, case_else or end_select\n");
1106         ended = 1;
1107         ubasic_error = UBASIC_E_PARSE;
1108      } else {
1109//GOSUB test for end_select and set to gosub-linenumber
1110        if (tokenizer_token() == TOKENIZER_END_SELECT) { end_select_statement(); }
1111        if (case_gosub) {
1112          gosub_stack[gosub_stack_ptr-1] = tokenizer_line_number();
1113          jump_line(gosub_ln);
1114          DEBUG_PRINTF("end_select_statement: GOSUB: returnLN=%d\n", gosub_stack[gosub_stack_ptr-1]);
1115        }
1116      } 
1117//GOSUB       
1118    }
1119  } else {
1120    DEBUG_PRINTF("case_statement: SELECT-Stack fail\n");
1121    ended = 1;
1122    ubasic_error = UBASIC_E_UNMATCHED_END_SELECT;
1123  }
1124}
1125/*---------------------------------------------------------------------------*/
1126static void
1127case_else_statement(void)
1128{
1129  short case_goto = 0, case_gosub = 0;
1130  int cur_ln, gosub_ln = 0;
1131 
1132  accept(TOKENIZER_CASE_ELSE);
1133  if(select_stack_ptr > 0) {
1134    if (!select_stack[select_stack_ptr - 1].case_run) {
1135      case_goto = (tokenizer_token() == TOKENIZER_GOTO);
1136      case_gosub = (tokenizer_token() == TOKENIZER_GOSUB);
1137//GOSUB - save curr linenumber
1138      cur_ln = tokenizer_line_number();
1139//GOSUB
1140      statement();
1141//GOSUB  - save new linenumber, reset to curr linenumber
1142      if (case_gosub) {
1143        gosub_ln = tokenizer_line_number();
1144        jump_line(cur_ln+1);
1145        DEBUG_PRINTF("case_else_statement: GOSUB: toLN=%d, nextLN=%d\n", gosub_ln, cur_ln+1);
1146      }
1147//GOSUB
1148      DEBUG_PRINTF("case_else_statement: case_else execute\n");
1149    } else {
1150      DEBUG_PRINTF("case_else_statement: case_else jump; case_run: %d\n", select_stack[select_stack_ptr - 1].case_run);
1151      accept_cr();
1152    }
1153//REM
1154    while ((tokenizer_token() == TOKENIZER_REM) && (!case_goto)) {statement();}
1155//REM
1156    if (case_goto) { dec_select_stack(); } else {
1157//GOSUB test for end_select and set to gosub-linenumber
1158      if (tokenizer_token() != TOKENIZER_END_SELECT) {
1159        DEBUG_PRINTF("ubasic.c: select_statement(): don't found end_select\n");
1160        ended = 1;
1161        ubasic_error = UBASIC_E_PARSE;
1162      } else {
1163          end_select_statement();
1164        if (case_gosub) {
1165          gosub_stack[gosub_stack_ptr-1] = tokenizer_line_number();
1166          jump_line(gosub_ln);
1167          DEBUG_PRINTF("end_select_statement: GOSUB: returnLN=%d\n", gosub_stack[gosub_stack_ptr-1]);
1168        }
1169      } 
1170//GOSUB     
1171    }
1172  } else {
1173    DEBUG_PRINTF("case_else_statement: SELECT-Stack fault\n");
1174    ended = 1;
1175    ubasic_error = UBASIC_E_UNMATCHED_END_SELECT;
1176  }
1177}
1178/*---------------------------------------------------------------------------*/
1179static void
1180select_statement(void)
1181{
1182 
1183  int select_value;
1184 
1185  accept(TOKENIZER_SELECT);
1186  select_value = expr(); 
1187  accept(TOKENIZER_CR);
1188//REM
1189    while (tokenizer_token() == TOKENIZER_REM) {statement();}
1190//REM
1191 
1192  if(select_stack_ptr < MAX_SELECT_STACK_DEPTH) {
1193    select_stack[select_stack_ptr].select_value = select_value;
1194    select_stack[select_stack_ptr].case_run = 0;
1195    DEBUG_PRINTF("select_statement: new select, value %d\n",select_stack[select_stack_ptr].select_value);
1196    select_stack_ptr++;
1197    if (tokenizer_token() != TOKENIZER_CASE) {
1198      DEBUG_PRINTF("ubasic.c: select_statement(): don't found case-statement\n");
1199      ended = 1;
1200      ubasic_error = UBASIC_E_PARSE;
1201    }
1202    else { case_statement(); }
1203  } else {
1204    DEBUG_PRINTF("select_statement: SELECT-stack depth exceeded\n");
1205    ended = 1;
1206    ubasic_error = UBASIC_E_SELECT_STACK_EXHAUSTED;
1207  }
1208}
1209/* SELECT-STATEMENT END                                                      */
1210/*---------------------------------------------------------------------------*/
1211static void
1212let_statement(void)
1213{
1214 
1215  int var;
1216
1217  var = tokenizer_variable_num();
1218
1219  accept(TOKENIZER_VARIABLE);
1220  accept(TOKENIZER_EQ);
1221  ubasic_set_variable(var, expr());
1222  DEBUG_PRINTF("let_statement: assign %d to %d\n", variables[var], var);
1223  accept_cr();
1224}
1225/*---------------------------------------------------------------------------*/
1226static void
1227rem_statement(void)
1228{
1229  accept(TOKENIZER_REM);
1230  DEBUG_PRINTF("rem_statement\n");
1231  accept(TOKENIZER_CR);
1232}
1233/*---------------------------------------------------------------------------*/
1234static void
1235cls_statement(void)
1236{
1237  accept(TOKENIZER_CLS);
1238  console_clear();
1239  DEBUG_PRINTF("cls_statement\n");
1240  accept(TOKENIZER_CR);
1241}
1242/*---------------------------------------------------------------------------*/
1243static void
1244gosub_statement(void)
1245{
1246  accept(TOKENIZER_GOSUB);
1247  if(tokenizer_token() == TOKENIZER_STRING) {
1248    tokenizer_string(string, sizeof(string));
1249    do {
1250    tokenizer_next();
1251    } while(tokenizer_token() != TOKENIZER_CR);
1252    accept(TOKENIZER_CR);
1253    if(gosub_stack_ptr < MAX_GOSUB_STACK_DEPTH) {
1254/*    tokenizer_line_number_inc();*/
1255      gosub_stack[gosub_stack_ptr] = tokenizer_line_number();
1256      gosub_stack_ptr++;
1257      jump_label(string);
1258    } else {
1259      DEBUG_PRINTF("gosub_statement: gosub stack exhausted\n");
1260      ended = 1;
1261      ubasic_error = UBASIC_E_GOSUB_STACK_EXHAUSTED;
1262    }
1263  } else {
1264    DEBUG_PRINTF("ubasic.c: goto_statement(): no label specified\n");
1265    ended = 1;
1266    ubasic_error = UBASIC_E_UNK_LABEL;
1267  }
1268}
1269/*---------------------------------------------------------------------------*/
1270static void
1271return_statement(void)
1272{
1273  accept(TOKENIZER_RETURN);
1274  if(gosub_stack_ptr > 0) {
1275    gosub_stack_ptr--;
1276    jump_line(gosub_stack[gosub_stack_ptr]);
1277  } else {
1278    DEBUG_PRINTF("return_statement: non-matching return\n");
1279    ended = 1;
1280    ubasic_error = UBASIC_E_UNMATCHED_RETURN;
1281  }
1282}
1283/*---------------------------------------------------------------------------*/
1284static void
1285next_statement(void)
1286{
1287  int var, value;
1288 
1289  accept(TOKENIZER_NEXT);
1290  var = tokenizer_variable_num();
1291  accept(TOKENIZER_VARIABLE);
1292  if(for_stack_ptr > 0 &&
1293     var == for_stack[for_stack_ptr - 1].for_variable) {
1294    value = ubasic_get_variable(var) + for_stack[for_stack_ptr - 1].step;
1295    ubasic_set_variable(var, value);
1296   
1297    if(((for_stack[for_stack_ptr - 1].step > 0) && (value <= for_stack[for_stack_ptr - 1].to)) ||
1298       ((for_stack[for_stack_ptr - 1].step < 0) && (value >= for_stack[for_stack_ptr - 1].to)))
1299        jump_line(for_stack[for_stack_ptr - 1].line_after_for);
1300    else {
1301      for_stack_ptr--;
1302      accept(TOKENIZER_CR);
1303    }
1304  } else {
1305    DEBUG_PRINTF("next_statement: non-matching next (expected %d, found %d)\n", for_stack[for_stack_ptr - 1].for_variable, var);
1306    ended = 1;
1307    ubasic_error = UBASIC_E_UNMATCHED_NEXT;
1308  }
1309
1310}
1311/*---------------------------------------------------------------------------*/
1312static void
1313for_statement(void)
1314{
1315  int for_variable, to, step;
1316 
1317  accept(TOKENIZER_FOR);
1318  for_variable = tokenizer_variable_num();
1319  accept(TOKENIZER_VARIABLE);
1320  accept(TOKENIZER_EQ);
1321  ubasic_set_variable(for_variable, expr());
1322  accept(TOKENIZER_TO);
1323  to = expr();                     
1324  step = 1;
1325  if (tokenizer_token() != TOKENIZER_CR) {
1326          accept(TOKENIZER_STEP);
1327          step = expr();         
1328  }
1329  accept(TOKENIZER_CR);
1330
1331  if(for_stack_ptr < MAX_FOR_STACK_DEPTH) {
1332    for_stack[for_stack_ptr].line_after_for = tokenizer_line_number();
1333    for_stack[for_stack_ptr].for_variable = for_variable;
1334    for_stack[for_stack_ptr].to = to;
1335    for_stack[for_stack_ptr].step = step;
1336    DEBUG_PRINTF("for_statement: new for, var %d to %d\n",
1337                 for_stack[for_stack_ptr].for_variable,
1338                 for_stack[for_stack_ptr].to);
1339                 
1340    for_stack_ptr++;
1341  } else {
1342    DEBUG_PRINTF("for_statement: for stack depth exceeded\n");
1343    ended = 1;
1344    ubasic_error = UBASIC_E_FOR_STACK_EXHAUSTED;
1345  }
1346}
1347/*---------------------------------------------------------------------------*/
1348static void
1349do_statement(void)
1350{
1351  accept(TOKENIZER_DO);
1352  accept(TOKENIZER_CR);
1353  if(do_stack_ptr < MAX_DO_STACK_DEPTH) {
1354     do_stack[do_stack_ptr] = tokenizer_line_number();
1355     do_stack_ptr++;
1356  } else {
1357    DEBUG_PRINTF("do_statement: do stack depth exceeded\n");
1358    ended = 1;
1359    ubasic_error = UBASIC_E_DO_STACK_EXHAUSTED;
1360  }
1361}
1362/*---------------------------------------------------------------------------*/
1363static void
1364until_statement(void)
1365{
1366  int r;
1367 
1368  accept(TOKENIZER_UNTIL);
1369  r = relation();
1370  if(do_stack_ptr > 0) {
1371    if(!r) {
1372      jump_line(do_stack[do_stack_ptr-1]);
1373    } else {
1374      do_stack_ptr--;
1375          accept_cr();
1376    }
1377  } else {
1378    DEBUG_PRINTF("until_statement: unmatched until\n");
1379    ended = 1;
1380    ubasic_error = UBASIC_E_UNMATCHED_UNTIL;
1381  }
1382}
1383/*---------------------------------------------------------------------------*/
1384static void
1385while_statement(void)
1386{
1387  int r, while_cntr;
1388 
1389  accept(TOKENIZER_WHILE);
1390  if(while_stack_ptr < MAX_WHILE_STACK_DEPTH) {
1391    if ((while_stack_ptr == 0)||((while_stack_ptr > 0) && (while_stack[while_stack_ptr-1] != tokenizer_line_number()))){
1392      while_stack[while_stack_ptr] = tokenizer_line_number();
1393      while_stack_ptr++;
1394    }
1395  } else {
1396    DEBUG_PRINTF("while_statement: while stack depth exceeded\n");
1397    ended = 1;
1398    ubasic_error = UBASIC_E_WHILE_STACK_EXHAUSTED;
1399    return;
1400  }
1401
1402  r = relation();
1403  if(while_stack_ptr > 0) {
1404    if(!r) {
1405        while_cntr=0;
1406      while((tokenizer_token() != TOKENIZER_WEND  || while_cntr ) &&
1407              tokenizer_token() != TOKENIZER_ENDOFINPUT){   
1408              if (tokenizer_token() == TOKENIZER_WHILE) while_cntr+=1;
1409              if (tokenizer_token() == TOKENIZER_WEND) while_cntr-=1;           
1410              tokenizer_next();
1411            } 
1412      while_stack_ptr--;
1413   
1414      accept(TOKENIZER_WEND);
1415      accept(TOKENIZER_CR);     
1416    } else {
1417          accept_cr();       
1418    }
1419  } else {
1420    DEBUG_PRINTF("while_statement: unmatched wend\n");
1421    ended = 1;
1422    ubasic_error = UBASIC_E_UNMATCHED_WEND;
1423  }
1424}
1425/*---------------------------------------------------------------------------*/
1426static void
1427wend_statement(void)
1428{
1429  accept(TOKENIZER_WEND);
1430  if(while_stack_ptr > 0) {
1431    jump_line(while_stack[while_stack_ptr-1]);
1432  } else {
1433    DEBUG_PRINTF("wend_statement: unmatched wend\n");
1434    ended = 1;
1435    ubasic_error = UBASIC_E_UNMATCHED_WEND;
1436  }
1437}
1438/*---------------------------------------------------------------------------*/
1439static void
1440end_statement(void)
1441{
1442  accept(TOKENIZER_END);
1443  ended = 1;
1444}
1445/*---------------------------------------------------------------------------*/
1446static void
1447click_statement(void)
1448{
1449  int k;
1450  accept(TOKENIZER_CLICK);
1451  k = ubasic_get_key_arg();
1452  if (k > 0) {
1453    action_push_click(k);
1454    flag_yield=1;
1455  }
1456
1457  DEBUG_PRINTF("End of click\n");
1458  accept_cr();
1459}
1460/*---------------------------------------------------------------------------*/
1461static void
1462press_statement(void)
1463{
1464  int k;
1465  accept(TOKENIZER_PRESS);
1466  k = ubasic_get_key_arg();
1467  if (k > 0) {
1468    action_push_press(k);
1469    flag_yield=1;
1470  }
1471  DEBUG_PRINTF("End of press\n");
1472  accept_cr();
1473}
1474/*---------------------------------------------------------------------------*/
1475static void
1476release_statement(void)
1477{
1478  int k;
1479  accept(TOKENIZER_RELEASE);
1480  k = ubasic_get_key_arg();
1481  if (k > 0) {
1482    action_push_release(k);
1483    flag_yield=1;
1484  }
1485  DEBUG_PRINTF("End of release\n");
1486  accept_cr();
1487}
1488/*---------------------------------------------------------------------------*/
1489static void
1490sleep_statement(void)
1491{
1492  int val;
1493  accept(TOKENIZER_SLEEP);
1494  val = expr();
1495  action_push_delay(val);
1496  flag_yield=1;
1497  DEBUG_PRINTF("End of sleep\n");
1498  accept_cr();
1499}
1500/*---------------------------------------------------------------------------*/
1501static void
1502shoot_statement(void)
1503{
1504  accept(TOKENIZER_SHOOT);
1505  action_push(AS_SHOOT);
1506  flag_yield=1;
1507  DEBUG_PRINTF("End of shoot\n");
1508  accept_cr();
1509}
1510
1511/*---------------------------------------------------------------------------*/
1512static void set_console_layout(void)
1513{
1514  int x1,y1,x2,y2;
1515  accept(TOKENIZER_SET_CONSOLE_LAYOUT);
1516  x1 = expr();
1517  y1 = expr();
1518  x2 = expr();
1519  y2 = expr();
1520  console_set_layout(x1,y1,x2,y2);
1521  accept_cr(); 
1522}
1523/*---------------------------------------------------------------------------*/
1524static void set_console_autoredraw(void)
1525{
1526  accept(TOKENIZER_SET_CONSOLE_AUTOREDRAW);
1527  console_set_autoredraw(expr());
1528  accept_cr(); 
1529}
1530/*---------------------------------------------------------------------------*/
1531static void console_redraw_statement(void)
1532{
1533  accept(TOKENIZER_CONSOLE_REDRAW);
1534  console_redraw();
1535    accept_cr();
1536}
1537
1538static void set_yield_statement()
1539{
1540    accept(TOKENIZER_SET_YIELD);
1541    int val = expr();
1542    yield_max_lines = val?val:YIELD_MAX_LINES_DEFAULT;
1543    val = expr();
1544    yield_max_ms = val?val:YIELD_MAX_MS_DEFAULT;
1545    accept_cr();
1546}
1547
1548/*---------------------------------------------------------------------------*/
1549
1550#ifdef INCLUDE_OLD_GET__SYNTAX
1551
1552// Call 'func' to get a CHDK short value and store in named parameter
1553static void get_short_var_statement(int token, short (*func)(void))
1554{
1555    int var;
1556    accept(token);
1557    var = tokenizer_variable_num();
1558    accept(TOKENIZER_VARIABLE);
1559    ubasic_set_variable(var, func());
1560    accept_cr();
1561}
1562
1563// Call 'func' to get a CHDK int value and store in named parameter
1564static void get_int_var_statement(int token, int (*func)(void))
1565{
1566    int var;
1567    accept(token);
1568    var = tokenizer_variable_num();
1569    accept(TOKENIZER_VARIABLE);
1570    ubasic_set_variable(var, func());
1571    accept_cr();
1572}
1573
1574static void get_prop_statement()
1575{
1576    int var, var1;
1577    accept(TOKENIZER_GET_PROP);
1578    var = expr();
1579    var1 = tokenizer_variable_num();
1580    accept(TOKENIZER_VARIABLE);
1581    ubasic_set_variable(var1, shooting_get_prop(var));
1582       
1583    accept_cr();
1584}
1585
1586#endif
1587
1588// Call CHDK function 'func' with one int parameter
1589static void one_int_param_function(int token, void (*func)(int))
1590{
1591    accept(token);
1592    func(expr());
1593    accept_cr();
1594}
1595
1596// Call CHDK function 'func' with one short parameter
1597static void one_short_param_function(int token, void (*func)(short))
1598{
1599    accept(token);
1600    func(expr());
1601    accept_cr();
1602}
1603
1604// Call CHDK function 'func' with one int parameter plus a second value 'p2'
1605static void one_int_param_plus_const_function(int token, void (*func)(int,short), short p2)
1606{
1607    accept(token);
1608    func(expr(),p2);
1609    accept_cr();
1610}
1611
1612// Call CHDK function 'func' with one short parameter plus a second value 'p2'
1613static void one_short_param_plus_const_function(int token, void (*func)(short,short), short p2)
1614{
1615    accept(token);
1616    func(expr(),p2);
1617    accept_cr();
1618}
1619
1620/*---------------------------------------------------------------------------*/
1621
1622
1623static void set_ev_statement()
1624        {
1625            int to;
1626            accept(TOKENIZER_SET_EV);
1627            to = expr();
1628                shooting_set_prop(PROPCASE_EV_CORRECTION_1, to);
1629                shooting_set_prop(PROPCASE_EV_CORRECTION_2, to);
1630            accept_cr();
1631        }
1632
1633static void set_movie_status_statement()
1634{
1635    int to;
1636    accept(TOKENIZER_SET_MOVIE_STATUS);
1637    to = expr();
1638    if (to==1) {
1639        if (movie_status == 4) {
1640            movie_status = 1;
1641        }
1642    }
1643    if (to==2) {
1644        if (movie_status == 1) {
1645            movie_status = 4;
1646        }
1647    }
1648    if (to==3) {
1649        if (movie_status == 1 || 4) {
1650            movie_status = 5;
1651        }
1652    }
1653    accept_cr();
1654}
1655
1656// Set the property 'prop' value from the next expression
1657static void set_propcase_statement(int token, int prop)
1658{
1659    accept(token);
1660        shooting_set_prop(prop, expr());
1661    accept_cr();
1662}
1663
1664
1665static void set_focus_statement()
1666{
1667    int to;
1668    accept(TOKENIZER_SET_FOCUS);
1669    to = expr();
1670    int m=mode_get()&MODE_SHOOTING_MASK;
1671        int mode_video=MODE_IS_VIDEO(m);
1672#if CAM_HAS_MANUAL_FOCUS
1673    if (shooting_get_focus_mode() || (mode_video)) shooting_set_focus(to, SET_NOW);
1674    else shooting_set_focus(to, SET_LATER);
1675#else
1676    if (mode_video) shooting_set_focus(to, SET_NOW);
1677    else shooting_set_focus(to, SET_LATER);   
1678#endif   
1679    accept_cr();
1680}
1681
1682static void set_led_statement()
1683{
1684    int to, to1, to2;
1685    accept(TOKENIZER_SET_LED);
1686    to = expr();
1687    to1 = expr();
1688        to2 = 200;
1689        if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1690                to2 = expr();
1691    }
1692        camera_set_led(to, to1, to2);
1693    accept_cr();
1694}
1695
1696static void set_prop_statement()
1697{
1698    int to, to1;
1699    accept(TOKENIZER_SET_PROP);
1700    to = expr();
1701    to1 = expr();
1702        shooting_set_prop(to, to1);
1703    accept_cr();
1704}
1705
1706/*---------------------------------------------------------------------------*/
1707
1708static void set_autostart_statement()
1709{
1710    int to;
1711    accept(TOKENIZER_SET_SCRIPT_AUTOSTART);
1712    to = expr();
1713#ifndef UBASIC_TEST
1714        if (to >= 0 && to <= 2) conf.script_startup=to;
1715        conf_save();
1716#endif
1717    accept_cr();
1718}
1719
1720static void set_capture_mode_canon_statement()
1721{
1722    int to;
1723    accept(TOKENIZER_SET_CAPTURE_MODE_CANON);
1724    to = expr();
1725    // if the value as negative, assume it is a mistakenly sign extended PROPCASE_SHOOTING_MODE value
1726    if( to < 0)
1727        to &= 0xFFFF;
1728    shooting_set_mode_canon(to);
1729    accept_cr();
1730}
1731
1732static void reboot_statement() {
1733    accept(TOKENIZER_REBOOT);
1734    if(tokenizer_token() == TOKENIZER_STRING) {
1735        tokenizer_string(string, sizeof(string));
1736        tokenizer_next();
1737            reboot(string);
1738    } else {
1739            reboot(NULL);
1740    }
1741}
1742
1743static void set_config_value_statement()
1744{
1745    int id, value;
1746    tConfigVal configVal = {0,0,0,0};
1747   
1748    accept(TOKENIZER_SET_CONFIG_VALUE);
1749    id = expr();
1750    value = expr();
1751    if( conf_getValue(id, &configVal) == CONF_VALUE ) {
1752        configVal.numb = value;
1753        configVal.isNumb = 1;
1754        conf_setValue(id, configVal);
1755    }
1756    accept_cr();
1757}
1758
1759/*---------------------------------------------------------------------------*/
1760
1761static void wait_click_statement()
1762{
1763    int timeout=0;
1764    accept(TOKENIZER_WAIT_CLICK);
1765    if (tokenizer_token() != TOKENIZER_CR &&
1766        tokenizer_token() != TOKENIZER_ELSE ) {
1767        timeout = expr();
1768    }
1769    action_wait_for_click(timeout);
1770    flag_yield=1;
1771    accept_cr();
1772}
1773
1774static void is_key_statement(void)
1775{
1776    int var;
1777    accept(TOKENIZER_IS_KEY);
1778    var = tokenizer_variable_num();
1779    accept(TOKENIZER_VARIABLE);
1780    ubasic_set_variable(var, script_key_is_clicked(ubasic_get_key_arg()));
1781    DEBUG_PRINTF("End of is_key\n");
1782    accept_cr();
1783}
1784
1785static void get_config_value_statement()
1786{
1787    int var, var1, var2;
1788    tConfigVal configVal;
1789    accept(TOKENIZER_GET_CONFIG_VALUE);
1790    var = expr();
1791    var1 = expr();
1792    var2 = tokenizer_variable_num();
1793    accept(TOKENIZER_VARIABLE);
1794    if( conf_getValue(var, &configVal) == CONF_VALUE ) {
1795        ubasic_set_variable(var2, configVal.numb);
1796    } else {
1797        ubasic_set_variable(var2, var1);
1798    }
1799    accept_cr();
1800}
1801
1802static void on_off_statement(int token, void (*on)(void), void (*off)(void))
1803{
1804  accept(token);
1805  if (expr() > 0) on();
1806  else off();
1807  accept_cr();
1808}
1809
1810
1811static void shutdown_statement(void){
1812  accept(TOKENIZER_SHUT_DOWN);
1813  camera_shutdown_in_a_second();
1814  accept_cr();
1815}
1816
1817/*---------------------------------------------------------------------------*/
1818
1819static void md_get_cell_diff_statement()
1820{
1821    int var, col, row;
1822    accept(TOKENIZER_MD_GET_CELL_DIFF);
1823
1824                col=expr();tokenizer_next();
1825
1826                row=expr();tokenizer_next();
1827
1828    var = tokenizer_variable_num();
1829    accept(TOKENIZER_VARIABLE);
1830       
1831    ubasic_set_variable(var, md_get_cell_diff(col,row));
1832    accept_cr();
1833}
1834
1835static void md_detect_motion_statement()
1836{
1837
1838 int columns;
1839 int rows;
1840 int pixel_measure_mode;
1841 int detection_timeout;
1842 int measure_interval;
1843 int threshold;
1844 int draw_grid=0;
1845 int clipping_region_mode=0;
1846 int clipping_region_row1=0;
1847 int clipping_region_column1=0;
1848 int clipping_region_row2=0;
1849 int clipping_region_column2=0;
1850 int parameters=0;
1851 int pixels_step=1;
1852 int msecs_before_trigger=0;
1853
1854 //static char buf[128];
1855
1856    accept(TOKENIZER_MD_DETECT_MOTION);
1857
1858//              sprintf(buf,"token: %d",tokenizer_token()); script_console_add_line(buf);
1859                columns=expr();tokenizer_next();
1860
1861//              sprintf(buf,"tk: %d",tokenizer_token()); script_console_add_line(buf);
1862                rows=expr();tokenizer_next();
1863
1864//              sprintf(buf,"tk %d",tokenizer_token()); script_console_add_line(buf);
1865                pixel_measure_mode=expr();tokenizer_next();
1866
1867                detection_timeout=expr();tokenizer_next();
1868
1869//              printf("token: %d",tokenizer_token());
1870                measure_interval=expr();tokenizer_next();
1871
1872//              printf("token: %d",tokenizer_token());
1873                threshold=expr();tokenizer_next();
1874
1875//              printf("token: %d",tokenizer_token());
1876                draw_grid=expr();tokenizer_next();
1877
1878//              printf("token: %d",tokenizer_token());
1879        ubasic_md_ret_var_num = tokenizer_variable_num();
1880
1881//              printf("%d,%d,%d,%d",columns,rows,pixel_measure_mode, detection_timeout);
1882
1883    accept(TOKENIZER_VARIABLE);
1884
1885
1886    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE) {
1887                        // eat COMA     
1888//                      tokenizer_next();
1889                }
1890
1891
1892               
1893    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE) {
1894                                tokenizer_next();
1895        clipping_region_mode = expr();
1896    }
1897    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1898                                tokenizer_next();
1899        clipping_region_column1 = expr();
1900    }
1901    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1902                                tokenizer_next();
1903        clipping_region_row1 = expr();
1904    }
1905    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1906                                tokenizer_next();
1907        clipping_region_column2 = expr();
1908    }
1909    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1910                                tokenizer_next();
1911        clipping_region_row2 = expr();
1912    }
1913    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1914                                tokenizer_next();
1915        parameters = expr();
1916    }
1917    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1918                                tokenizer_next();
1919        pixels_step = expr();
1920    }
1921
1922    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1923                                tokenizer_next();
1924        msecs_before_trigger = expr();
1925    }
1926                       
1927
1928    accept_cr();
1929
1930//              sprintf(buf,"[%dx%d] md:%d tmout:%d", columns, rows, pixel_measure_mode, detection_timeout);
1931//              script_console_add_line(buf);
1932
1933//              sprintf(buf,"int:%d trsh:%d g:%d vr:%d", measure_interval, threshold, draw_grid, ret_var_num);
1934//              script_console_add_line(buf);
1935
1936//              sprintf(buf,"clip %d [%d,%d][%d,%d]", clipping_region_mode, clipping_region_column1, clipping_region_row1, clipping_region_column2,clipping_region_row2);
1937//              script_console_add_line(buf);
1938
1939        md_init_motion_detector(
1940                        columns, rows, pixel_measure_mode, detection_timeout,
1941                        measure_interval, threshold, draw_grid,
1942                        clipping_region_mode,
1943                        clipping_region_column1, clipping_region_row1,
1944                        clipping_region_column2, clipping_region_row2,
1945                        parameters, pixels_step, msecs_before_trigger
1946        );
1947    flag_yield=1;
1948}
1949
1950/*---------------------------------------------------------------------------*/
1951
1952static void
1953statement(void)
1954{
1955  ubasic_token token;
1956
1957  token = tokenizer_token();
1958
1959  switch(token) {
1960  // aflock
1961  case TOKENIZER_SET_AFLOCK:
1962      on_off_statement(token, DoAFLock, UnlockAF);
1963      break;
1964
1965  case TOKENIZER_PRINT_SCREEN:
1966      one_int_param_function(token, script_print_screen_statement);
1967      break;
1968  case TOKENIZER_PRINT:
1969      print_statement();
1970      break;
1971
1972  case TOKENIZER_SLEEP:
1973      sleep_statement();
1974      break;
1975  case TOKENIZER_CLICK:
1976      click_statement();
1977      break;
1978  case TOKENIZER_PRESS:
1979      press_statement();
1980      break;
1981  case TOKENIZER_RELEASE:
1982      release_statement();
1983      break;
1984  case TOKENIZER_SHOOT:
1985      shoot_statement();
1986      break;
1987  case TOKENIZER_SET_CONSOLE_LAYOUT:
1988      set_console_layout();
1989      break;
1990  case TOKENIZER_SET_CONSOLE_AUTOREDRAW:
1991      set_console_autoredraw();
1992      break;
1993  case TOKENIZER_CONSOLE_REDRAW:
1994      console_redraw_statement();
1995      break;
1996#ifdef INCLUDE_OLD_GET__SYNTAX
1997  case TOKENIZER_GET_TV96:
1998      get_short_var_statement(token, shooting_get_tv96);
1999      break;
2000  case TOKENIZER_GET_USER_TV96:
2001      get_short_var_statement(token, shooting_get_user_tv96);
2002      break;
2003  case TOKENIZER_GET_USER_TV_ID:
2004      get_int_var_statement(token, shooting_get_user_tv_id);
2005      break;
2006  case TOKENIZER_GET_AV96:
2007      get_short_var_statement(token, shooting_get_av96);
2008      break;
2009  case TOKENIZER_GET_USER_AV96:
2010      get_short_var_statement(token, shooting_get_user_av96);
2011      break;
2012  case TOKENIZER_GET_USER_AV_ID:
2013      get_int_var_statement(token, shooting_get_user_av_id);
2014      break;
2015  case TOKENIZER_GET_ZOOM:
2016      get_int_var_statement(token, shooting_get_zoom);
2017      break;
2018  case TOKENIZER_GET_FOCUS:
2019      get_int_var_statement(token, shooting_get_subject_distance);
2020      break;
2021  case TOKENIZER_GET_NEAR_LIMIT:
2022      get_int_var_statement(token, shooting_get_near_limit_of_acceptable_sharpness);
2023      break;
2024  case TOKENIZER_GET_FAR_LIMIT:
2025      get_int_var_statement(token, shooting_get_far_limit_of_acceptable_sharpness);
2026      break;
2027  case TOKENIZER_GET_DOF:
2028      get_int_var_statement(token, shooting_get_depth_of_field);
2029      break;
2030  case TOKENIZER_GET_HYPERFOCAL_DIST:
2031      get_int_var_statement(token, shooting_get_hyperfocal_distance);
2032      break;
2033  case TOKENIZER_GET_ISO_MARKET:
2034      get_short_var_statement(token, shooting_get_iso_market);
2035      break;
2036  case TOKENIZER_GET_ISO_REAL:
2037      get_short_var_statement(token, shooting_get_iso_real);
2038      break;
2039  case TOKENIZER_GET_BV96:
2040      get_short_var_statement(token, shooting_get_bv96);
2041      break;
2042  case TOKENIZER_GET_SV96:
2043      get_short_var_statement(token, shooting_get_sv96);
2044      break;
2045  case TOKENIZER_GET_ISO_MODE:
2046      get_int_var_statement(token, shooting_get_iso_mode);
2047      break;
2048  case TOKENIZER_GET_VBATT:
2049      get_int_var_statement(token, (int (*)(void))stat_get_vbatt);
2050      break;
2051  case TOKENIZER_GET_DISK_SIZE:
2052      get_int_var_statement(token, (int (*)(void))GetTotalCardSpaceKb);
2053      break;
2054  case TOKENIZER_GET_FREE_DISK_SPACE:
2055      get_int_var_statement(token, (int (*)(void))GetFreeCardSpaceKb);
2056      break;
2057  case TOKENIZER_GET_JPG_COUNT:
2058      get_int_var_statement(token, (int (*)(void))GetJpgCount);
2059      break;
2060  case TOKENIZER_GET_RAW_COUNT:
2061      get_int_var_statement(token, (int (*)(void))GetRawCount);
2062      break;
2063  case TOKENIZER_GET_PROP:
2064      get_prop_statement();
2065      break;
2066#endif
2067  case TOKENIZER_SET_TV96_DIRECT:
2068      one_short_param_plus_const_function(token, shooting_set_tv96_direct, SET_LATER);
2069      break;
2070  case TOKENIZER_SET_TV96:
2071      one_short_param_plus_const_function(token, shooting_set_tv96, SET_LATER);
2072      break;
2073  case TOKENIZER_PLAY_SOUND:
2074      one_int_param_function(token, (void (*)(int))play_sound);
2075      break;
2076  case TOKENIZER_SET_SHUTTER_SPEED:
2077      one_int_param_plus_const_function(token, shooting_set_shutter_speed_ubasic, SET_LATER);
2078      break;
2079  case TOKENIZER_SET_USER_TV96:
2080      one_short_param_function(token, shooting_set_user_tv96);
2081      break;
2082  case TOKENIZER_SET_USER_TV_BY_ID:
2083      one_int_param_function(token, shooting_set_user_tv_by_id);
2084      break;
2085  case TOKENIZER_SET_USER_TV_BY_ID_REL:
2086      one_int_param_function(token, shooting_set_user_tv_by_id_rel);
2087      break;
2088  case TOKENIZER_SET_AV96_DIRECT:
2089      one_short_param_plus_const_function(token, shooting_set_av96_direct, SET_LATER);
2090      break;
2091  case TOKENIZER_SET_AV96:
2092      one_short_param_plus_const_function(token, shooting_set_av96, SET_LATER);
2093      break;
2094   
2095  case TOKENIZER_SET_USER_AV96:
2096      one_short_param_function(token, shooting_set_user_av96);
2097      break;
2098  case TOKENIZER_SET_USER_AV_BY_ID:
2099      one_int_param_function(token, shooting_set_user_av_by_id);
2100      break;
2101  case TOKENIZER_SET_USER_AV_BY_ID_REL:
2102      one_int_param_function(token, shooting_set_user_av_by_id_rel);
2103      break;
2104   
2105  case TOKENIZER_SET_ND_FILTER:
2106      one_short_param_plus_const_function(token, shooting_set_nd_filter_state, SET_LATER);
2107      break;
2108 
2109  case TOKENIZER_SET_ZOOM:
2110      one_int_param_function(token, shooting_set_zoom);
2111      break;
2112  case TOKENIZER_SET_ZOOM_REL:
2113      one_int_param_function(token, shooting_set_zoom_rel);
2114      break;
2115  case TOKENIZER_SET_ZOOM_SPEED:
2116      one_int_param_function(token, shooting_set_zoom_speed);
2117      break;
2118
2119  case TOKENIZER_SET_FOCUS:
2120      set_focus_statement();
2121      break;
2122
2123  //ARM Begin
2124/*
2125  case TOKENIZER_SET_ISO_MARKET:
2126      one_int_param_function(token, shooting_set_iso_market);
2127      break;
2128  case TOKENIZER_SET_ISO_DL_F_B:
2129      one_int_param_function(token, shooting_set_iso_real_delta_from_base);
2130      break;
2131*/ 
2132  //ARM End
2133 
2134  case TOKENIZER_SET_ISO_REAL:
2135      one_short_param_plus_const_function(token, shooting_set_iso_real, SET_LATER);
2136      break;
2137  case TOKENIZER_SET_SV96:
2138      one_short_param_plus_const_function(token, shooting_set_sv96, SET_LATER);
2139      break;
2140
2141  case TOKENIZER_SET_ISO_MODE:
2142      one_int_param_function(token, shooting_set_iso_mode);
2143      break;
2144
2145  case TOKENIZER_SET_PROP:
2146      set_prop_statement();
2147      break;
2148  case TOKENIZER_SET_LED:
2149      set_led_statement();
2150      break;
2151
2152  case TOKENIZER_SET_EV:
2153     set_ev_statement();
2154     break;
2155
2156  case TOKENIZER_SET_MOVIE_STATUS:
2157      set_movie_status_statement();
2158      break;
2159  case TOKENIZER_SET_RESOLUTION:
2160      set_propcase_statement(token, PROPCASE_RESOLUTION);
2161      break;
2162  case TOKENIZER_SET_QUALITY:
2163      set_propcase_statement(token, PROPCASE_QUALITY);
2164      break;
2165
2166  case TOKENIZER_WAIT_CLICK:
2167      wait_click_statement();
2168      break;
2169  case TOKENIZER_IS_KEY:
2170      is_key_statement();
2171      break;
2172
2173  case TOKENIZER_WHEEL_LEFT:
2174      accept(token);
2175#ifdef CAM_HAS_JOGDIAL
2176      JogDial_CCW();
2177#endif
2178      accept_cr();
2179      break;
2180  case TOKENIZER_WHEEL_RIGHT:
2181      accept(token);
2182#ifdef CAM_HAS_JOGDIAL
2183      JogDial_CW();
2184#endif
2185      accept_cr();
2186      break;
2187
2188  case TOKENIZER_IF:
2189      if_statement();
2190      break;
2191  case TOKENIZER_ELSE:
2192      else_statement();
2193      break;
2194  case TOKENIZER_ENDIF:
2195      endif_statement();
2196      break;
2197  case TOKENIZER_SELECT:
2198      select_statement();
2199      break;
2200  case TOKENIZER_CASE:
2201      case_statement();
2202      break;
2203  case TOKENIZER_CASE_ELSE:
2204      case_else_statement();
2205      break;
2206  case TOKENIZER_GOTO:
2207      goto_statement();
2208      break;
2209  case TOKENIZER_GOSUB:
2210      gosub_statement();
2211      break;
2212  case TOKENIZER_RETURN:
2213      return_statement();
2214      break;
2215  case TOKENIZER_FOR:
2216      for_statement();
2217      break;
2218  case TOKENIZER_NEXT:
2219      next_statement();
2220      break;
2221  case TOKENIZER_DO:
2222      do_statement();
2223      break;
2224  case TOKENIZER_UNTIL:
2225      until_statement();
2226      break;
2227  case TOKENIZER_WHILE:
2228      while_statement();
2229      break;
2230  case TOKENIZER_WEND:
2231      wend_statement();
2232      break;
2233  case TOKENIZER_END:
2234      end_statement();
2235      break;
2236  case TOKENIZER_LET:
2237      accept(TOKENIZER_LET);
2238      /* Fall through. */
2239  case TOKENIZER_VARIABLE:
2240      let_statement();
2241      break;
2242  case TOKENIZER_REM:
2243      rem_statement();
2244      break;
2245  case TOKENIZER_CLS:
2246      cls_statement();
2247      break;
2248  case TOKENIZER_SET_RAW:
2249      one_int_param_function(token, camera_set_raw);
2250      break;
2251  case TOKENIZER_SET_RAW_NR:
2252      one_int_param_function(token, camera_set_nr);
2253      break;
2254  case TOKENIZER_SET_SCRIPT_AUTOSTART:
2255      set_autostart_statement();
2256      break;
2257  case TOKENIZER_EXIT_ALT:
2258      one_int_param_function(token, exit_alt);
2259      break;
2260  case TOKENIZER_SHUT_DOWN:
2261      shutdown_statement();
2262      break;
2263  case TOKENIZER_SET_BACKLIGHT:
2264      on_off_statement(token, TurnOnBackLight, TurnOffBackLight);
2265      break;
2266
2267      // >> mx3 . motion detector
2268  case   TOKENIZER_MD_DETECT_MOTION:
2269      md_detect_motion_statement();
2270      break;
2271  case  TOKENIZER_MD_GET_CELL_DIFF:
2272      md_get_cell_diff_statement();
2273      break;
2274      // << mx3 . motion_detector
2275
2276  case TOKENIZER_SHOT_HISTO_ENABLE:
2277      one_int_param_function(token, (void (*)(int))shot_histogram_set);
2278      break;
2279
2280  case TOKENIZER_SET_RECORD:
2281      on_off_statement(token, levent_set_record, levent_set_play);
2282      break;
2283
2284  case TOKENIZER_SET_CAPTURE_MODE:
2285      one_int_param_function(token, (void (*)(int))shooting_set_mode_chdk);
2286      break;
2287
2288  case TOKENIZER_SET_CAPTURE_MODE_CANON:
2289      set_capture_mode_canon_statement();
2290      break;
2291
2292  case TOKENIZER_REBOOT:
2293      reboot_statement();
2294      break;
2295
2296  case TOKENIZER_GET_CONFIG_VALUE:
2297    get_config_value_statement();
2298    break;
2299
2300  case TOKENIZER_SET_CONFIG_VALUE:
2301    set_config_value_statement();
2302    break;
2303  case TOKENIZER_SET_YIELD:
2304    set_yield_statement();
2305    break;
2306
2307  default:
2308      DEBUG_PRINTF("ubasic.c: statement(): not implemented %d\n", token);
2309      ended = 1;
2310      ubasic_error = UBASIC_E_UNK_STATEMENT;
2311  }
2312}
2313
2314/*---------------------------------------------------------------------------*/
2315static void
2316line_statement(void)
2317{
2318  /* line numbers have been removed */
2319  DEBUG_PRINTF("----------- Line number %d ---------\n", tokenizer_line_number());
2320  /*    current_linenum = tokenizer_num();*/
2321#if 0
2322  if (tokenizer_token() == TOKENIZER_LABEL) {
2323#ifdef DEBUG
2324      tokenizer_label(string, sizeof(string));
2325      DEBUG_PRINTF("line_statement: label: %s\n", string );
2326#endif
2327      accept(TOKENIZER_LABEL);
2328      accept(TOKENIZER_CR);
2329      return;
2330  }
2331#endif
2332  /* reyalp - eat up to 100 labels or rems at a time so they don't cost 10ms each */
2333  int count = 100;
2334  do {
2335    int r=tokenizer_token();
2336    if ( r == TOKENIZER_LABEL ) {
2337      /* hit limit and we are on a label, return */
2338      if( count == 1 )
2339        return;
2340#ifdef DEBUG
2341      tokenizer_label(string, sizeof(string));
2342      DEBUG_PRINTF("line_statement: label: %s\n", string );
2343#endif
2344      accept(TOKENIZER_LABEL);
2345      accept(TOKENIZER_CR);
2346    }
2347    else if ( r == TOKENIZER_REM ) {
2348      rem_statement();
2349    }
2350    else {
2351      break;
2352    }
2353  } while(--count);
2354  statement();
2355  return;
2356}
2357/*---------------------------------------------------------------------------*/
2358void
2359ubasic_run(void)
2360{
2361 unsigned start_tick = get_tick_count();
2362 unsigned lines = 0;
2363 flag_yield = 0;
2364
2365 do
2366 {
2367  if( ubasic_finished() ) {
2368    DEBUG_PRINTF("uBASIC program finished\n");
2369    return;
2370  }
2371
2372  line_statement();
2373
2374  // Return control to CHDK only if external processing required 
2375  if ( flag_yield )
2376    return;
2377
2378  lines++;
2379 } while (lines < yield_max_lines && get_tick_count() - start_tick < yield_max_ms);
2380}
2381/*---------------------------------------------------------------------------*/
2382int
2383ubasic_finished(void)
2384{
2385  return ended || tokenizer_finished();
2386}
2387/*---------------------------------------------------------------------------*/
2388void
2389ubasic_set_variable(int varnum, int value)
2390{
2391  if(varnum >= 0 && varnum < MAX_VARNUM) {
2392    variables[varnum] = value;
2393  }
2394}
2395/*---------------------------------------------------------------------------*/
2396int
2397ubasic_get_variable(int varnum)
2398{
2399  if(varnum >= 0 && varnum < MAX_VARNUM) {
2400    return variables[varnum];
2401  }
2402  return 0;
2403}
2404/*---------------------------------------------------------------------------*/
2405void
2406ubasic_end() {
2407}
2408/*---------------------------------------------------------------------------*/
2409
2410void ubasic_set_md_ret(int md_ret)
2411{
2412    ubasic_set_variable(ubasic_md_ret_var_num, md_ret);
2413}
Note: See TracBrowser for help on using the browser.