root/trunk/lib/ubasic/ubasic.c

Revision 872, 65.4 KB (checked in by msl, 3 months ago)

Aktualisierung auf Rev. 1434 offizieller Trunk

*  http://trac.assembla.com/chdk/changeset/1434/trunk
* Betrifft alle
+ Zusammenfassung der in Revision 867 neu eingeführten uBasic-Befehle zu einem Befehl
+ set_yield MAX_LINES MAX_TICKS

  • 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_clicked(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){return;}
848  if (tokenizer_token() == TOKENIZER_CR) {
849    //multiline IF-Statement
850    if(if_stack_ptr < MAX_IF_STACK_DEPTH) {
851      if_stack[if_stack_ptr] = r;
852      if_stack_ptr++;
853    } else {
854      DEBUG_PRINTF("if_statement: IF-stack depth exceeded\n");
855      ended = 1;
856      ubasic_error = UBASIC_E_IF_STACK_EXHAUSTED;
857      return;
858    }
859    DEBUG_PRINTF("if_statement: stack_ptr %d\n", if_stack_ptr);
860          accept(TOKENIZER_CR);
861          if(r) {
862      DEBUG_PRINTF("if_statement: result true\n");
863                return;
864          }else {
865      DEBUG_PRINTF("if_statement: result false\n");
866     
867                else_cntr=endif_cntr=0;
868                f_nt=f_sl=0;
869
870      while(((tokenizer_token() != TOKENIZER_ELSE &&  tokenizer_token() != TOKENIZER_ENDIF)
871                       || else_cntr || endif_cntr) && tokenizer_token() != TOKENIZER_ENDOFINPUT){
872        f_nt=0;
873        if( tokenizer_token() == TOKENIZER_IF) {
874          else_cntr+=1;
875          endif_cntr+=1;
876          f_sl=0;
877          DEBUG_PRINTF("IF: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
878        }
879        if( tokenizer_token() == TOKENIZER_THEN) {
880          f_nt=1;
881          tokenizer_next();
882          DEBUG_PRINTF("THEN: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
883          if (tokenizer_token() != TOKENIZER_CR) { f_sl=1; }
884          DEBUG_PRINTF("THEN_SL: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
885        }
886        if(tokenizer_token() == TOKENIZER_ELSE) {
887          else_cntr--;
888          DEBUG_PRINTF("ELSE: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
889          if (else_cntr<0) {
890            DEBUG_PRINTF("ubasic.c: if_statement(): if without endif-statement\n");
891            ended = 1;
892            ubasic_error = UBASIC_E_UNMATCHED_IF;
893            return;
894          }
895        }
896        if(!f_sl && (tokenizer_token() == TOKENIZER_ENDIF)) {
897          endif_cntr--;
898          if (endif_cntr != else_cntr) else_cntr--;
899          DEBUG_PRINTF("ENDIF: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
900        } else {
901          if (f_sl && (tokenizer_token() == TOKENIZER_CR))  {
902            f_sl=0;
903            endif_cntr--;
904            if (endif_cntr != else_cntr) else_cntr--;
905            DEBUG_PRINTF("ENDIF_SL: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
906          }else{
907            if (tokenizer_token()==TOKENIZER_ENDIF){
908              DEBUG_PRINTF("ubasic.c: if_statement(): endif in singleline if-statement\n");
909              ended = 1;
910              ubasic_error = UBASIC_E_PARSE;
911              return;
912            }
913          }
914        }
915        if (!f_nt) { tokenizer_next(); }
916      }
917            if(tokenizer_token() == TOKENIZER_ELSE) { return; }
918          }     
919    endif_statement();
920  }else {
921  // Singleline IF-Statement
922          if(r) {
923            statement();
924          } else {
925            do {
926              tokenizer_next();
927            } while(tokenizer_token() != TOKENIZER_ELSE &&
928                    tokenizer_token() != TOKENIZER_CR &&
929                    tokenizer_token() != TOKENIZER_ENDOFINPUT);
930            if(tokenizer_token() == TOKENIZER_ELSE) {
931              accept(TOKENIZER_ELSE);
932              statement();
933            } else { accept(TOKENIZER_CR); }
934    }
935  }
936}
937/*---------------------------------------------------------------------------*/
938static void
939else_statement(void)
940{
941  int r=0, endif_cntr, f_nt;
942 
943  accept(TOKENIZER_ELSE);
944  if(if_stack_ptr > 0) {
945    r = if_stack[if_stack_ptr-1];
946  }
947  else{
948    DEBUG_PRINTF("ubasic.c: else_statement(): else without if-statement\n");
949    ended = 1;
950    ubasic_error = UBASIC_E_PARSE;
951    return;
952  }
953  DEBUG_PRINTF("else_statement: relation %d\n", r);
954 
955  if (tokenizer_token() == TOKENIZER_CR) {
956          accept(TOKENIZER_CR);
957          if(!r) {
958      DEBUG_PRINTF("else_statement: result true\n");
959                return;
960          } else {
961      DEBUG_PRINTF("else_statement: result false\n");
962                endif_cntr=0;
963                while(((tokenizer_token() != TOKENIZER_ENDIF )
964                       || endif_cntr) && tokenizer_token() != TOKENIZER_ENDOFINPUT){
965                  f_nt=0;
966                  if( tokenizer_token() == TOKENIZER_IF) {endif_cntr+=1;}
967                  if( tokenizer_token() == TOKENIZER_THEN) {
968                    tokenizer_next();
969                    if (tokenizer_token() == TOKENIZER_CR) {
970                      f_nt=1;
971                    }else{
972                      endif_cntr--;
973                        while(tokenizer_token() != TOKENIZER_ENDIF && tokenizer_token() != TOKENIZER_CR
974                             && tokenizer_token() != TOKENIZER_ENDOFINPUT){
975                          tokenizer_next();
976                        }
977            if (tokenizer_token()==TOKENIZER_ENDIF){
978              DEBUG_PRINTF("ubasic.c: else_statement(): endif in singleline if-statement\n");
979              ended = 1;
980              ubasic_error = UBASIC_E_PARSE;
981              return;
982            }
983                    }
984                  }
985                    if( tokenizer_token() == TOKENIZER_ENDIF)  { endif_cntr--; }
986                    if (!f_nt) { tokenizer_next(); }
987                  }
988          }
989    endif_statement();
990  }else{
991    DEBUG_PRINTF("ubasic.c: else_statement(): CR after ELSE expected\n");
992    ended = 1;
993    ubasic_error = UBASIC_E_PARSE;
994  }
995}
996/*---------------------------------------------------------------------------*/
997
998/*---------------------------------------------------------------------------*/
999/* SELECT-STATEMENT                                                          */
1000
1001static void
1002dec_select_stack(void)
1003{
1004  if(select_stack_ptr > 0) {
1005      select_stack_ptr--;
1006  } else {
1007    DEBUG_PRINTF("select_statement: SELECT-Stack fail\n");
1008    ended = 1;
1009    ubasic_error = UBASIC_E_UNMATCHED_END_SELECT;
1010  }
1011}
1012/*---------------------------------------------------------------------------*/
1013static void
1014end_select_statement(void)
1015{
1016  if(select_stack_ptr > 0) {
1017    accept(TOKENIZER_END_SELECT);
1018    accept(TOKENIZER_CR);
1019    dec_select_stack();
1020  } else {
1021    DEBUG_PRINTF("ubasic.c: end_select_statement(): end_select without select-statement\n");
1022    ended = 1;
1023    ubasic_error = UBASIC_E_UNMATCHED_END_SELECT;
1024  }
1025}
1026/*---------------------------------------------------------------------------*/
1027static void
1028case_statement(void)
1029{
1030  int select_value, case_value_1, case_value_2, case_value_eq;
1031  short case_run, case_goto = 0, case_gosub = 0;
1032  int cur_ln, gosub_ln = 0;
1033 
1034  accept(TOKENIZER_CASE);
1035  if(select_stack_ptr > 0) {
1036    select_value = select_stack[select_stack_ptr - 1].select_value;
1037    case_run = select_stack[select_stack_ptr - 1].case_run;
1038 
1039    if (!case_run) {
1040      case_value_1 = expr();
1041      case_value_eq = (select_value == case_value_1);
1042      if (case_value_eq) { DEBUG_PRINTF("case_statement: case_value_eq %d, case_value %d\n", case_value_eq, case_value_1); } 
1043
1044      if(tokenizer_token() == TOKENIZER_TO) {
1045        accept(TOKENIZER_TO);
1046        case_value_2 = expr();
1047        if (case_value_1 < case_value_2) {
1048          case_value_eq = ((select_value >= case_value_1) && (select_value <= case_value_2));
1049          DEBUG_PRINTF("case_statement: case_value %d to %d\n", case_value_1, case_value_2);
1050        } else {
1051          case_value_eq = ((select_value >= case_value_2) && (select_value <= case_value_1));
1052          DEBUG_PRINTF("case_statement: case_value %d to %d\n", case_value_2, case_value_1);
1053        }
1054      } else if (tokenizer_token() == TOKENIZER_COMMA) {
1055        do {
1056          accept(TOKENIZER_COMMA);
1057          if (case_value_eq) {
1058            case_value_2 = expr();
1059          } else {
1060            case_value_1 = expr();
1061            case_value_eq = (select_value == case_value_1);
1062          }
1063        } while (tokenizer_token() == TOKENIZER_COMMA);
1064        DEBUG_PRINTF("case_statement: case_value_eq %d, case_value_comma %d\n", case_value_eq, case_value_1);
1065      }
1066     
1067      accept(TOKENIZER_SEMICOLON);
1068      if (case_value_eq) {
1069        case_goto = (tokenizer_token() == TOKENIZER_GOTO);
1070        case_gosub = (tokenizer_token() == TOKENIZER_GOSUB);
1071//GOSUB - save curr linenumber
1072        cur_ln = tokenizer_line_number();
1073//GOSUB
1074        statement();
1075//GOSUB  - save new linenumber, reset to curr linenumber
1076      if (case_gosub) {
1077        gosub_ln = tokenizer_line_number();
1078        jump_line(cur_ln+1);
1079        DEBUG_PRINTF("case_statement: GOSUB: toLN=%d, nextLN=%d\n", gosub_ln, cur_ln+1);
1080      }
1081//GOSUB
1082        DEBUG_PRINTF("case_statement: case execute\n");
1083        case_run = 1;
1084        select_stack[select_stack_ptr - 1].case_run = case_run;
1085      } else {
1086        DEBUG_PRINTF("case_statement: case jump; case_run: %d\n", case_run);
1087        accept_cr();
1088      }
1089    } else {accept_cr();}
1090//REM
1091    while ((tokenizer_token() == TOKENIZER_REM) && (!case_goto)) {statement();}
1092//REM
1093    if (case_goto) { dec_select_stack(); } else {
1094      if ((tokenizer_token() != TOKENIZER_CASE) && (tokenizer_token() != TOKENIZER_CASE_ELSE) &&
1095         (tokenizer_token() != TOKENIZER_END_SELECT)) {
1096         DEBUG_PRINTF("ubasic.c: select_statement(): don't found case, case_else or end_select\n");
1097         ended = 1;
1098         ubasic_error = UBASIC_E_PARSE;
1099      } else {
1100//GOSUB test for end_select and set to gosub-linenumber
1101        if (tokenizer_token() == TOKENIZER_END_SELECT) { end_select_statement(); }
1102        if (case_gosub) {
1103          gosub_stack[gosub_stack_ptr-1] = tokenizer_line_number();
1104          jump_line(gosub_ln);
1105          DEBUG_PRINTF("end_select_statement: GOSUB: returnLN=%d\n", gosub_stack[gosub_stack_ptr-1]);
1106        }
1107      } 
1108//GOSUB       
1109    }
1110  } else {
1111    DEBUG_PRINTF("case_statement: SELECT-Stack fail\n");
1112    ended = 1;
1113    ubasic_error = UBASIC_E_UNMATCHED_END_SELECT;
1114  }
1115}
1116/*---------------------------------------------------------------------------*/
1117static void
1118case_else_statement(void)
1119{
1120  short case_goto = 0, case_gosub = 0;
1121  int cur_ln, gosub_ln = 0;
1122 
1123  accept(TOKENIZER_CASE_ELSE);
1124  if(select_stack_ptr > 0) {
1125    if (!select_stack[select_stack_ptr - 1].case_run) {
1126      case_goto = (tokenizer_token() == TOKENIZER_GOTO);
1127      case_gosub = (tokenizer_token() == TOKENIZER_GOSUB);
1128//GOSUB - save curr linenumber
1129      cur_ln = tokenizer_line_number();
1130//GOSUB
1131      statement();
1132//GOSUB  - save new linenumber, reset to curr linenumber
1133      if (case_gosub) {
1134        gosub_ln = tokenizer_line_number();
1135        jump_line(cur_ln+1);
1136        DEBUG_PRINTF("case_else_statement: GOSUB: toLN=%d, nextLN=%d\n", gosub_ln, cur_ln+1);
1137      }
1138//GOSUB
1139      DEBUG_PRINTF("case_else_statement: case_else execute\n");
1140    } else {
1141      DEBUG_PRINTF("case_else_statement: case_else jump; case_run: %d\n", select_stack[select_stack_ptr - 1].case_run);
1142      accept_cr();
1143    }
1144//REM
1145    while ((tokenizer_token() == TOKENIZER_REM) && (!case_goto)) {statement();}
1146//REM
1147    if (case_goto) { dec_select_stack(); } else {
1148//GOSUB test for end_select and set to gosub-linenumber
1149      if (tokenizer_token() != TOKENIZER_END_SELECT) {
1150        DEBUG_PRINTF("ubasic.c: select_statement(): don't found end_select\n");
1151        ended = 1;
1152        ubasic_error = UBASIC_E_PARSE;
1153      } else {
1154          end_select_statement();
1155        if (case_gosub) {
1156          gosub_stack[gosub_stack_ptr-1] = tokenizer_line_number();
1157          jump_line(gosub_ln);
1158          DEBUG_PRINTF("end_select_statement: GOSUB: returnLN=%d\n", gosub_stack[gosub_stack_ptr-1]);
1159        }
1160      } 
1161//GOSUB     
1162    }
1163  } else {
1164    DEBUG_PRINTF("case_else_statement: SELECT-Stack fault\n");
1165    ended = 1;
1166    ubasic_error = UBASIC_E_UNMATCHED_END_SELECT;
1167  }
1168}
1169/*---------------------------------------------------------------------------*/
1170static void
1171select_statement(void)
1172{
1173 
1174  int select_value;
1175 
1176  accept(TOKENIZER_SELECT);
1177  select_value = expr(); 
1178  accept(TOKENIZER_CR);
1179//REM
1180    while (tokenizer_token() == TOKENIZER_REM) {statement();}
1181//REM
1182 
1183  if(select_stack_ptr < MAX_SELECT_STACK_DEPTH) {
1184    select_stack[select_stack_ptr].select_value = select_value;
1185    select_stack[select_stack_ptr].case_run = 0;
1186    DEBUG_PRINTF("select_statement: new select, value %d\n",select_stack[select_stack_ptr].select_value);
1187    select_stack_ptr++;
1188    if (tokenizer_token() != TOKENIZER_CASE) {
1189      DEBUG_PRINTF("ubasic.c: select_statement(): don't found case-statement\n");
1190      ended = 1;
1191      ubasic_error = UBASIC_E_PARSE;
1192    }
1193    else { case_statement(); }
1194  } else {
1195    DEBUG_PRINTF("select_statement: SELECT-stack depth exceeded\n");
1196    ended = 1;
1197    ubasic_error = UBASIC_E_SELECT_STACK_EXHAUSTED;
1198  }
1199}
1200/* SELECT-STATEMENT END                                                      */
1201/*---------------------------------------------------------------------------*/
1202static void
1203let_statement(void)
1204{
1205 
1206  int var;
1207
1208  var = tokenizer_variable_num();
1209
1210  accept(TOKENIZER_VARIABLE);
1211  accept(TOKENIZER_EQ);
1212  ubasic_set_variable(var, expr());
1213  DEBUG_PRINTF("let_statement: assign %d to %d\n", variables[var], var);
1214  accept_cr();
1215}
1216/*---------------------------------------------------------------------------*/
1217static void
1218rem_statement(void)
1219{
1220  accept(TOKENIZER_REM);
1221  DEBUG_PRINTF("rem_statement\n");
1222  accept(TOKENIZER_CR);
1223}
1224/*---------------------------------------------------------------------------*/
1225static void
1226cls_statement(void)
1227{
1228  accept(TOKENIZER_CLS);
1229  console_clear();
1230  DEBUG_PRINTF("cls_statement\n");
1231  accept(TOKENIZER_CR);
1232}
1233/*---------------------------------------------------------------------------*/
1234static void
1235gosub_statement(void)
1236{
1237  accept(TOKENIZER_GOSUB);
1238  if(tokenizer_token() == TOKENIZER_STRING) {
1239    tokenizer_string(string, sizeof(string));
1240    do {
1241    tokenizer_next();
1242    } while(tokenizer_token() != TOKENIZER_CR);
1243    accept(TOKENIZER_CR);
1244    if(gosub_stack_ptr < MAX_GOSUB_STACK_DEPTH) {
1245/*    tokenizer_line_number_inc();*/
1246      gosub_stack[gosub_stack_ptr] = tokenizer_line_number();
1247      gosub_stack_ptr++;
1248      jump_label(string);
1249    } else {
1250      DEBUG_PRINTF("gosub_statement: gosub stack exhausted\n");
1251      ended = 1;
1252      ubasic_error = UBASIC_E_GOSUB_STACK_EXHAUSTED;
1253    }
1254  } else {
1255    DEBUG_PRINTF("ubasic.c: goto_statement(): no label specified\n");
1256    ended = 1;
1257    ubasic_error = UBASIC_E_UNK_LABEL;
1258  }
1259}
1260/*---------------------------------------------------------------------------*/
1261static void
1262return_statement(void)
1263{
1264  accept(TOKENIZER_RETURN);
1265  if(gosub_stack_ptr > 0) {
1266    gosub_stack_ptr--;
1267    jump_line(gosub_stack[gosub_stack_ptr]);
1268  } else {
1269    DEBUG_PRINTF("return_statement: non-matching return\n");
1270    ended = 1;
1271    ubasic_error = UBASIC_E_UNMATCHED_RETURN;
1272  }
1273}
1274/*---------------------------------------------------------------------------*/
1275static void
1276next_statement(void)
1277{
1278  int var, value;
1279 
1280  accept(TOKENIZER_NEXT);
1281  var = tokenizer_variable_num();
1282  accept(TOKENIZER_VARIABLE);
1283  if(for_stack_ptr > 0 &&
1284     var == for_stack[for_stack_ptr - 1].for_variable) {
1285    value = ubasic_get_variable(var) + for_stack[for_stack_ptr - 1].step;
1286    ubasic_set_variable(var, value);
1287   
1288    if(((for_stack[for_stack_ptr - 1].step > 0) && (value <= for_stack[for_stack_ptr - 1].to)) ||
1289       ((for_stack[for_stack_ptr - 1].step < 0) && (value >= for_stack[for_stack_ptr - 1].to)))
1290        jump_line(for_stack[for_stack_ptr - 1].line_after_for);
1291    else {
1292      for_stack_ptr--;
1293      accept(TOKENIZER_CR);
1294    }
1295  } else {
1296    DEBUG_PRINTF("next_statement: non-matching next (expected %d, found %d)\n", for_stack[for_stack_ptr - 1].for_variable, var);
1297    ended = 1;
1298    ubasic_error = UBASIC_E_UNMATCHED_NEXT;
1299  }
1300
1301}
1302/*---------------------------------------------------------------------------*/
1303static void
1304for_statement(void)
1305{
1306  int for_variable, to, step;
1307 
1308  accept(TOKENIZER_FOR);
1309  for_variable = tokenizer_variable_num();
1310  accept(TOKENIZER_VARIABLE);
1311  accept(TOKENIZER_EQ);
1312  ubasic_set_variable(for_variable, expr());
1313  accept(TOKENIZER_TO);
1314  to = expr();                     
1315  step = 1;
1316  if (tokenizer_token() != TOKENIZER_CR) {
1317          accept(TOKENIZER_STEP);
1318          step = expr();         
1319  }
1320  accept(TOKENIZER_CR);
1321
1322  if(for_stack_ptr < MAX_FOR_STACK_DEPTH) {
1323    for_stack[for_stack_ptr].line_after_for = tokenizer_line_number();
1324    for_stack[for_stack_ptr].for_variable = for_variable;
1325    for_stack[for_stack_ptr].to = to;
1326    for_stack[for_stack_ptr].step = step;
1327    DEBUG_PRINTF("for_statement: new for, var %d to %d\n",
1328                 for_stack[for_stack_ptr].for_variable,
1329                 for_stack[for_stack_ptr].to);
1330                 
1331    for_stack_ptr++;
1332  } else {
1333    DEBUG_PRINTF("for_statement: for stack depth exceeded\n");
1334    ended = 1;
1335    ubasic_error = UBASIC_E_FOR_STACK_EXHAUSTED;
1336  }
1337}
1338/*---------------------------------------------------------------------------*/
1339static void
1340do_statement(void)
1341{
1342  accept(TOKENIZER_DO);
1343  accept(TOKENIZER_CR);
1344  if(do_stack_ptr < MAX_DO_STACK_DEPTH) {
1345     do_stack[do_stack_ptr] = tokenizer_line_number();
1346     do_stack_ptr++;
1347  } else {
1348    DEBUG_PRINTF("do_statement: do stack depth exceeded\n");
1349    ended = 1;
1350    ubasic_error = UBASIC_E_DO_STACK_EXHAUSTED;
1351  }
1352}
1353/*---------------------------------------------------------------------------*/
1354static void
1355until_statement(void)
1356{
1357  int r;
1358 
1359  accept(TOKENIZER_UNTIL);
1360  r = relation();
1361  if(do_stack_ptr > 0) {
1362    if(!r) {
1363      jump_line(do_stack[do_stack_ptr-1]);
1364    } else {
1365      do_stack_ptr--;
1366          accept_cr();
1367    }
1368  } else {
1369    DEBUG_PRINTF("until_statement: unmatched until\n");
1370    ended = 1;
1371    ubasic_error = UBASIC_E_UNMATCHED_UNTIL;
1372  }
1373}
1374/*---------------------------------------------------------------------------*/
1375static void
1376while_statement(void)
1377{
1378  int r, while_cntr;
1379 
1380  accept(TOKENIZER_WHILE);
1381  if(while_stack_ptr < MAX_WHILE_STACK_DEPTH) {
1382    if ((while_stack_ptr == 0)||((while_stack_ptr > 0) && (while_stack[while_stack_ptr-1] != tokenizer_line_number()))){
1383      while_stack[while_stack_ptr] = tokenizer_line_number();
1384      while_stack_ptr++;
1385    }
1386  } else {
1387    DEBUG_PRINTF("while_statement: while stack depth exceeded\n");
1388    ended = 1;
1389    ubasic_error = UBASIC_E_WHILE_STACK_EXHAUSTED;
1390    return;
1391  }
1392
1393  r = relation();
1394  if(while_stack_ptr > 0) {
1395    if(!r) {
1396        while_cntr=0;
1397      while((tokenizer_token() != TOKENIZER_WEND  || while_cntr ) &&
1398              tokenizer_token() != TOKENIZER_ENDOFINPUT){   
1399              if (tokenizer_token() == TOKENIZER_WHILE) while_cntr+=1;
1400              if (tokenizer_token() == TOKENIZER_WEND) while_cntr-=1;           
1401              tokenizer_next();
1402            } 
1403      while_stack_ptr--;
1404   
1405      accept(TOKENIZER_WEND);
1406      accept(TOKENIZER_CR);     
1407    } else {
1408          accept_cr();       
1409    }
1410  } else {
1411    DEBUG_PRINTF("while_statement: unmatched wend\n");
1412    ended = 1;
1413    ubasic_error = UBASIC_E_UNMATCHED_WEND;
1414  }
1415}
1416/*---------------------------------------------------------------------------*/
1417static void
1418wend_statement(void)
1419{
1420  accept(TOKENIZER_WEND);
1421  if(while_stack_ptr > 0) {
1422    jump_line(while_stack[while_stack_ptr-1]);
1423  } else {
1424    DEBUG_PRINTF("wend_statement: unmatched wend\n");
1425    ended = 1;
1426    ubasic_error = UBASIC_E_UNMATCHED_WEND;
1427  }
1428}
1429/*---------------------------------------------------------------------------*/
1430static void
1431end_statement(void)
1432{
1433  accept(TOKENIZER_END);
1434  ended = 1;
1435}
1436/*---------------------------------------------------------------------------*/
1437static void
1438click_statement(void)
1439{
1440  int k;
1441  accept(TOKENIZER_CLICK);
1442  k = ubasic_get_key_arg();
1443  if (k > 0) {
1444    action_push_click(k);
1445    flag_yield=1;
1446  }
1447
1448  DEBUG_PRINTF("End of click\n");
1449  accept_cr();
1450}
1451/*---------------------------------------------------------------------------*/
1452static void
1453press_statement(void)
1454{
1455  int k;
1456  accept(TOKENIZER_PRESS);
1457  k = ubasic_get_key_arg();
1458  if (k > 0) {
1459    action_push_press(k);
1460    flag_yield=1;
1461  }
1462  DEBUG_PRINTF("End of press\n");
1463  accept_cr();
1464}
1465/*---------------------------------------------------------------------------*/
1466static void
1467release_statement(void)
1468{
1469  int k;
1470  accept(TOKENIZER_RELEASE);
1471  k = ubasic_get_key_arg();
1472  if (k > 0) {
1473    action_push_release(k);
1474    flag_yield=1;
1475  }
1476  DEBUG_PRINTF("End of release\n");
1477  accept_cr();
1478}
1479/*---------------------------------------------------------------------------*/
1480static void
1481sleep_statement(void)
1482{
1483  int val;
1484  accept(TOKENIZER_SLEEP);
1485  val = expr();
1486  action_push_delay(val);
1487  flag_yield=1;
1488  DEBUG_PRINTF("End of sleep\n");
1489  accept_cr();
1490}
1491/*---------------------------------------------------------------------------*/
1492static void
1493shoot_statement(void)
1494{
1495  accept(TOKENIZER_SHOOT);
1496  action_push(AS_SHOOT);
1497  flag_yield=1;
1498  DEBUG_PRINTF("End of shoot\n");
1499  accept_cr();
1500}
1501
1502/*---------------------------------------------------------------------------*/
1503static void set_console_layout(void)
1504{
1505  int x1,y1,x2,y2;
1506  accept(TOKENIZER_SET_CONSOLE_LAYOUT);
1507  x1 = expr();
1508  y1 = expr();
1509  x2 = expr();
1510  y2 = expr();
1511  console_set_layout(x1,y1,x2,y2);
1512  accept_cr(); 
1513}
1514/*---------------------------------------------------------------------------*/
1515static void set_console_autoredraw(void)
1516{
1517  accept(TOKENIZER_SET_CONSOLE_AUTOREDRAW);
1518  console_set_autoredraw(expr());
1519  accept_cr(); 
1520}
1521/*---------------------------------------------------------------------------*/
1522static void console_redraw_statement(void)
1523{
1524  accept(TOKENIZER_CONSOLE_REDRAW);
1525  console_redraw();
1526    accept_cr();
1527}
1528
1529static void set_yield_statement()
1530{
1531    accept(TOKENIZER_SET_YIELD);
1532    int val = expr();
1533    yield_max_lines = val?val:YIELD_MAX_LINES_DEFAULT;
1534    val = expr();
1535    yield_max_ms = val?val:YIELD_MAX_MS_DEFAULT;
1536    accept_cr();
1537}
1538
1539/*---------------------------------------------------------------------------*/
1540
1541#ifdef INCLUDE_OLD_GET__SYNTAX
1542
1543// Call 'func' to get a CHDK short value and store in named parameter
1544static void get_short_var_statement(int token, short (*func)(void))
1545{
1546    int var;
1547    accept(token);
1548    var = tokenizer_variable_num();
1549    accept(TOKENIZER_VARIABLE);
1550    ubasic_set_variable(var, func());
1551    accept_cr();
1552}
1553
1554// Call 'func' to get a CHDK int value and store in named parameter
1555static void get_int_var_statement(int token, int (*func)(void))
1556{
1557    int var;
1558    accept(token);
1559    var = tokenizer_variable_num();
1560    accept(TOKENIZER_VARIABLE);
1561    ubasic_set_variable(var, func());
1562    accept_cr();
1563}
1564
1565static void get_prop_statement()
1566{
1567    int var, var1;
1568    accept(TOKENIZER_GET_PROP);
1569    var = expr();
1570    var1 = tokenizer_variable_num();
1571    accept(TOKENIZER_VARIABLE);
1572    ubasic_set_variable(var1, shooting_get_prop(var));
1573       
1574    accept_cr();
1575}
1576
1577#endif
1578
1579// Call CHDK function 'func' with one int parameter
1580static void one_int_param_function(int token, void (*func)(int))
1581{
1582    accept(token);
1583    func(expr());
1584    accept_cr();
1585}
1586
1587// Call CHDK function 'func' with one short parameter
1588static void one_short_param_function(int token, void (*func)(short))
1589{
1590    accept(token);
1591    func(expr());
1592    accept_cr();
1593}
1594
1595// Call CHDK function 'func' with one int parameter plus a second value 'p2'
1596static void one_int_param_plus_const_function(int token, void (*func)(int,short), short p2)
1597{
1598    accept(token);
1599    func(expr(),p2);
1600    accept_cr();
1601}
1602
1603// Call CHDK function 'func' with one short parameter plus a second value 'p2'
1604static void one_short_param_plus_const_function(int token, void (*func)(short,short), short p2)
1605{
1606    accept(token);
1607    func(expr(),p2);
1608    accept_cr();
1609}
1610
1611/*---------------------------------------------------------------------------*/
1612
1613
1614static void set_ev_statement()
1615        {
1616            int to;
1617            accept(TOKENIZER_SET_EV);
1618            to = expr();
1619                shooting_set_prop(PROPCASE_EV_CORRECTION_1, to);
1620                shooting_set_prop(PROPCASE_EV_CORRECTION_2, to);
1621            accept_cr();
1622        }
1623
1624static void set_movie_status_statement()
1625{
1626    int to;
1627    accept(TOKENIZER_SET_MOVIE_STATUS);
1628    to = expr();
1629    if (to==1) {
1630        if (movie_status == 4) {
1631            movie_status = 1;
1632        }
1633    }
1634    if (to==2) {
1635        if (movie_status == 1) {
1636            movie_status = 4;
1637        }
1638    }
1639    if (to==3) {
1640        if (movie_status == 1 || 4) {
1641            movie_status = 5;
1642        }
1643    }
1644    accept_cr();
1645}
1646
1647// Set the property 'prop' value from the next expression
1648static void set_propcase_statement(int token, int prop)
1649{
1650    accept(token);
1651        shooting_set_prop(prop, expr());
1652    accept_cr();
1653}
1654
1655
1656static void set_focus_statement()
1657{
1658    int to;
1659    accept(TOKENIZER_SET_FOCUS);
1660    to = expr();
1661    int m=mode_get()&MODE_SHOOTING_MASK;
1662        int mode_video=MODE_IS_VIDEO(m);
1663#if CAM_HAS_MANUAL_FOCUS
1664    if (shooting_get_focus_mode() || (mode_video)) shooting_set_focus(to, SET_NOW);
1665    else shooting_set_focus(to, SET_LATER);
1666#else
1667    if (mode_video) shooting_set_focus(to, SET_NOW);
1668    else shooting_set_focus(to, SET_LATER);   
1669#endif   
1670    accept_cr();
1671}
1672
1673static void set_led_statement()
1674{
1675    int to, to1, to2;
1676    accept(TOKENIZER_SET_LED);
1677    to = expr();
1678    to1 = expr();
1679        to2 = 200;
1680        if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1681                to2 = expr();
1682    }
1683        camera_set_led(to, to1, to2);
1684    accept_cr();
1685}
1686
1687static void set_prop_statement()
1688{
1689    int to, to1;
1690    accept(TOKENIZER_SET_PROP);
1691    to = expr();
1692    to1 = expr();
1693        shooting_set_prop(to, to1);
1694    accept_cr();
1695}
1696
1697/*---------------------------------------------------------------------------*/
1698
1699static void set_autostart_statement()
1700{
1701    int to;
1702    accept(TOKENIZER_SET_SCRIPT_AUTOSTART);
1703    to = expr();
1704#ifndef UBASIC_TEST
1705        if (to >= 0 && to <= 2) conf.script_startup=to;
1706        conf_save();
1707#endif
1708    accept_cr();
1709}
1710
1711static void set_capture_mode_canon_statement()
1712{
1713    int to;
1714    accept(TOKENIZER_SET_CAPTURE_MODE_CANON);
1715    to = expr();
1716    // if the value as negative, assume it is a mistakenly sign extended PROPCASE_SHOOTING_MODE value
1717    if( to < 0)
1718        to &= 0xFFFF;
1719    shooting_set_mode_canon(to);
1720    accept_cr();
1721}
1722
1723static void reboot_statement() {
1724    accept(TOKENIZER_REBOOT);
1725    if(tokenizer_token() == TOKENIZER_STRING) {
1726        tokenizer_string(string, sizeof(string));
1727        tokenizer_next();
1728    reboot(string);
1729    } else {
1730    reboot(NULL);
1731    }
1732}
1733
1734static void set_config_value_statement()
1735{
1736    int id, value;
1737    tConfigVal configVal = {0,0,0,0};
1738   
1739    accept(TOKENIZER_SET_CONFIG_VALUE);
1740    id = expr();
1741    value = expr();
1742    if( conf_getValue(id, &configVal) == CONF_VALUE ) {
1743        configVal.numb = value;
1744        configVal.isNumb = 1;
1745        conf_setValue(id, configVal);
1746    }
1747    accept_cr();
1748}
1749
1750/*---------------------------------------------------------------------------*/
1751
1752static void wait_click_statement()
1753{
1754    int timeout=0;
1755    accept(TOKENIZER_WAIT_CLICK);
1756    if (tokenizer_token() != TOKENIZER_CR &&
1757        tokenizer_token() != TOKENIZER_ELSE ) {
1758        timeout = expr();
1759    }
1760    action_wait_for_click(timeout);
1761    flag_yield=1;
1762    accept_cr();
1763}
1764
1765static void is_key_statement(void)
1766{
1767    int var;
1768    accept(TOKENIZER_IS_KEY);
1769    var = tokenizer_variable_num();
1770    accept(TOKENIZER_VARIABLE);
1771    ubasic_set_variable(var, script_key_is_clicked(ubasic_get_key_arg()));
1772    DEBUG_PRINTF("End of is_key\n");
1773    accept_cr();
1774}
1775
1776static void get_config_value_statement()
1777{
1778    int var, var1, var2;
1779    tConfigVal configVal;
1780    accept(TOKENIZER_GET_CONFIG_VALUE);
1781    var = expr();
1782    var1 = expr();
1783    var2 = tokenizer_variable_num();
1784    accept(TOKENIZER_VARIABLE);
1785    if( conf_getValue(var, &configVal) == CONF_VALUE ) {
1786        ubasic_set_variable(var2, configVal.numb);
1787    } else {
1788        ubasic_set_variable(var2, var1);
1789    }
1790    accept_cr();
1791}
1792
1793static void on_off_statement(int token, void (*on)(void), void (*off)(void))
1794{
1795  accept(token);
1796  if (expr() > 0) on();
1797  else off();
1798  accept_cr();
1799}
1800
1801
1802static void shutdown_statement(void){
1803  accept(TOKENIZER_SHUT_DOWN);
1804  camera_shutdown_in_a_second();
1805  accept_cr();
1806}
1807
1808/*---------------------------------------------------------------------------*/
1809
1810static void md_get_cell_diff_statement()
1811{
1812    int var, col, row;
1813    accept(TOKENIZER_MD_GET_CELL_DIFF);
1814
1815                col=expr();tokenizer_next();
1816
1817                row=expr();tokenizer_next();
1818
1819    var = tokenizer_variable_num();
1820    accept(TOKENIZER_VARIABLE);
1821       
1822    ubasic_set_variable(var, md_get_cell_diff(col,row));
1823    accept_cr();
1824}
1825
1826static void md_detect_motion_statement()
1827{
1828
1829 int columns;
1830 int rows;
1831 int pixel_measure_mode;
1832 int detection_timeout;
1833 int measure_interval;
1834 int threshold;
1835 int draw_grid=0;
1836 int clipping_region_mode=0;
1837 int clipping_region_row1=0;
1838 int clipping_region_column1=0;
1839 int clipping_region_row2=0;
1840 int clipping_region_column2=0;
1841 int parameters=0;
1842 int pixels_step=1;
1843 int msecs_before_trigger=0;
1844
1845 //static char buf[128];
1846
1847    accept(TOKENIZER_MD_DETECT_MOTION);
1848
1849//              sprintf(buf,"token: %d",tokenizer_token()); script_console_add_line(buf);
1850                columns=expr();tokenizer_next();
1851
1852//              sprintf(buf,"tk: %d",tokenizer_token()); script_console_add_line(buf);
1853                rows=expr();tokenizer_next();
1854
1855//              sprintf(buf,"tk %d",tokenizer_token()); script_console_add_line(buf);
1856                pixel_measure_mode=expr();tokenizer_next();
1857
1858                detection_timeout=expr();tokenizer_next();
1859
1860//              printf("token: %d",tokenizer_token());
1861                measure_interval=expr();tokenizer_next();
1862
1863//              printf("token: %d",tokenizer_token());
1864                threshold=expr();tokenizer_next();
1865
1866//              printf("token: %d",tokenizer_token());
1867                draw_grid=expr();tokenizer_next();
1868
1869//              printf("token: %d",tokenizer_token());
1870        ubasic_md_ret_var_num = tokenizer_variable_num();
1871
1872//              printf("%d,%d,%d,%d",columns,rows,pixel_measure_mode, detection_timeout);
1873
1874    accept(TOKENIZER_VARIABLE);
1875
1876
1877    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE) {
1878                        // eat COMA     
1879//                      tokenizer_next();
1880                }
1881
1882
1883               
1884    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE) {
1885                                tokenizer_next();
1886        clipping_region_mode = expr();
1887    }
1888    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1889                                tokenizer_next();
1890        clipping_region_column1 = expr();
1891    }
1892    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1893                                tokenizer_next();
1894        clipping_region_row1 = expr();
1895    }
1896    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1897                                tokenizer_next();
1898        clipping_region_column2 = expr();
1899    }
1900    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1901                                tokenizer_next();
1902        clipping_region_row2 = expr();
1903    }
1904    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1905                                tokenizer_next();
1906        parameters = expr();
1907    }
1908    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1909                                tokenizer_next();
1910        pixels_step = expr();
1911    }
1912
1913    if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1914                                tokenizer_next();
1915        msecs_before_trigger = expr();
1916    }
1917                       
1918
1919    accept_cr();
1920
1921//              sprintf(buf,"[%dx%d] md:%d tmout:%d", columns, rows, pixel_measure_mode, detection_timeout);
1922//              script_console_add_line(buf);
1923
1924//              sprintf(buf,"int:%d trsh:%d g:%d vr:%d", measure_interval, threshold, draw_grid, ret_var_num);
1925//              script_console_add_line(buf);
1926
1927//              sprintf(buf,"clip %d [%d,%d][%d,%d]", clipping_region_mode, clipping_region_column1, clipping_region_row1, clipping_region_column2,clipping_region_row2);
1928//              script_console_add_line(buf);
1929
1930        md_init_motion_detector(
1931                        columns, rows, pixel_measure_mode, detection_timeout,
1932                        measure_interval, threshold, draw_grid,
1933                        clipping_region_mode,
1934                        clipping_region_column1, clipping_region_row1,
1935                        clipping_region_column2, clipping_region_row2,
1936                        parameters, pixels_step, msecs_before_trigger
1937        );
1938    flag_yield=1;
1939}
1940
1941/*---------------------------------------------------------------------------*/
1942
1943static void
1944statement(void)
1945{
1946  ubasic_token token;
1947
1948  token = tokenizer_token();
1949
1950  switch(token) {
1951  // aflock
1952  case TOKENIZER_SET_AFLOCK:
1953      on_off_statement(token, DoAFLock, UnlockAF);
1954      break;
1955
1956  case TOKENIZER_PRINT_SCREEN:
1957      one_int_param_function(token, script_print_screen_statement);
1958      break;
1959  case TOKENIZER_PRINT:
1960      print_statement();
1961      break;
1962
1963  case TOKENIZER_SLEEP:
1964      sleep_statement();
1965      break;
1966  case TOKENIZER_CLICK:
1967      click_statement();
1968      break;
1969  case TOKENIZER_PRESS:
1970      press_statement();
1971      break;
1972  case TOKENIZER_RELEASE:
1973      release_statement();
1974      break;
1975  case TOKENIZER_SHOOT:
1976      shoot_statement();
1977      break;
1978  case TOKENIZER_SET_CONSOLE_LAYOUT:
1979      set_console_layout();
1980      break;
1981  case TOKENIZER_SET_CONSOLE_AUTOREDRAW:
1982      set_console_autoredraw();
1983      break;
1984  case TOKENIZER_CONSOLE_REDRAW:
1985      console_redraw_statement();
1986      break;
1987#ifdef INCLUDE_OLD_GET__SYNTAX
1988  case TOKENIZER_GET_TV96:
1989      get_short_var_statement(token, shooting_get_tv96);
1990      break;
1991  case TOKENIZER_GET_USER_TV96:
1992      get_short_var_statement(token, shooting_get_user_tv96);
1993      break;
1994  case TOKENIZER_GET_USER_TV_ID:
1995      get_int_var_statement(token, shooting_get_user_tv_id);
1996      break;
1997  case TOKENIZER_GET_AV96:
1998      get_short_var_statement(token, shooting_get_av96);
1999      break;
2000  case TOKENIZER_GET_USER_AV96:
2001      get_short_var_statement(token, shooting_get_user_av96);
2002      break;
2003  case TOKENIZER_GET_USER_AV_ID:
2004      get_int_var_statement(token, shooting_get_user_av_id);
2005      break;
2006  case TOKENIZER_GET_ZOOM:
2007      get_int_var_statement(token, shooting_get_zoom);
2008      break;
2009  case TOKENIZER_GET_FOCUS:
2010      get_int_var_statement(token, shooting_get_subject_distance);
2011      break;
2012  case TOKENIZER_GET_NEAR_LIMIT:
2013      get_int_var_statement(token, shooting_get_near_limit_of_acceptable_sharpness);
2014      break;
2015  case TOKENIZER_GET_FAR_LIMIT:
2016      get_int_var_statement(token, shooting_get_far_limit_of_acceptable_sharpness);
2017      break;
2018  case TOKENIZER_GET_DOF:
2019      get_int_var_statement(token, shooting_get_depth_of_field);
2020      break;
2021  case TOKENIZER_GET_HYPERFOCAL_DIST:
2022      get_int_var_statement(token, shooting_get_hyperfocal_distance);
2023      break;
2024  case TOKENIZER_GET_ISO_MARKET:
2025      get_short_var_statement(token, shooting_get_iso_market);
2026      break;
2027  case TOKENIZER_GET_ISO_REAL:
2028      get_short_var_statement(token, shooting_get_iso_real);
2029      break;
2030  case TOKENIZER_GET_BV96:
2031      get_short_var_statement(token, shooting_get_bv96);
2032      break;
2033  case TOKENIZER_GET_SV96:
2034      get_short_var_statement(token, shooting_get_sv96);
2035      break;
2036  case TOKENIZER_GET_ISO_MODE:
2037      get_int_var_statement(token, shooting_get_iso_mode);
2038      break;
2039  case TOKENIZER_GET_VBATT:
2040      get_int_var_statement(token, (int (*)(void))stat_get_vbatt);
2041      break;
2042  case TOKENIZER_GET_DISK_SIZE:
2043      get_int_var_statement(token, (int (*)(void))GetTotalCardSpaceKb);
2044      break;
2045  case TOKENIZER_GET_FREE_DISK_SPACE:
2046      get_int_var_statement(token, (int (*)(void))GetFreeCardSpaceKb);
2047      break;
2048  case TOKENIZER_GET_JPG_COUNT:
2049      get_int_var_statement(token, (int (*)(void))GetJpgCount);
2050      break;
2051  case TOKENIZER_GET_RAW_COUNT:
2052      get_int_var_statement(token, (int (*)(void))GetRawCount);
2053      break;
2054  case TOKENIZER_GET_PROP:
2055      get_prop_statement();
2056      break;
2057#endif
2058  case TOKENIZER_SET_TV96_DIRECT:
2059      one_short_param_plus_const_function(token, shooting_set_tv96_direct, SET_LATER);
2060      break;
2061  case TOKENIZER_SET_TV96:
2062      one_short_param_plus_const_function(token, shooting_set_tv96, SET_LATER);
2063      break;
2064  case TOKENIZER_PLAY_SOUND:
2065      one_int_param_function(token, (void (*)(int))play_sound);
2066      break;
2067  case TOKENIZER_SET_SHUTTER_SPEED:
2068      one_int_param_plus_const_function(token, shooting_set_shutter_speed_ubasic, SET_LATER);
2069      break;
2070  case TOKENIZER_SET_USER_TV96:
2071      one_short_param_function(token, shooting_set_user_tv96);
2072      break;
2073  case TOKENIZER_SET_USER_TV_BY_ID:
2074      one_int_param_function(token, shooting_set_user_tv_by_id);
2075      break;
2076  case TOKENIZER_SET_USER_TV_BY_ID_REL:
2077      one_int_param_function(token, shooting_set_user_tv_by_id_rel);
2078      break;
2079  case TOKENIZER_SET_AV96_DIRECT:
2080      one_short_param_plus_const_function(token, shooting_set_av96_direct, SET_LATER);
2081      break;
2082  case TOKENIZER_SET_AV96:
2083      one_short_param_plus_const_function(token, shooting_set_av96, SET_LATER);
2084      break;
2085   
2086  case TOKENIZER_SET_USER_AV96:
2087      one_short_param_function(token, shooting_set_user_av96);
2088      break;
2089  case TOKENIZER_SET_USER_AV_BY_ID:
2090      one_int_param_function(token, shooting_set_user_av_by_id);
2091      break;
2092  case TOKENIZER_SET_USER_AV_BY_ID_REL:
2093      one_int_param_function(token, shooting_set_user_av_by_id_rel);
2094      break;
2095   
2096  case TOKENIZER_SET_ND_FILTER:
2097      one_short_param_plus_const_function(token, shooting_set_nd_filter_state, SET_LATER);
2098      break;
2099 
2100  case TOKENIZER_SET_ZOOM:
2101      one_int_param_function(token, shooting_set_zoom);
2102      break;
2103  case TOKENIZER_SET_ZOOM_REL:
2104      one_int_param_function(token, shooting_set_zoom_rel);
2105      break;
2106  case TOKENIZER_SET_ZOOM_SPEED:
2107      one_int_param_function(token, shooting_set_zoom_speed);
2108      break;
2109
2110  case TOKENIZER_SET_FOCUS:
2111      set_focus_statement();
2112      break;
2113
2114  //ARM Begin
2115/*
2116  case TOKENIZER_SET_ISO_MARKET:
2117      one_int_param_function(token, shooting_set_iso_market);
2118      break;
2119  case TOKENIZER_SET_ISO_DL_F_B:
2120      one_int_param_function(token, shooting_set_iso_real_delta_from_base);
2121      break;
2122*/ 
2123  //ARM End
2124 
2125  case TOKENIZER_SET_ISO_REAL:
2126      one_short_param_plus_const_function(token, shooting_set_iso_real, SET_LATER);
2127      break;
2128  case TOKENIZER_SET_SV96:
2129      one_short_param_plus_const_function(token, shooting_set_sv96, SET_LATER);
2130      break;
2131
2132  case TOKENIZER_SET_ISO_MODE:
2133      one_int_param_function(token, shooting_set_iso_mode);
2134      break;
2135
2136  case TOKENIZER_SET_PROP:
2137      set_prop_statement();
2138      break;
2139  case TOKENIZER_SET_LED:
2140      set_led_statement();
2141      break;
2142
2143  case TOKENIZER_SET_EV:
2144     set_ev_statement();
2145     break;
2146
2147  case TOKENIZER_SET_MOVIE_STATUS:
2148      set_movie_status_statement();
2149      break;
2150  case TOKENIZER_SET_RESOLUTION:
2151      set_propcase_statement(token, PROPCASE_RESOLUTION);
2152      break;
2153  case TOKENIZER_SET_QUALITY:
2154      set_propcase_statement(token, PROPCASE_QUALITY);
2155      break;
2156
2157  case TOKENIZER_WAIT_CLICK:
2158      wait_click_statement();
2159      break;
2160  case TOKENIZER_IS_KEY:
2161      is_key_statement();
2162      break;
2163
2164  case TOKENIZER_WHEEL_LEFT:
2165      accept(token);
2166#ifdef CAM_HAS_JOGDIAL
2167      JogDial_CCW();
2168#endif
2169      accept_cr();
2170      break;
2171  case TOKENIZER_WHEEL_RIGHT:
2172      accept(token);
2173#ifdef CAM_HAS_JOGDIAL
2174      JogDial_CW();
2175#endif
2176      accept_cr();
2177      break;
2178
2179  case TOKENIZER_IF:
2180      if_statement();
2181      break;
2182  case TOKENIZER_ELSE:
2183      else_statement();
2184      break;
2185  case TOKENIZER_ENDIF:
2186      endif_statement();
2187      break;
2188  case TOKENIZER_SELECT:
2189      select_statement();
2190      break;
2191  case TOKENIZER_CASE:
2192      case_statement();
2193      break;
2194  case TOKENIZER_CASE_ELSE:
2195      case_else_statement();
2196      break;
2197  case TOKENIZER_GOTO:
2198      goto_statement();
2199      break;
2200  case TOKENIZER_GOSUB:
2201      gosub_statement();
2202      break;
2203  case TOKENIZER_RETURN:
2204      return_statement();
2205      break;
2206  case TOKENIZER_FOR:
2207      for_statement();
2208      break;
2209  case TOKENIZER_NEXT:
2210      next_statement();
2211      break;
2212  case TOKENIZER_DO:
2213      do_statement();
2214      break;
2215  case TOKENIZER_UNTIL:
2216      until_statement();
2217      break;
2218  case TOKENIZER_WHILE:
2219      while_statement();
2220      break;
2221  case TOKENIZER_WEND:
2222      wend_statement();
2223      break;
2224  case TOKENIZER_END:
2225      end_statement();
2226      break;
2227  case TOKENIZER_LET:
2228      accept(TOKENIZER_LET);
2229      /* Fall through. */
2230  case TOKENIZER_VARIABLE:
2231      let_statement();
2232      break;
2233  case TOKENIZER_REM:
2234      rem_statement();
2235      break;
2236  case TOKENIZER_CLS:
2237      cls_statement();
2238      break;
2239  case TOKENIZER_SET_RAW:
2240      one_int_param_function(token, camera_set_raw);
2241      break;
2242  case TOKENIZER_SET_RAW_NR:
2243      one_int_param_function(token, camera_set_nr);
2244      break;
2245  case TOKENIZER_SET_SCRIPT_AUTOSTART:
2246      set_autostart_statement();
2247      break;
2248  case TOKENIZER_EXIT_ALT:
2249      one_int_param_function(token, exit_alt);
2250      break;
2251  case TOKENIZER_SHUT_DOWN:
2252      shutdown_statement();
2253      break;
2254  case TOKENIZER_SET_BACKLIGHT:
2255      on_off_statement(token, TurnOnBackLight, TurnOffBackLight);
2256      break;
2257
2258      // >> mx3 . motion detector
2259  case   TOKENIZER_MD_DETECT_MOTION:
2260      md_detect_motion_statement();
2261      break;
2262  case  TOKENIZER_MD_GET_CELL_DIFF:
2263      md_get_cell_diff_statement();
2264      break;
2265      // << mx3 . motion_detector
2266
2267  case TOKENIZER_SHOT_HISTO_ENABLE:
2268      one_int_param_function(token, (void (*)(int))shot_histogram_set);
2269      break;
2270
2271  case TOKENIZER_SET_RECORD:
2272      on_off_statement(token, levent_set_record, levent_set_play);
2273      break;
2274
2275  case TOKENIZER_SET_CAPTURE_MODE:
2276      one_int_param_function(token, (void (*)(int))shooting_set_mode_chdk);
2277      break;
2278
2279  case TOKENIZER_SET_CAPTURE_MODE_CANON:
2280      set_capture_mode_canon_statement();
2281      break;
2282
2283  case TOKENIZER_REBOOT:
2284      reboot_statement();
2285      break;
2286
2287  case TOKENIZER_GET_CONFIG_VALUE:
2288    get_config_value_statement();
2289    break;
2290
2291  case TOKENIZER_SET_CONFIG_VALUE:
2292    set_config_value_statement();
2293    break;
2294  case TOKENIZER_SET_YIELD:
2295    set_yield_statement();
2296    break;
2297
2298  default:
2299      DEBUG_PRINTF("ubasic.c: statement(): not implemented %d\n", token);
2300      ended = 1;
2301      ubasic_error = UBASIC_E_UNK_STATEMENT;
2302  }
2303}
2304
2305/*---------------------------------------------------------------------------*/
2306static void
2307line_statement(void)
2308{
2309  /* line numbers have been removed */
2310  DEBUG_PRINTF("----------- Line number %d ---------\n", tokenizer_line_number());
2311  /*    current_linenum = tokenizer_num();*/
2312#if 0
2313  if (tokenizer_token() == TOKENIZER_LABEL) {
2314#ifdef DEBUG
2315      tokenizer_label(string, sizeof(string));
2316      DEBUG_PRINTF("line_statement: label: %s\n", string );
2317#endif
2318      accept(TOKENIZER_LABEL);
2319      accept(TOKENIZER_CR);
2320      return;
2321  }
2322#endif
2323  /* reyalp - eat up to 100 labels or rems at a time so they don't cost 10ms each */
2324  int count = 100;
2325  do {
2326    int r=tokenizer_token();
2327    if ( r == TOKENIZER_LABEL ) {
2328      /* hit limit and we are on a label, return */
2329      if( count == 1 )
2330        return;
2331#ifdef DEBUG
2332      tokenizer_label(string, sizeof(string));
2333      DEBUG_PRINTF("line_statement: label: %s\n", string );
2334#endif
2335      accept(TOKENIZER_LABEL);
2336      accept(TOKENIZER_CR);
2337    }
2338    else if ( r == TOKENIZER_REM ) {
2339      rem_statement();
2340    }
2341    else {
2342      break;
2343    }
2344  } while(--count);
2345  statement();
2346  return;
2347}
2348/*---------------------------------------------------------------------------*/
2349void
2350ubasic_run(void)
2351{
2352 unsigned start_tick = get_tick_count();
2353 unsigned lines = 0;
2354 flag_yield = 0;
2355
2356 do
2357 {
2358  if( ubasic_finished() ) {
2359    DEBUG_PRINTF("uBASIC program finished\n");
2360    return;
2361  }
2362
2363  line_statement();
2364
2365  // Return control to CHDK only if external processing required 
2366  if ( flag_yield )
2367    return;
2368
2369  lines++;
2370 } while (lines < yield_max_lines && get_tick_count() - start_tick < yield_max_ms);
2371}
2372/*---------------------------------------------------------------------------*/
2373int
2374ubasic_finished(void)
2375{
2376  return ended || tokenizer_finished();
2377}
2378/*---------------------------------------------------------------------------*/
2379void
2380ubasic_set_variable(int varnum, int value)
2381{
2382  if(varnum >= 0 && varnum < MAX_VARNUM) {
2383    variables[varnum] = value;
2384  }
2385}
2386/*---------------------------------------------------------------------------*/
2387int
2388ubasic_get_variable(int varnum)
2389{
2390  if(varnum >= 0 && varnum < MAX_VARNUM) {
2391    return variables[varnum];
2392  }
2393  return 0;
2394}
2395/*---------------------------------------------------------------------------*/
2396void
2397ubasic_end() {
2398}
2399/*---------------------------------------------------------------------------*/
2400
2401void ubasic_set_md_ret(int md_ret)
2402{
2403    ubasic_set_variable(ubasic_md_ret_var_num, md_ret);
2404}
Note: See TracBrowser for help on using the browser.