root/lib/ubasic/ubasic.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ubasic_linenumber
  2. ubasic_init
  3. ubasic_get_key_arg
  4. accept
  5. accept_cr
  6. varfactor
  7. shooting_get_near_limit_of_acceptable_sharpness
  8. shooting_get_far_limit_of_acceptable_sharpness
  9. shooting_get_depth_of_field
  10. shooting_get_min_stack_distance
  11. factor
  12. term
  13. expr
  14. relation
  15. jump_linenum
  16. jump_line
  17. jump_label
  18. goto_statement
  19. print_statement
  20. endif_statement
  21. if_statement
  22. else_statement
  23. dec_select_stack
  24. end_select_statement
  25. case_statement
  26. case_else_statement
  27. select_statement
  28. let_statement
  29. rem_statement
  30. cls_statement
  31. gosub_statement
  32. return_statement
  33. next_statement
  34. for_statement
  35. do_statement
  36. until_statement
  37. while_statement
  38. wend_statement
  39. end_statement
  40. click_statement
  41. press_statement
  42. release_statement
  43. action_stack_AS_UBASIC_SLEEP
  44. sleep_delay
  45. sleep_statement
  46. shoot_statement
  47. set_console_layout
  48. set_console_autoredraw
  49. console_redraw_statement
  50. set_yield_statement
  51. get_short_var_statement
  52. get_int_var_statement
  53. get_prop_statement
  54. one_int_param_function
  55. one_short_param_function
  56. set_ev_statement
  57. set_movie_status_statement
  58. set_propcase_statement
  59. set_mf_statement
  60. set_focus_statement
  61. set_led_statement
  62. set_prop_statement
  63. set_autostart_statement
  64. set_capture_mode_canon_statement
  65. reboot_statement
  66. set_config_value_statement
  67. action_stack_AS_UBASIC_WAIT_CLICK
  68. wait_click_statement
  69. is_key_statement
  70. set_exit_key_statement
  71. get_config_value_statement
  72. on_off_statement
  73. shutdown_statement
  74. uB_set_av96
  75. uB_set_av96_direct
  76. uB_set_tv96
  77. uB_set_tv96_direct
  78. uB_set_sv96
  79. uB_set_nd_filter_state
  80. uB_set_iso_real
  81. md_get_cell_diff_statement
  82. md_get_cell_val_statement
  83. md_detect_motion_statement
  84. _shot_histogram_set
  85. statement
  86. line_statement
  87. ubasic_run
  88. ubasic_set_variable
  89. ubasic_get_variable
  90. ubasic_end
  91. ubasic_set_as_ret

   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 #include "camera_info.h"
  38 #include "shot_histogram.h"
  39 #include "levent.h"
  40 #include "script.h"
  41 #include "console.h"
  42 #include "conf.h"
  43 #include "lang.h"
  44 #include "gui_lang.h"
  45 #include "action_stack.h"
  46 #include "shooting.h"
  47 #include "sd_card.h"
  48 #include "backlight.h"
  49 #include "battery.h"
  50 #include "temperature.h"
  51 #include "clock.h"
  52 #include "file_counter.h"
  53 #include "lens.h"
  54 #include "debug_led.h"
  55 #include "keyboard.h"
  56 #include "usb_remote.h"
  57 #include "shutdown.h"
  58 #include "sound.h"
  59 #include "motion_detector.h"
  60 
  61 #include "string.h"
  62 #include "time.h"
  63 
  64 #ifdef UBASIC_TEST
  65 #include "camera_functions.h"
  66 Conf conf;                      // TODO: initialisation
  67 _cam_info camera_info;          // TOTO: initialisation
  68 #else
  69 #include "script_key_funcs.h"
  70 #include "properties.h"
  71 #endif
  72 
  73 #include "ubasic.h"
  74 #include "tokenizer.h"
  75 
  76 // Forward references
  77 int ubasic_get_variable(int varnum);
  78 void ubasic_set_variable(int varum, int value);
  79 
  80 #define INCLUDE_OLD_GET__SYNTAX
  81 
  82 static char const *program_ptr;
  83 #define MAX_STRINGLEN 40
  84 static char string[MAX_STRINGLEN];
  85 
  86 #define MAX_GOSUB_STACK_DEPTH 10
  87 static short gosub_stack[MAX_GOSUB_STACK_DEPTH];
  88 static int gosub_stack_ptr;
  89 
  90 #define MAX_IF_STACK_DEPTH 4
  91 static short if_stack[MAX_IF_STACK_DEPTH];
  92 static int if_stack_ptr;
  93 
  94 struct select_state {
  95   int select_value;
  96   short case_run;
  97 };
  98 #define MAX_SELECT_STACK_DEPTH 4
  99 static struct select_state select_stack[MAX_SELECT_STACK_DEPTH];
 100 static int select_stack_ptr;
 101 
 102 #define MAX_WHILE_STACK_DEPTH 4
 103 static short while_stack[MAX_WHILE_STACK_DEPTH];
 104 static int while_stack_ptr;
 105 
 106 #define MAX_DO_STACK_DEPTH 4
 107 static short do_stack[MAX_DO_STACK_DEPTH];
 108 static int do_stack_ptr;
 109 
 110 struct for_state {
 111   short line_after_for;
 112   short for_variable;
 113   int to;
 114   int step;
 115 };
 116 #define MAX_FOR_STACK_DEPTH 4
 117 static struct for_state for_stack[MAX_FOR_STACK_DEPTH];
 118 static int for_stack_ptr;
 119 
 120 #define MAX_VARNUM 52
 121 static int variables[MAX_VARNUM];
 122 
 123 static int ended;
 124 
 125 // Variable number to store return values from Action Stack functions (e.g. motion_detect, shoot)
 126 static int ubasic_as_ret_var_num;
 127 
 128 static int expr(void);
 129 static void line_statement(void);
 130 static void statement(void);
 131 static int relation(void);
 132 
 133 /*
 134 ubasic scheduling controls
 135 ubasic returns control to kbd_task as soon as either of the following is is exceeded
 136 defaults is 1 ubasic line per kbd_task cycle, mimicing old behavior
 137 */
 138 #define YIELD_MAX_LINES_DEFAULT 1
 139 #define YIELD_MAX_MS_DEFAULT 10
 140 // maximum number lines before yielding (labels, blank lines and REMs excluded)
 141 static unsigned yield_max_lines;
 142 // maximum number of ticks before yielding
 143 static unsigned yield_max_ms;
 144 // set flag to immediately transfer execution flow to main CHDK to process external action
 145 // TODO a better approach to this might be to check if AS_RUN is on top of the action_stack
 146 static int flag_yield;
 147 
 148 int ubasic_error;
 149 const char *ubasic_errstrings[UBASIC_E_ENDMARK] =
 150 {
 151     "No err",
 152     "Parse err",
 153     "Unk stmt",
 154     "Unk key",
 155     "Unk label",
 156     "gosub: Stack ful",
 157     "bad return",
 158     "if: Stack ful",
 159     "bad endif",
 160     "select: Stack ful",
 161     "bad end_select",
 162     "for: Stack ful",
 163     "bad next",
 164     "do: Stack ful",
 165     "bad until",
 166     "while: Stack ful",
 167     "bad wend",
 168     "Unk err" 
 169 };
 170 
 171 /*---------------------------------------------------------------------------*/
 172 int
 173 ubasic_linenumber()
 174 {
 175   return tokenizer_line_number();
 176 }
 177 
 178 /*---------------------------------------------------------------------------*/
 179 int
 180 ubasic_init(const char *program, __attribute__ ((unused))int is_ptp)
 181 {
 182   program_ptr = program;
 183   flag_yield = 0;
 184   for_stack_ptr = gosub_stack_ptr = while_stack_ptr = do_stack_ptr = if_stack_ptr = select_stack_ptr = 0;
 185   tokenizer_init(program);
 186   ended = 0;
 187   ubasic_error = UBASIC_E_NONE;
 188   yield_max_lines = YIELD_MAX_LINES_DEFAULT;
 189   yield_max_ms = YIELD_MAX_MS_DEFAULT;
 190   return 1;
 191 }
 192 /*---------------------------------------------------------------------------*/
 193 // read a key name and return key id, 
 194 // set error and return 0 if key invalid
 195 static int ubasic_get_key_arg() {
 196   int k;
 197   tokenizer_string(string, sizeof(string));
 198   tokenizer_next();
 199   k = script_keyid_by_name(string);
 200   if (k <= 0)
 201     ubasic_error = UBASIC_E_UNK_KEY;
 202   return k;
 203 }
 204 /*---------------------------------------------------------------------------*/
 205 static void
 206 accept(int token)
 207 {
 208   if(token != tokenizer_token()) {
 209     DEBUG_PRINTF("Token not what was expected (expected %d, got %d)\n",
 210                  token, tokenizer_token());
 211     tokenizer_error_print();
 212      tokenizer_next();
 213      ended = 1;
 214      ubasic_error = UBASIC_E_PARSE;
 215      return;
 216   }
 217   DEBUG_PRINTF("Expected %d, got it\n", token);
 218   tokenizer_next();
 219 }
 220 /*---------------------------------------------------------------------------*/
 221 static void
 222 accept_cr()
 223 {
 224     while(tokenizer_token() != TOKENIZER_CR &&
 225             tokenizer_token() != TOKENIZER_ENDOFINPUT)
 226       tokenizer_next();
 227     accept(TOKENIZER_CR);
 228 }
 229 /*---------------------------------------------------------------------------*/
 230 static int
 231 varfactor(void)
 232 {
 233   int r;
 234   DEBUG_PRINTF("varfactor: obtaining %d from variable %d\n", variables[tokenizer_variable_num()], tokenizer_variable_num());
 235   r = ubasic_get_variable(tokenizer_variable_num());
 236   accept(TOKENIZER_VARIABLE);
 237   return r;
 238 }
 239 /*---------------------------------------------------------------------------*/
 240 static int shooting_get_near_limit_of_acceptable_sharpness()
 241 {
 242   shooting_update_dof_values();
 243   return camera_info.dof_values.near_limit;
 244 }
 245 
 246 static int shooting_get_far_limit_of_acceptable_sharpness()
 247 {
 248   shooting_update_dof_values();
 249   return camera_info.dof_values.far_limit;
 250 }
 251 
 252 static int shooting_get_depth_of_field()
 253 {
 254   shooting_update_dof_values();
 255   return camera_info.dof_values.depth_of_field;
 256 }
 257 
 258 static int shooting_get_min_stack_distance()
 259 {
 260   shooting_update_dof_values();
 261   return camera_info.dof_values.min_stack_distance;
 262 }
 263 
 264 static int factor(void)
 265 {
 266   int r = 0;
 267   tConfigVal configVal;
 268 
 269   DEBUG_PRINTF("factor: token %d\n", tokenizer_token());
 270   switch(tokenizer_token()) {
 271   case TOKENIZER_NUMBER:
 272     r = tokenizer_num();
 273     DEBUG_PRINTF("factor: number %d\n", r);
 274     accept(TOKENIZER_NUMBER);
 275     break;
 276   case TOKENIZER_LEFTPAREN:
 277     accept(TOKENIZER_LEFTPAREN);
 278     r = relation();
 279     accept(TOKENIZER_RIGHTPAREN);
 280     break;
 281   case TOKENIZER_PLUS:
 282     accept(TOKENIZER_PLUS);
 283     r = factor();
 284     break;
 285   case TOKENIZER_MINUS:
 286     accept(TOKENIZER_MINUS);
 287     r = - factor();
 288     break;
 289   case TOKENIZER_LNOT:
 290     accept(TOKENIZER_LNOT);
 291     r = ! relation();
 292     break;
 293   case TOKENIZER_GET_VBATT:
 294     accept(TOKENIZER_GET_VBATT);
 295     r = (unsigned short) stat_get_vbatt();
 296     break;
 297   case TOKENIZER_GET_DAY_SECONDS:
 298     {
 299         accept(TOKENIZER_GET_DAY_SECONDS);
 300         struct tm *ttm;
 301         ttm = get_localtime();
 302         r = ttm->tm_hour * 3600 + ttm->tm_min * 60 + ttm->tm_sec;
 303     }
 304     break;
 305   case TOKENIZER_GET_TICK_COUNT:
 306     accept(TOKENIZER_GET_TICK_COUNT);
 307     r = get_tick_count();     
 308     break;
 309   case TOKENIZER_GET_MODE:
 310     accept(TOKENIZER_GET_MODE);
 311     if (!camera_info.state.mode_play) r = 0;
 312     if (camera_info.state.mode_play) r = 1;
 313     if (!camera_info.state.mode_play && camera_info.state.mode_video) r = 2;
 314   break;
 315   case TOKENIZER_GET_RAW_NR:
 316     accept(TOKENIZER_GET_RAW_NR);
 317     r = conf.raw_nr;     
 318     break;
 319   case TOKENIZER_IS_KEY:
 320     accept(TOKENIZER_IS_KEY);
 321     r = script_key_is_clicked(ubasic_get_key_arg());
 322     break;
 323   case TOKENIZER_SCRIPT_AUTOSTARTED:
 324     accept(TOKENIZER_SCRIPT_AUTOSTARTED);
 325     r = camera_info.state.auto_started;
 326     break;
 327   case TOKENIZER_GET_SCRIPT_AUTOSTART:
 328     accept(TOKENIZER_GET_SCRIPT_AUTOSTART);
 329 #ifdef UBASIC_TEST
 330     r = 0;
 331 #else
 332     r = conf.script_startup;
 333 #endif
 334     break;
 335   case TOKENIZER_GET_USB_POWER:
 336     accept(TOKENIZER_GET_USB_POWER);
 337         int usbpwr = 0 ;
 338         if (tokenizer_token() != TOKENIZER_CR &&
 339         tokenizer_token() != TOKENIZER_ELSE ) {
 340         usbpwr = expr();
 341     }
 342     r = get_usb_power(usbpwr);
 343     break;
 344   case TOKENIZER_GET_EXP_COUNT:
 345     accept(TOKENIZER_GET_EXP_COUNT);
 346     r = get_exposure_counter();
 347     break;
 348   case TOKENIZER_IS_PRESSED:
 349     accept(TOKENIZER_IS_PRESSED);
 350     r = script_key_is_pressed(ubasic_get_key_arg());
 351     break;
 352   case TOKENIZER_RANDOM:
 353     accept(TOKENIZER_RANDOM);
 354     int min = expr();
 355     int max = expr();
 356     // shouldn't srand every time...
 357     srand((int)shooting_get_bv96()+(unsigned short)stat_get_vbatt()+get_tick_count());
 358     // wtf
 359     action_push_delay(rand()%10);
 360     flag_yield=1;
 361     r = min + rand()%(max-min+1);
 362   break;
 363   case TOKENIZER_GET_MOVIE_STATUS:
 364     accept(TOKENIZER_GET_MOVIE_STATUS);
 365     r = get_movie_status();
 366     break;
 367   case TOKENIZER_GET_PLATFORM_ID:
 368     accept(TOKENIZER_GET_PLATFORM_ID);
 369     r = conf.platformid;
 370     break;
 371   case TOKENIZER_GET_DRIVE_MODE:
 372     accept(TOKENIZER_GET_DRIVE_MODE);
 373     r = shooting_get_drive_mode();
 374     break;
 375    case TOKENIZER_GET_FOCUS_MODE:
 376     accept(TOKENIZER_GET_FOCUS_MODE);
 377     r = shooting_get_real_focus_mode();
 378     break;
 379   case TOKENIZER_GET_FOCUS_STATE:
 380     accept(TOKENIZER_GET_FOCUS_STATE);
 381     r = shooting_get_focus_state();
 382     break;
 383   case TOKENIZER_GET_FOCUS_OK:
 384     accept(TOKENIZER_GET_FOCUS_OK);
 385     r = shooting_get_focus_ok();
 386     break;
 387   case TOKENIZER_GET_DISPLAY_MODE:
 388     accept(TOKENIZER_GET_DISPLAY_MODE);
 389     r = shooting_get_display_mode();
 390     break;
 391   case TOKENIZER_GET_FLASH_MODE:
 392     accept(TOKENIZER_GET_FLASH_MODE);
 393     r = shooting_get_flash_mode();
 394     break;
 395   case TOKENIZER_GET_SHOOTING:
 396     accept(TOKENIZER_GET_SHOOTING);
 397     r = shooting_in_progress();
 398     break;
 399   case TOKENIZER_GET_FLASH_READY:
 400     accept(TOKENIZER_GET_FLASH_READY);
 401     r = shooting_is_flash();
 402     break;
 403   case TOKENIZER_GET_IS_MODE:
 404     accept(TOKENIZER_GET_IS_MODE);
 405     r = shooting_get_is_mode();
 406     break;
 407   case TOKENIZER_GET_EV:
 408     accept(TOKENIZER_GET_EV);
 409     r = shooting_get_ev_correction1();
 410     break;
 411   case TOKENIZER_GET_RESOLUTION:
 412     accept(TOKENIZER_GET_RESOLUTION);
 413     r = shooting_get_resolution();
 414     break;
 415   case TOKENIZER_GET_QUALITY:
 416     accept(TOKENIZER_GET_QUALITY);
 417     r = shooting_get_prop(camera_info.props.quality);
 418     break;
 419   case TOKENIZER_GET_ORIENTATION_SENSOR:
 420     accept(TOKENIZER_GET_ORIENTATION_SENSOR);
 421     r = shooting_get_prop(camera_info.props.orientation_sensor);
 422     break;
 423   case TOKENIZER_GET_ZOOM_STEPS:
 424     accept(TOKENIZER_GET_ZOOM_STEPS);
 425     r = zoom_points;
 426     break;
 427   case TOKENIZER_GET_ND_PRESENT:
 428     accept(TOKENIZER_GET_ND_PRESENT);
 429     if (camera_info.cam_has_nd_filter == 0)
 430     {
 431         r = 0;
 432     }
 433     else
 434     {
 435         if (camera_info.cam_has_iris_diaphragm == 0)
 436         {
 437             r = 1;
 438         }
 439         else
 440         {
 441             r = 2;
 442         }
 443     }
 444     break;
 445   case TOKENIZER_GET_PROPSET:
 446     accept(TOKENIZER_GET_PROPSET);
 447     r = camera_info.props.propset;
 448     break;
 449   case TOKENIZER_GET_TV96:
 450     accept(TOKENIZER_GET_TV96);
 451     r = shooting_get_tv96();
 452     break;
 453   case TOKENIZER_GET_USER_TV96:
 454     accept(TOKENIZER_GET_USER_TV96);
 455     r = shooting_get_user_tv96();
 456     break;   
 457   case TOKENIZER_GET_USER_TV_ID:
 458     accept(TOKENIZER_GET_USER_TV_ID);
 459     r = shooting_get_user_tv_id();
 460     break;
 461   case TOKENIZER_GET_AV96:
 462     accept(TOKENIZER_GET_AV96);
 463     r = shooting_get_av96();
 464     break;  
 465   case TOKENIZER_GET_USER_AV96:
 466     accept(TOKENIZER_GET_USER_AV96);
 467     r = shooting_get_user_av96();
 468     break;    
 469   case TOKENIZER_GET_USER_AV_ID:
 470     accept(TOKENIZER_GET_USER_AV_ID);
 471     r = shooting_get_user_av_id();
 472     break;
 473   case TOKENIZER_GET_ZOOM:
 474     accept(TOKENIZER_GET_ZOOM);
 475     r = shooting_get_zoom();
 476     break;
 477   case TOKENIZER_GET_FOCUS:
 478     accept(TOKENIZER_GET_FOCUS);
 479     r = shooting_get_subject_distance();
 480     break;
 481   case TOKENIZER_GET_NEAR_LIMIT:
 482     accept(TOKENIZER_GET_NEAR_LIMIT);
 483     r = shooting_get_near_limit_of_acceptable_sharpness();
 484     break;
 485   case TOKENIZER_GET_FAR_LIMIT:
 486     accept(TOKENIZER_GET_FAR_LIMIT);
 487     r = shooting_get_far_limit_of_acceptable_sharpness();
 488     break;  
 489    case TOKENIZER_GET_DOF:
 490     accept(TOKENIZER_GET_DOF);
 491     r = shooting_get_depth_of_field();
 492     break;
 493   case TOKENIZER_GET_HYPERFOCAL_DIST:
 494     accept(TOKENIZER_GET_HYPERFOCAL_DIST);
 495     r = shooting_get_hyperfocal_distance();
 496     break;  
 497    case TOKENIZER_GET_SD_OVER_MODES:
 498     accept(TOKENIZER_GET_SD_OVER_MODES);
 499     r = sd_over_modes() ;
 500     break;
 501   case TOKENIZER_GET_ISO_MARKET:
 502     accept(TOKENIZER_GET_ISO_MARKET);
 503     r = (int)shooting_get_iso_market();
 504     break;
 505   case TOKENIZER_GET_ISO_REAL:
 506     accept(TOKENIZER_GET_ISO_REAL);
 507     r = (int)shooting_get_iso_real();
 508     break;
 509   case TOKENIZER_GET_BV96:
 510     accept(TOKENIZER_GET_BV96);
 511     r = (int)shooting_get_bv96();
 512     break;  
 513   case TOKENIZER_GET_SV96:
 514     accept(TOKENIZER_GET_SV96);
 515     r = (int)shooting_get_sv96_real();
 516     break;    
 517   case TOKENIZER_GET_ISO_MODE:
 518     accept(TOKENIZER_GET_ISO_MODE);
 519     r = shooting_get_iso_mode();
 520     break;
 521   case TOKENIZER_GET_DISK_SIZE:
 522     accept(TOKENIZER_GET_DISK_SIZE);
 523     r = GetTotalCardSpaceKb();
 524     break;
 525   case TOKENIZER_GET_FREE_DISK_SPACE:
 526     accept(TOKENIZER_GET_FREE_DISK_SPACE);
 527     r = GetFreeCardSpaceKb();
 528     break;
 529   case TOKENIZER_GET_JPG_COUNT:
 530     accept(TOKENIZER_GET_JPG_COUNT);
 531     r = GetJpgCount();
 532     break;
 533   case TOKENIZER_GET_VIDEO_BUTTON:
 534     accept(TOKENIZER_GET_VIDEO_BUTTON);
 535     r = (camera_info.cam_has_video_button) ? 1 : 0;
 536     break;
 537   case TOKENIZER_GET_VIDEO_RECORDING:
 538     accept(TOKENIZER_GET_VIDEO_RECORDING);
 539     r = is_video_recording();
 540     break;
 541   case TOKENIZER_GET_RAW_COUNT:
 542     accept(TOKENIZER_GET_RAW_COUNT);
 543     r = GetRawCount();
 544     break;
 545   case TOKENIZER_GET_PROP:
 546     accept(TOKENIZER_GET_PROP);
 547     int var = expr();
 548     r = shooting_get_prop(var);
 549     break;
 550   case TOKENIZER_GET_HISTO_RANGE:
 551     accept(TOKENIZER_GET_HISTO_RANGE);
 552     int from = expr();
 553     int to = expr();
 554 #ifdef UBASIC_TEST
 555     (void)from; (void)to;
 556     r = 0;
 557 #else
 558     r = (unsigned short)libshothisto->shot_histogram_get_range(from, to);
 559 #endif
 560     break;
 561   case TOKENIZER_GET_TEMPERATURE:
 562     accept(TOKENIZER_GET_TEMPERATURE);
 563     int temp = expr();
 564     switch (temp)
 565     {
 566     case 0:
 567       r = get_optical_temp(); 
 568       break;
 569     case 1:
 570       r = get_ccd_temp(); 
 571       break;
 572     case 2:
 573       r = get_battery_temp();
 574       break;
 575     default: // do something sane if given a bad index
 576       r = 0;
 577     }
 578     break;
 579   case TOKENIZER_GET_TIME:
 580       accept(TOKENIZER_GET_TIME);
 581       int tmode = expr();
 582       static struct tm *ttm;
 583       ttm = get_localtime();
 584       if (tmode==0) r = ttm->tm_sec;
 585       else if (tmode==1) r = ttm->tm_min;
 586       else if (tmode==2) r = ttm->tm_hour;
 587       else if (tmode==3) r = ttm->tm_mday;
 588       else if (tmode==4) r = ttm->tm_mon+1;
 589       else if (tmode==5) r = 1900+ttm->tm_year;
 590       break;
 591  case TOKENIZER_GET_RAW:
 592     accept(TOKENIZER_GET_RAW);
 593 #ifdef UBASIC_TEST
 594     r = 1;
 595 #else
 596     r = conf.save_raw;
 597 #endif    
 598     break;
 599   // get canon raw / jpeg setting
 600   case TOKENIZER_GET_CANON_IMAGE_FORMAT:
 601     accept(TOKENIZER_GET_CANON_IMAGE_FORMAT);
 602     r = shooting_get_canon_image_format();
 603     break;
 604   // get whether canon firmware supports raw
 605   case TOKENIZER_GET_CANON_RAW_SUPPORT:
 606     accept(TOKENIZER_GET_CANON_RAW_SUPPORT);
 607     r = camera_info.cam_canon_raw;
 608     break;
 609   // get CHDK capture mode value, or 0 if in playback or unknown (broken modemap)
 610   // NOTE: different from get_mode, since this returns the actual value
 611   case TOKENIZER_GET_CAPTURE_MODE:
 612     accept(TOKENIZER_GET_CAPTURE_MODE);
 613     if (camera_info.state.mode_rec) 
 614       r = camera_info.state.mode_shooting;
 615     else
 616       r = 0;
 617     break;
 618   // check if CHDK capture mode exists in modemap of this camera
 619   case TOKENIZER_IS_CAPTURE_MODE_VALID:
 620     accept(TOKENIZER_IS_CAPTURE_MODE_VALID);
 621     int modenum = expr();
 622     if (shooting_mode_chdk2canon(modenum) == -1)
 623       r = 0;
 624     else
 625       r = 1;
 626     break;
 627   case TOKENIZER_GET_FOCAL_LENGTH:
 628     accept(TOKENIZER_GET_FOCAL_LENGTH);
 629     r = get_focal_length(lens_get_zoom_point());
 630     break;
 631   case TOKENIZER_GET_MIN_STACK_DIST:
 632     accept(TOKENIZER_GET_MIN_STACK_DIST);
 633     r = shooting_get_min_stack_distance();
 634     break;
 635   case TOKENIZER_GET_CONFIG_VALUE:
 636     accept(TOKENIZER_GET_CONFIG_VALUE);
 637     int var1 = expr();
 638     int var2 = expr();
 639     if( conf_getValue(var1, &configVal) == CONF_VALUE) r = configVal.numb; else r = var2;
 640     break;
 641   case TOKENIZER_SWAP_PARTITIONS:
 642     accept(TOKENIZER_SWAP_PARTITIONS);
 643     int partNr = expr();
 644     r = swap_partitions(partNr);
 645     break;
 646 
 647   // APEX functions
 648   case TOKENIZER_ISO_TO_SV96:
 649     accept(TOKENIZER_ISO_TO_SV96);
 650     r = shooting_get_sv96_from_iso(expr());
 651     break;
 652   case TOKENIZER_SV96_TO_ISO:
 653     accept(TOKENIZER_SV96_TO_ISO);
 654     r = shooting_get_iso_from_sv96(expr());
 655     break;
 656   case TOKENIZER_ISO_REAL_TO_MARKET:
 657     accept(TOKENIZER_ISO_REAL_TO_MARKET);
 658     r = shooting_iso_real_to_market(expr());
 659     break;
 660   case TOKENIZER_ISO_MARKET_TO_REAL:
 661     accept(TOKENIZER_ISO_MARKET_TO_REAL);
 662     r = shooting_iso_market_to_real(expr());
 663     break;
 664   case TOKENIZER_SV96_REAL_TO_MARKET:
 665     accept(TOKENIZER_SV96_REAL_TO_MARKET);
 666     r = shooting_sv96_real_to_market(expr());
 667     break;
 668   case TOKENIZER_SV96_MARKET_TO_REAL:
 669     accept(TOKENIZER_SV96_MARKET_TO_REAL);
 670     r = shooting_sv96_market_to_real(expr());
 671     break;
 672   case TOKENIZER_APERTURE_TO_AV96:
 673     accept(TOKENIZER_APERTURE_TO_AV96);
 674     r = shooting_get_av96_from_aperture(expr());
 675     break;
 676   case TOKENIZER_AV96_TO_APERTURE:
 677     accept(TOKENIZER_AV96_TO_APERTURE);
 678     r = shooting_get_aperture_from_av96(expr());
 679     break;
 680   case TOKENIZER_USEC_TO_TV96:
 681     accept(TOKENIZER_USEC_TO_TV96);
 682     r = shooting_get_tv96_from_shutter_speed((float)expr()/1000000.0);
 683     break;
 684   case TOKENIZER_TV96_TO_USEC:
 685     accept(TOKENIZER_TV96_TO_USEC);
 686     r = (int)(shooting_get_shutter_speed_from_tv96(expr()) * 1000000.0 + 0.5);
 687     break;
 688   case TOKENIZER_SECONDS_TO_TV96:
 689     accept(TOKENIZER_SECONDS_TO_TV96);
 690     int n = expr();
 691     int d = expr();
 692     r = shooting_get_tv96_from_shutter_speed((float)n/(float)d);
 693     break;
 694   case TOKENIZER_GET_DRAW_TITLE_LINE:    
 695     accept(TOKENIZER_GET_DRAW_TITLE_LINE);  
 696     r = camera_info.state.osd_title_line ;
 697     break;
 698   case TOKENIZER_FORCE_USB_PRESENT:
 699     accept(TOKENIZER_FORCE_USB_PRESENT);
 700     r=force_usb_state(expr()) ;
 701     break;
 702   case TOKENIZER_FORCE_ANALOG_AV:
 703     accept(TOKENIZER_FORCE_ANALOG_AV);
 704     r=kbd_force_analog_av(expr()) ;
 705     break;
 706   case TOKENIZER_GET_ALT_MODE:
 707     accept(TOKENIZER_GET_ALT_MODE);
 708     r = (camera_info.state.gui_mode != 0);
 709     break;    
 710   case TOKENIZER_GET_RAW_SUPPORT:
 711     accept(TOKENIZER_GET_RAW_SUPPORT);
 712     r = (is_raw_possible() && !camera_info.state.mode_play);
 713     break;    
 714   case TOKENIZER_GET_CURRENT_AV96:
 715     accept(TOKENIZER_GET_CURRENT_AV96);
 716     r = shooting_get_current_av96();
 717     break;
 718   case TOKENIZER_GET_CURRENT_TV96:
 719     accept(TOKENIZER_GET_CURRENT_TV96);
 720     r = shooting_get_current_tv96();
 721     break;
 722   case TOKENIZER_GET_CURRENT_DELTA_SV96:
 723     accept(TOKENIZER_GET_CURRENT_DELTA_SV96);
 724     r = shooting_get_current_delta_sv96();
 725     break;
 726   case TOKENIZER_GET_CURRENT_BASE_SV96:
 727     accept(TOKENIZER_GET_CURRENT_BASE_SV96);
 728     r = shooting_get_current_base_sv96();
 729     break;
 730   case TOKENIZER_GET_IMAGER_ACTIVE:
 731     accept(TOKENIZER_GET_IMAGER_ACTIVE);
 732     r = shooting_get_imager_active();
 733     break;
 734   case TOKENIZER_GET_MAX_AV96:
 735     accept(TOKENIZER_GET_MAX_AV96);
 736     r = shooting_get_max_av96(); // NOTE -1 if not available, i.e. playback
 737     break;
 738   case TOKENIZER_GET_MIN_AV96:
 739     accept(TOKENIZER_GET_MIN_AV96);
 740     r = shooting_get_min_av96(); // NOTE -1 if not available, i.e. playback
 741     break;
 742   case TOKENIZER_GET_ND_VALUE_EV96:
 743     accept(TOKENIZER_GET_ND_VALUE_EV96);
 744     r = shooting_get_nd_value_ev96();
 745     break;
 746   case TOKENIZER_GET_ND_CURRENT_EV96:
 747     accept(TOKENIZER_GET_ND_CURRENT_EV96);
 748     r = shooting_get_nd_current_ev96();
 749     break;
 750   case TOKENIZER_GET_DIGIC:
 751     accept(TOKENIZER_GET_DIGIC);
 752     r = camera_info.cam_digic;
 753     break;
 754   //ARM Begin
 755       
 756   default:
 757     r = varfactor();
 758     break;
 759   }
 760   return r;
 761 }
 762 /*---------------------------------------------------------------------------*/
 763 static int
 764 term(void)
 765 {
 766   int f1, f2;
 767   int op;
 768 
 769   f1 = factor();
 770   op = tokenizer_token();
 771   DEBUG_PRINTF("term: token %d\n", op);
 772   while(op == TOKENIZER_ASTR ||
 773         op == TOKENIZER_SLASH ||
 774         op == TOKENIZER_LT ||
 775         op == TOKENIZER_GT ||
 776         op == TOKENIZER_GE ||
 777         op == TOKENIZER_LE ||
 778         op == TOKENIZER_NE ||
 779         op == TOKENIZER_EQ ||
 780         op == TOKENIZER_XOR || 
 781         op == TOKENIZER_OR ||
 782         op == TOKENIZER_MOD) {
 783     tokenizer_next();
 784     f2 = factor();
 785     DEBUG_PRINTF("term: %d %d %d\n", f1, op, f2);
 786     switch(op) {
 787     case TOKENIZER_ASTR:
 788       f1 = f1 * f2;
 789       break;
 790     case TOKENIZER_SLASH:
 791       f1 = f1 / f2;
 792       break;
 793     case TOKENIZER_MOD:
 794       f1 = f1 % f2;
 795       break;
 796     case TOKENIZER_LT:
 797       f1 = f1 < f2;
 798       break;
 799     case TOKENIZER_GT:
 800       f1 = f1 > f2;
 801       break;
 802     case TOKENIZER_EQ:
 803       f1 = f1 == f2;
 804       break;
 805     case TOKENIZER_NE:
 806       f1 = f1 != f2;
 807       break;
 808     case TOKENIZER_LE:
 809       f1 = f1 <= f2;
 810       break;
 811     case TOKENIZER_GE:
 812       f1 = f1 >= f2;
 813       break;
 814     case TOKENIZER_OR:
 815       f1 = f1 | f2;
 816       break;
 817     case TOKENIZER_XOR:
 818       f1 = f1 ^ f2;
 819       break;
 820     }
 821     op = tokenizer_token();
 822   }
 823   DEBUG_PRINTF("term: %d\n", f1);
 824   return f1;
 825 }
 826 /*---------------------------------------------------------------------------*/
 827 static int
 828 expr(void)
 829 {
 830   int t1, t2;
 831   int op;
 832   
 833   t1 = term();
 834   op = tokenizer_token();
 835   DEBUG_PRINTF("expr: token %d\n", op);
 836   while(op == TOKENIZER_PLUS ||
 837         op == TOKENIZER_MINUS ||
 838         op == TOKENIZER_AND ||
 839         op == TOKENIZER_LOR ||
 840         op == TOKENIZER_XOR) {
 841     tokenizer_next();
 842     t2 = term();
 843     DEBUG_PRINTF("expr: %d %d %d\n", t1, op, t2);
 844     switch(op) {
 845     case TOKENIZER_PLUS:
 846       t1 = t1 + t2;
 847       break;
 848     case TOKENIZER_MINUS:
 849       t1 = t1 - t2;
 850       break;
 851     case TOKENIZER_AND:
 852       t1 = t1 & t2;
 853       break;
 854     case TOKENIZER_LOR:
 855       t1 = t1 || t2;
 856       break;
 857     }
 858     op = tokenizer_token();
 859   }
 860   DEBUG_PRINTF("expr: %d\n", t1);
 861   return t1;
 862 }
 863 /*---------------------------------------------------------------------------*/
 864 static int
 865 relation(void)
 866 {
 867   int r1, r2;
 868   int op;
 869   
 870   r1 = expr();
 871   op = tokenizer_token();
 872   DEBUG_PRINTF("relation: token %d\n", op);
 873   while(op == TOKENIZER_LAND) {
 874     tokenizer_next();
 875     r2 = expr();
 876     DEBUG_PRINTF("relation: %d %d %d\n", r1, op, r2);
 877     switch(op) {
 878     case TOKENIZER_LAND:
 879       r1 = r1 && r2;
 880       break;
 881     }
 882     op = tokenizer_token();
 883   }
 884   return r1;
 885 }
 886 
 887 #if 0
 888 /*---------------------------------------------------------------------------*/
 889 static void
 890 jump_linenum(int linenum)
 891 {
 892   tokenizer_init(program_ptr);
 893   while(tokenizer_num() != linenum) {
 894     do {
 895       do {
 896         tokenizer_next();
 897       } while(tokenizer_token() != TOKENIZER_CR &&
 898               tokenizer_token() != TOKENIZER_ENDOFINPUT);
 899       if(tokenizer_token() == TOKENIZER_CR) {
 900         tokenizer_next();
 901       }
 902     } while(tokenizer_token() != TOKENIZER_NUMBER);
 903     DEBUG_PRINTF("jump_linenum: Found line %d\n", tokenizer_num());
 904   }
 905 }
 906 #endif
 907 
 908 /*---------------------------------------------------------------------------*/
 909 static void
 910 jump_line(int linenum)
 911 {
 912   tokenizer_init(program_ptr);
 913   while(tokenizer_line_number() != linenum) {
 914     tokenizer_next();
 915   }
 916   /* swallow the CR that would be read next */
 917   accept(TOKENIZER_CR);
 918 
 919 }
 920 /*---------------------------------------------------------------------------*/
 921 // TODO: error handling?
 922 int
 923 jump_label(char * label)
 924 {
 925   char currLabel[MAX_STRINGLEN];
 926   tokenizer_init(program_ptr);
 927   currLabel[0] = 0;
 928   while(tokenizer_token() != TOKENIZER_ENDOFINPUT) {
 929     tokenizer_next();
 930     if (tokenizer_token() == TOKENIZER_LABEL) {
 931       tokenizer_label(currLabel, sizeof(currLabel));
 932       tokenizer_next();
 933       if(strcmp(label, currLabel) == 0) {
 934         accept(TOKENIZER_CR);
 935         DEBUG_PRINTF("jump_linenum: Found line %d\n", tokenizer_line_number());
 936         break;
 937       }
 938     }
 939   }
 940   if (tokenizer_token() == TOKENIZER_ENDOFINPUT) {
 941     if (camera_info.state.state_kbd_script_run == 1) {  
 942       DEBUG_PRINTF("Label %s not found", label);
 943       ubasic_error = UBASIC_E_UNK_LABEL;
 944     }
 945       return 0;
 946   } else {
 947       return 1;
 948   }
 949 }
 950 /*---------------------------------------------------------------------------*/
 951 static void
 952 goto_statement(void)
 953 {
 954   accept(TOKENIZER_GOTO);
 955   if(tokenizer_token() == TOKENIZER_STRING) {
 956     tokenizer_string(string, sizeof(string));
 957     tokenizer_next();
 958     jump_label(string);
 959   } else {
 960     DEBUG_PRINTF("ubasic.c: goto_statement(): no label specified\n");
 961     ended = 1;
 962     ubasic_error = UBASIC_E_UNK_LABEL;
 963   }
 964 }
 965 /*---------------------------------------------------------------------------*/
 966 static void
 967 print_statement(void)
 968 {
 969   static char buf[128];
 970 
 971   buf[0]=0;
 972   accept(TOKENIZER_PRINT);
 973   do {
 974     DEBUG_PRINTF("Print loop\n");
 975     if(tokenizer_token() == TOKENIZER_STRING) {
 976       tokenizer_string(string, sizeof(string));
 977       sprintf(buf+strlen(buf), "%s", string);
 978       tokenizer_next();
 979     } else if(tokenizer_token() == TOKENIZER_COMMA) {
 980       strcat(buf, " ");
 981       tokenizer_next();
 982     } else if(tokenizer_token() == TOKENIZER_SEMICOLON) {
 983       tokenizer_next();
 984     } else {
 985       sprintf(buf+strlen(buf), "%d", expr());
 986     }
 987   } while(tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ENDOFINPUT && tokenizer_token() != TOKENIZER_ELSE);
 988   script_console_add_line((long)buf);
 989   DEBUG_PRINTF("End of print\n");
 990   accept_cr();
 991 }
 992 /*---------------------------------------------------------------------------*/
 993 /* IF-STATEMENT                                                              */
 994 
 995 static void
 996 endif_statement(void)
 997 {
 998   if(if_stack_ptr > 0) {
 999     accept(TOKENIZER_ENDIF);
1000     accept(TOKENIZER_CR);
1001     if_stack_ptr--;
1002   } else {
1003     DEBUG_PRINTF("ubasic.c: endif_statement(): endif without if-statement\n");
1004     ended = 1;
1005     ubasic_error = UBASIC_E_UNMATCHED_IF;
1006   }
1007 }
1008 /*---------------------------------------------------------------------------*/
1009 static void
1010 if_statement(void)
1011 {
1012   int r, else_cntr,endif_cntr,f_nt,f_sl;
1013   
1014   accept(TOKENIZER_IF);
1015   DEBUG_PRINTF("if_statement: get_relation\n");
1016   r = relation();
1017   DEBUG_PRINTF("if_statement: relation %d\n", r);
1018   accept(TOKENIZER_THEN);
1019   if (ended) {
1020     return;
1021   }
1022 
1023   if (tokenizer_token() == TOKENIZER_CR) {
1024     // CR after then -> multiline IF-Statement
1025     if(if_stack_ptr < MAX_IF_STACK_DEPTH) {
1026       if_stack[if_stack_ptr] = r;
1027       if_stack_ptr++;
1028     } else {
1029       DEBUG_PRINTF("if_statement: IF-stack depth exceeded\n");
1030       ended = 1;
1031       ubasic_error = UBASIC_E_IF_STACK_EXHAUSTED;
1032       return;
1033     }
1034     DEBUG_PRINTF("if_statement: stack_ptr %d\n", if_stack_ptr);
1035     accept(TOKENIZER_CR);
1036     if(r) {
1037       DEBUG_PRINTF("if_statement: result true\n");
1038       return;
1039     }else {
1040       DEBUG_PRINTF("if_statement: result false\n");
1041 
1042       else_cntr=endif_cntr=0; // number of else/endif possible in current nesting
1043       f_nt=f_sl=0; // f_nt flag for additional next token, f_fs flag single line
1044 
1045       while(((tokenizer_token() != TOKENIZER_ELSE &&  tokenizer_token() != TOKENIZER_ENDIF)
1046            || else_cntr || endif_cntr) && tokenizer_token() != TOKENIZER_ENDOFINPUT){
1047         f_nt=0;
1048         // nested if
1049         if( tokenizer_token() == TOKENIZER_IF) {
1050           else_cntr+=1;
1051           endif_cntr+=1;
1052           f_sl=0;
1053           DEBUG_PRINTF("IF: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
1054         }
1055         if( tokenizer_token() == TOKENIZER_THEN) {
1056           f_nt=1;
1057           tokenizer_next();
1058           DEBUG_PRINTF("THEN: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
1059           if (tokenizer_token() != TOKENIZER_CR) { f_sl=1; }
1060           DEBUG_PRINTF("THEN_SL: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
1061         }
1062         if(tokenizer_token() == TOKENIZER_ELSE) {
1063           else_cntr--;
1064           DEBUG_PRINTF("ELSE: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
1065           if (else_cntr<0) { 
1066             DEBUG_PRINTF("ubasic.c: if_statement(): else without if-statement\n");
1067             ended = 1;
1068             ubasic_error = UBASIC_E_UNMATCHED_IF;
1069             return;
1070           }
1071         }
1072         if(!f_sl && (tokenizer_token() == TOKENIZER_ENDIF)) {
1073           endif_cntr--;
1074           if (endif_cntr != else_cntr) else_cntr--;
1075           DEBUG_PRINTF("ENDIF: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
1076         } else {
1077           if (f_sl && (tokenizer_token() == TOKENIZER_CR))  {
1078             f_sl=0;
1079             endif_cntr--;
1080             if (endif_cntr != else_cntr) else_cntr--;
1081             DEBUG_PRINTF("ENDIF_SL: line %d, token %d, else %d, end %d\n", tokenizer_line_number(),tokenizer_token(),else_cntr,endif_cntr);
1082           }else{
1083             if (tokenizer_token()==TOKENIZER_ENDIF){
1084               DEBUG_PRINTF("ubasic.c: if_statement(): endif in singleline if-statement\n");
1085               ended = 1;
1086               ubasic_error = UBASIC_E_PARSE;
1087               return;
1088             }
1089           }
1090         }
1091         if (!f_nt) { tokenizer_next(); }
1092       }
1093       if(tokenizer_token() == TOKENIZER_ELSE) { return; }
1094     }
1095     endif_statement();
1096   }else {
1097   // Singleline IF-Statement
1098     if(r) {
1099       statement();
1100     } else {
1101       do {
1102         tokenizer_next();
1103       } while(tokenizer_token() != TOKENIZER_ELSE &&
1104         tokenizer_token() != TOKENIZER_CR &&
1105         tokenizer_token() != TOKENIZER_ENDOFINPUT);
1106       if(tokenizer_token() == TOKENIZER_ELSE) {
1107         accept(TOKENIZER_ELSE);
1108         statement();
1109       } else {
1110         accept(TOKENIZER_CR);
1111       }
1112     }
1113   }
1114 }
1115 /*---------------------------------------------------------------------------*/
1116 static void
1117 else_statement(void)
1118 {
1119   int r=0, endif_cntr, f_nt;
1120   
1121   accept(TOKENIZER_ELSE);
1122   if(if_stack_ptr > 0) {
1123     r = if_stack[if_stack_ptr-1];
1124   }
1125   else{
1126     DEBUG_PRINTF("ubasic.c: else_statement(): else without if-statement\n");
1127     ended = 1;
1128     ubasic_error = UBASIC_E_PARSE;
1129     return;
1130   }
1131   DEBUG_PRINTF("else_statement: relation %d\n", r);
1132   
1133   if (tokenizer_token() == TOKENIZER_CR) {
1134           accept(TOKENIZER_CR);
1135           if(!r) {
1136       DEBUG_PRINTF("else_statement: result true\n");
1137       return;
1138     } else {
1139       DEBUG_PRINTF("else_statement: result false\n");
1140       endif_cntr=0;
1141       while(((tokenizer_token() != TOKENIZER_ENDIF )
1142            || endif_cntr) && tokenizer_token() != TOKENIZER_ENDOFINPUT){
1143         f_nt=0;
1144         if( tokenizer_token() == TOKENIZER_IF) {
1145           endif_cntr+=1;
1146         }
1147         if( tokenizer_token() == TOKENIZER_THEN) {
1148           tokenizer_next();
1149           // then followed by CR -> multi line
1150           if (tokenizer_token() == TOKENIZER_CR) {
1151             f_nt=1;
1152           } else { // single line
1153             endif_cntr--;
1154             while(tokenizer_token() != TOKENIZER_ENDIF && tokenizer_token() != TOKENIZER_CR
1155                  && tokenizer_token() != TOKENIZER_ENDOFINPUT){
1156               tokenizer_next();
1157             }
1158             if (tokenizer_token()==TOKENIZER_ENDIF){
1159               DEBUG_PRINTF("ubasic.c: else_statement(): endif in singleline if-statement\n");
1160               ended = 1;
1161               ubasic_error = UBASIC_E_PARSE;
1162               return;
1163             }
1164           }
1165         }
1166         if( tokenizer_token() == TOKENIZER_ENDIF)  { endif_cntr--; }
1167         if (!f_nt) { tokenizer_next(); }
1168       }
1169     }
1170     endif_statement();
1171   }else{
1172     DEBUG_PRINTF("ubasic.c: else_statement(): CR after ELSE expected\n");
1173     ended = 1;
1174     ubasic_error = UBASIC_E_PARSE;
1175   }
1176 }
1177 /*---------------------------------------------------------------------------*/
1178 
1179 /*---------------------------------------------------------------------------*/
1180 /* SELECT-STATEMENT                                                          */
1181 
1182 static void
1183 dec_select_stack(void)
1184 {
1185   if(select_stack_ptr > 0) {
1186       select_stack_ptr--;
1187   } else {
1188     DEBUG_PRINTF("select_statement: SELECT-Stack fail\n");
1189     ended = 1;
1190     ubasic_error = UBASIC_E_UNMATCHED_END_SELECT;
1191   }
1192 }
1193 /*---------------------------------------------------------------------------*/
1194 static void
1195 end_select_statement(void)
1196 {
1197   if(select_stack_ptr > 0) {
1198     accept(TOKENIZER_END_SELECT);
1199     accept(TOKENIZER_CR);
1200     dec_select_stack();
1201   } else {
1202     DEBUG_PRINTF("ubasic.c: end_select_statement(): end_select without select-statement\n");
1203     ended = 1;
1204     ubasic_error = UBASIC_E_UNMATCHED_END_SELECT;
1205   }
1206 }
1207 /*---------------------------------------------------------------------------*/
1208 static void
1209 case_statement(void)
1210 {
1211   int select_value, case_value_1, case_value_2, case_value_eq;
1212   short case_run, case_goto = 0, case_gosub = 0;
1213   int cur_ln, gosub_ln = 0;
1214   
1215   accept(TOKENIZER_CASE);
1216   if(select_stack_ptr > 0) {
1217     select_value = select_stack[select_stack_ptr - 1].select_value;
1218     case_run = select_stack[select_stack_ptr - 1].case_run;
1219   
1220     if (!case_run) {
1221       case_value_1 = expr();
1222       case_value_eq = (select_value == case_value_1);
1223       if (case_value_eq) { DEBUG_PRINTF("case_statement: case_value_eq %d, case_value %d\n", case_value_eq, case_value_1); }  
1224 
1225       if(tokenizer_token() == TOKENIZER_TO) {
1226         accept(TOKENIZER_TO);
1227         case_value_2 = expr();
1228         if (case_value_1 < case_value_2) {
1229           case_value_eq = ((select_value >= case_value_1) && (select_value <= case_value_2));
1230           DEBUG_PRINTF("case_statement: case_value %d to %d\n", case_value_1, case_value_2);
1231         } else {
1232           case_value_eq = ((select_value >= case_value_2) && (select_value <= case_value_1));
1233           DEBUG_PRINTF("case_statement: case_value %d to %d\n", case_value_2, case_value_1);
1234         }
1235       } else if (tokenizer_token() == TOKENIZER_COMMA) {
1236         do {
1237           accept(TOKENIZER_COMMA);
1238           if (case_value_eq) {
1239             case_value_2 = expr();
1240           } else {
1241             case_value_1 = expr();
1242             case_value_eq = (select_value == case_value_1);
1243           }
1244         } while (tokenizer_token() == TOKENIZER_COMMA);
1245         DEBUG_PRINTF("case_statement: case_value_eq %d, case_value_comma %d\n", case_value_eq, case_value_1);
1246       }
1247       
1248       accept(TOKENIZER_SEMICOLON);
1249       if (case_value_eq) {
1250         case_goto = (tokenizer_token() == TOKENIZER_GOTO);
1251         case_gosub = (tokenizer_token() == TOKENIZER_GOSUB);
1252 //GOSUB - save curr linenumber
1253         cur_ln = tokenizer_line_number();
1254 //GOSUB
1255         statement();
1256 //GOSUB  - save new linenumber, reset to curr linenumber
1257       if (case_gosub) { 
1258         gosub_ln = tokenizer_line_number();
1259         jump_line(cur_ln+1);
1260         DEBUG_PRINTF("case_statement: GOSUB: toLN=%d, nextLN=%d\n", gosub_ln, cur_ln+1);
1261       }
1262 //GOSUB
1263         DEBUG_PRINTF("case_statement: case execute\n");
1264         case_run = 1;
1265         select_stack[select_stack_ptr - 1].case_run = case_run;
1266       } else {
1267         DEBUG_PRINTF("case_statement: case jump; case_run: %d\n", case_run);
1268         accept_cr();
1269       }
1270     } else {accept_cr();}
1271 //REM
1272     while ((tokenizer_token() == TOKENIZER_REM) && (!case_goto)) {statement();}
1273 //REM
1274     if (case_goto) { dec_select_stack(); } else {
1275       if ((tokenizer_token() != TOKENIZER_CASE) && (tokenizer_token() != TOKENIZER_CASE_ELSE) && 
1276          (tokenizer_token() != TOKENIZER_END_SELECT)) {
1277          DEBUG_PRINTF("ubasic.c: select_statement(): don't found case, case_else or end_select\n");
1278          ended = 1;
1279          ubasic_error = UBASIC_E_PARSE;
1280       } else { 
1281 //GOSUB test for end_select and set to gosub-linenumber
1282         if (tokenizer_token() == TOKENIZER_END_SELECT) { end_select_statement(); }
1283         if (case_gosub) {
1284           gosub_stack[gosub_stack_ptr-1] = tokenizer_line_number();
1285           jump_line(gosub_ln);
1286           DEBUG_PRINTF("end_select_statement: GOSUB: returnLN=%d\n", gosub_stack[gosub_stack_ptr-1]);
1287         }
1288       }  
1289 //GOSUB        
1290     }
1291   } else {
1292     DEBUG_PRINTF("case_statement: SELECT-Stack fail\n");
1293     ended = 1;
1294     ubasic_error = UBASIC_E_UNMATCHED_END_SELECT;
1295   }
1296 }
1297 /*---------------------------------------------------------------------------*/
1298 static void
1299 case_else_statement(void)
1300 {
1301   short case_goto = 0, case_gosub = 0;
1302   int cur_ln, gosub_ln = 0;
1303   
1304   accept(TOKENIZER_CASE_ELSE);
1305   if(select_stack_ptr > 0) {
1306     if (!select_stack[select_stack_ptr - 1].case_run) {
1307       case_goto = (tokenizer_token() == TOKENIZER_GOTO); 
1308       case_gosub = (tokenizer_token() == TOKENIZER_GOSUB); 
1309 //GOSUB - save curr linenumber
1310       cur_ln = tokenizer_line_number();
1311 //GOSUB
1312       statement();
1313 //GOSUB  - save new linenumber, reset to curr linenumber
1314       if (case_gosub) { 
1315         gosub_ln = tokenizer_line_number();
1316         jump_line(cur_ln+1);
1317         DEBUG_PRINTF("case_else_statement: GOSUB: toLN=%d, nextLN=%d\n", gosub_ln, cur_ln+1);
1318       }
1319 //GOSUB
1320       DEBUG_PRINTF("case_else_statement: case_else execute\n");
1321     } else {
1322       DEBUG_PRINTF("case_else_statement: case_else jump; case_run: %d\n", select_stack[select_stack_ptr - 1].case_run);
1323       accept_cr();
1324     }
1325 //REM
1326     while ((tokenizer_token() == TOKENIZER_REM) && (!case_goto)) {statement();}
1327 //REM
1328     if (case_goto) { dec_select_stack(); } else { 
1329 //GOSUB test for end_select and set to gosub-linenumber
1330       if (tokenizer_token() != TOKENIZER_END_SELECT) {
1331         DEBUG_PRINTF("ubasic.c: select_statement(): don't found end_select\n");
1332         ended = 1;
1333         ubasic_error = UBASIC_E_PARSE;
1334       } else { 
1335           end_select_statement(); 
1336         if (case_gosub) {
1337           gosub_stack[gosub_stack_ptr-1] = tokenizer_line_number();
1338           jump_line(gosub_ln);
1339           DEBUG_PRINTF("end_select_statement: GOSUB: returnLN=%d\n", gosub_stack[gosub_stack_ptr-1]);
1340         }
1341       }  
1342 //GOSUB      
1343     }
1344   } else {
1345     DEBUG_PRINTF("case_else_statement: SELECT-Stack fault\n");
1346     ended = 1;
1347     ubasic_error = UBASIC_E_UNMATCHED_END_SELECT;
1348   }
1349 }
1350 /*---------------------------------------------------------------------------*/
1351 static void
1352 select_statement(void)
1353 {
1354  
1355   int select_value;
1356   
1357   accept(TOKENIZER_SELECT);
1358   select_value = expr();  
1359   accept(TOKENIZER_CR);
1360 //REM
1361     while (tokenizer_token() == TOKENIZER_REM) {statement();}
1362 //REM
1363   
1364   if(select_stack_ptr < MAX_SELECT_STACK_DEPTH) {
1365     select_stack[select_stack_ptr].select_value = select_value;
1366     select_stack[select_stack_ptr].case_run = 0;
1367     DEBUG_PRINTF("select_statement: new select, value %d\n",select_stack[select_stack_ptr].select_value);
1368     select_stack_ptr++;
1369     if (tokenizer_token() != TOKENIZER_CASE) {
1370       DEBUG_PRINTF("ubasic.c: select_statement(): don't found case-statement\n");
1371       ended = 1;
1372       ubasic_error = UBASIC_E_PARSE;
1373     }
1374     else { case_statement(); }
1375   } else {
1376     DEBUG_PRINTF("select_statement: SELECT-stack depth exceeded\n");
1377     ended = 1;
1378     ubasic_error = UBASIC_E_SELECT_STACK_EXHAUSTED;
1379   }
1380 }
1381 /* SELECT-STATEMENT END                                                      */
1382 /*---------------------------------------------------------------------------*/
1383 static void
1384 let_statement(void)
1385 {
1386  
1387   int var;
1388 
1389   var = tokenizer_variable_num();
1390 
1391   accept(TOKENIZER_VARIABLE);
1392   accept(TOKENIZER_EQ);
1393   ubasic_set_variable(var, expr());
1394   DEBUG_PRINTF("let_statement: assign %d to %d\n", variables[var], var);
1395   accept_cr();
1396 }
1397 /*---------------------------------------------------------------------------*/
1398 static void
1399 rem_statement(void)
1400 {
1401   accept(TOKENIZER_REM);
1402   DEBUG_PRINTF("rem_statement\n");
1403   accept(TOKENIZER_CR);
1404 }
1405 /*---------------------------------------------------------------------------*/
1406 static void
1407 cls_statement(void)
1408 {
1409   accept(TOKENIZER_CLS);
1410   console_clear();
1411   DEBUG_PRINTF("cls_statement\n");
1412   accept(TOKENIZER_CR);
1413 }
1414 /*---------------------------------------------------------------------------*/
1415 static void
1416 gosub_statement(void)
1417 {
1418   accept(TOKENIZER_GOSUB);
1419   if(tokenizer_token() == TOKENIZER_STRING) {
1420     tokenizer_string(string, sizeof(string));
1421     do {
1422     tokenizer_next();
1423     } while(tokenizer_token() != TOKENIZER_CR);
1424     accept(TOKENIZER_CR);
1425     if(gosub_stack_ptr < MAX_GOSUB_STACK_DEPTH) {
1426 /*    tokenizer_line_number_inc();*/
1427       gosub_stack[gosub_stack_ptr] = tokenizer_line_number();
1428       gosub_stack_ptr++;
1429       jump_label(string);
1430     } else {
1431       DEBUG_PRINTF("gosub_statement: gosub stack exhausted\n");
1432       ended = 1;
1433       ubasic_error = UBASIC_E_GOSUB_STACK_EXHAUSTED;
1434     }
1435   } else {
1436     DEBUG_PRINTF("ubasic.c: goto_statement(): no label specified\n");
1437     ended = 1;
1438     ubasic_error = UBASIC_E_UNK_LABEL;
1439   }
1440 }
1441 /*---------------------------------------------------------------------------*/
1442 static void
1443 return_statement(void)
1444 {
1445   accept(TOKENIZER_RETURN);
1446   if(gosub_stack_ptr > 0) {
1447     gosub_stack_ptr--;
1448     jump_line(gosub_stack[gosub_stack_ptr]);
1449   } else {
1450     DEBUG_PRINTF("return_statement: non-matching return\n");
1451     ended = 1;
1452     ubasic_error = UBASIC_E_UNMATCHED_RETURN;
1453   }
1454 }
1455 /*---------------------------------------------------------------------------*/
1456 static void
1457 next_statement(void)
1458 {
1459   int var, value;
1460   
1461   accept(TOKENIZER_NEXT);
1462   var = tokenizer_variable_num();
1463   accept(TOKENIZER_VARIABLE);
1464   if(for_stack_ptr > 0 &&
1465      var == for_stack[for_stack_ptr - 1].for_variable) {
1466     value = ubasic_get_variable(var) + for_stack[for_stack_ptr - 1].step;
1467     ubasic_set_variable(var, value);
1468     
1469     if(((for_stack[for_stack_ptr - 1].step > 0) && (value <= for_stack[for_stack_ptr - 1].to)) ||
1470        ((for_stack[for_stack_ptr - 1].step < 0) && (value >= for_stack[for_stack_ptr - 1].to)))
1471         jump_line(for_stack[for_stack_ptr - 1].line_after_for); 
1472     else {
1473       for_stack_ptr--;
1474       accept(TOKENIZER_CR);
1475     }
1476   } else {
1477     DEBUG_PRINTF("next_statement: non-matching next (expected %d, found %d)\n", for_stack[for_stack_ptr - 1].for_variable, var);
1478     ended = 1;
1479     ubasic_error = UBASIC_E_UNMATCHED_NEXT;
1480   }
1481 
1482 }
1483 /*---------------------------------------------------------------------------*/
1484 static void
1485 for_statement(void)
1486 {
1487   int for_variable, to, step;
1488   
1489   accept(TOKENIZER_FOR);
1490   for_variable = tokenizer_variable_num();
1491   accept(TOKENIZER_VARIABLE);
1492   accept(TOKENIZER_EQ);
1493   ubasic_set_variable(for_variable, expr());
1494   accept(TOKENIZER_TO);
1495   to = expr();                     
1496   step = 1;
1497   if (tokenizer_token() != TOKENIZER_CR) {
1498           accept(TOKENIZER_STEP);
1499           step = expr();         
1500   }
1501   accept(TOKENIZER_CR);
1502 
1503   if(for_stack_ptr < MAX_FOR_STACK_DEPTH) {
1504     for_stack[for_stack_ptr].line_after_for = tokenizer_line_number();
1505     for_stack[for_stack_ptr].for_variable = for_variable;
1506     for_stack[for_stack_ptr].to = to;
1507     for_stack[for_stack_ptr].step = step;
1508     DEBUG_PRINTF("for_statement: new for, var %d to %d\n",
1509                  for_stack[for_stack_ptr].for_variable,
1510                  for_stack[for_stack_ptr].to);
1511                  
1512     for_stack_ptr++;
1513   } else {
1514     DEBUG_PRINTF("for_statement: for stack depth exceeded\n");
1515     ended = 1;
1516     ubasic_error = UBASIC_E_FOR_STACK_EXHAUSTED;
1517   }
1518 }
1519 /*---------------------------------------------------------------------------*/
1520 static void
1521 do_statement(void)
1522 {
1523   accept(TOKENIZER_DO);
1524   accept(TOKENIZER_CR);
1525   if(do_stack_ptr < MAX_DO_STACK_DEPTH) {
1526      do_stack[do_stack_ptr] = tokenizer_line_number();
1527      do_stack_ptr++;
1528   } else {
1529     DEBUG_PRINTF("do_statement: do stack depth exceeded\n");
1530     ended = 1;
1531     ubasic_error = UBASIC_E_DO_STACK_EXHAUSTED;
1532   }
1533 }
1534 /*---------------------------------------------------------------------------*/
1535 static void
1536 until_statement(void)
1537 {
1538   int r;
1539   
1540   accept(TOKENIZER_UNTIL);
1541   r = relation();
1542   if(do_stack_ptr > 0) {
1543     if(!r) {
1544       jump_line(do_stack[do_stack_ptr-1]);
1545     } else {
1546       do_stack_ptr--;
1547           accept_cr();
1548     }
1549   } else {
1550     DEBUG_PRINTF("until_statement: unmatched until\n");
1551     ended = 1;
1552     ubasic_error = UBASIC_E_UNMATCHED_UNTIL;
1553   }
1554 }
1555 /*---------------------------------------------------------------------------*/
1556 static void
1557 while_statement(void)
1558 {
1559   int r, while_cntr;
1560   
1561   accept(TOKENIZER_WHILE);
1562   if(while_stack_ptr < MAX_WHILE_STACK_DEPTH) {
1563     if ((while_stack_ptr == 0)||((while_stack_ptr > 0) && (while_stack[while_stack_ptr-1] != tokenizer_line_number()))){
1564       while_stack[while_stack_ptr] = tokenizer_line_number();
1565       while_stack_ptr++;
1566     }
1567   } else {
1568     DEBUG_PRINTF("while_statement: while stack depth exceeded\n");
1569     ended = 1;
1570     ubasic_error = UBASIC_E_WHILE_STACK_EXHAUSTED;
1571     return;
1572   }
1573 
1574   r = relation();
1575   if(while_stack_ptr > 0) {
1576     if(!r) {
1577         while_cntr=0;
1578       while((tokenizer_token() != TOKENIZER_WEND  || while_cntr ) && 
1579               tokenizer_token() != TOKENIZER_ENDOFINPUT){   
1580               if (tokenizer_token() == TOKENIZER_WHILE) while_cntr+=1;
1581               if (tokenizer_token() == TOKENIZER_WEND) while_cntr-=1;           
1582               tokenizer_next();
1583             }  
1584       while_stack_ptr--;
1585     
1586       accept(TOKENIZER_WEND);
1587       accept(TOKENIZER_CR);     
1588     } else {
1589           accept_cr();        
1590     }
1591   } else {
1592     DEBUG_PRINTF("while_statement: unmatched wend\n");
1593     ended = 1;
1594     ubasic_error = UBASIC_E_UNMATCHED_WEND;
1595   }
1596 }
1597 /*---------------------------------------------------------------------------*/
1598 static void
1599 wend_statement(void)
1600 {
1601   accept(TOKENIZER_WEND);
1602   if(while_stack_ptr > 0) {
1603     jump_line(while_stack[while_stack_ptr-1]);
1604   } else {
1605     DEBUG_PRINTF("wend_statement: unmatched wend\n");
1606     ended = 1;
1607     ubasic_error = UBASIC_E_UNMATCHED_WEND;
1608   }
1609 }
1610 /*---------------------------------------------------------------------------*/
1611 static void
1612 end_statement(void)
1613 {
1614   accept(TOKENIZER_END);
1615   ended = 1;
1616 }
1617 /*---------------------------------------------------------------------------*/
1618 static void
1619 click_statement(void)
1620 {
1621   int k;
1622   accept(TOKENIZER_CLICK);
1623   k = ubasic_get_key_arg();
1624   if (k > 0) {
1625     action_push_click(k);
1626     flag_yield=1;
1627   }
1628 
1629   DEBUG_PRINTF("End of click\n");
1630   accept_cr();
1631 }
1632 /*---------------------------------------------------------------------------*/
1633 static void
1634 press_statement(void)
1635 {
1636   int k;
1637   accept(TOKENIZER_PRESS);
1638   k = ubasic_get_key_arg();
1639   if (k > 0) {
1640     action_push_press(k);
1641     flag_yield=1;
1642   }
1643   DEBUG_PRINTF("End of press\n");
1644   accept_cr();
1645 }
1646 /*---------------------------------------------------------------------------*/
1647 static void
1648 release_statement(void)
1649 {
1650   int k;
1651   accept(TOKENIZER_RELEASE);
1652   k = ubasic_get_key_arg();
1653   if (k > 0) {
1654     action_push_release(k);
1655     flag_yield=1;
1656   }
1657   DEBUG_PRINTF("End of release\n");
1658   accept_cr();
1659 }
1660 /*---------------------------------------------------------------------------*/
1661 
1662 // Process a sleep function from the stack
1663 static int action_stack_AS_UBASIC_SLEEP()
1664 {
1665     if (get_tick_count() >= action_top(2))
1666     {
1667         action_pop_func(1);
1668         return 1;
1669     }
1670     return 0;
1671 }
1672 
1673 static int sleep_delay(int delay)
1674 {
1675     /* delay of -1 signals indefinite (actually 1 day) delay */
1676     if (delay == -1)
1677         delay = 86400000;
1678 
1679     if (delay > 0)
1680         return delay + get_tick_count();
1681 
1682     return 0;
1683 }
1684 
1685 static void
1686 sleep_statement(void)
1687 {
1688     accept(TOKENIZER_SLEEP);
1689 
1690     int delay = sleep_delay(expr());
1691     if (delay > 0)
1692     {
1693         action_push(delay);
1694         action_push_func(action_stack_AS_UBASIC_SLEEP);
1695     }
1696 
1697     flag_yield=1;
1698     DEBUG_PRINTF("End of sleep\n");
1699     accept_cr();
1700 }
1701 /*---------------------------------------------------------------------------*/
1702 static void
1703 shoot_statement(void)
1704 {
1705   accept(TOKENIZER_SHOOT);
1706   ubasic_as_ret_var_num = -1;
1707   if (tokenizer_token() != TOKENIZER_CR)
1708   {
1709     ubasic_as_ret_var_num = tokenizer_variable_num();
1710     accept(TOKENIZER_VARIABLE);
1711   }
1712   action_push_shoot(1);
1713   flag_yield=1;
1714   DEBUG_PRINTF("End of shoot\n");
1715   accept_cr();
1716 }
1717 
1718 /*---------------------------------------------------------------------------*/
1719 static void set_console_layout(void)
1720 {
1721   int x1,y1,x2,y2;
1722   accept(TOKENIZER_SET_CONSOLE_LAYOUT);
1723   x1 = expr();
1724   y1 = expr();
1725   x2 = expr();
1726   y2 = expr();
1727   console_set_layout(x1,y1,x2,y2);
1728   accept_cr();  
1729 }
1730 /*---------------------------------------------------------------------------*/
1731 static void set_console_autoredraw(void)
1732 {
1733   accept(TOKENIZER_SET_CONSOLE_AUTOREDRAW);
1734   console_set_autoredraw(expr());
1735   accept_cr();  
1736 }
1737 /*---------------------------------------------------------------------------*/
1738 static void console_redraw_statement(void)
1739 {
1740   accept(TOKENIZER_CONSOLE_REDRAW);
1741   console_redraw();
1742     accept_cr();
1743 }
1744 
1745 static void set_yield_statement()
1746 {
1747     accept(TOKENIZER_SET_YIELD);
1748     int val = expr();
1749     yield_max_lines = val?val:YIELD_MAX_LINES_DEFAULT;
1750     val = expr();
1751     yield_max_ms = val?val:YIELD_MAX_MS_DEFAULT;
1752     accept_cr();
1753 }
1754 
1755 /*---------------------------------------------------------------------------*/
1756 
1757 #ifdef INCLUDE_OLD_GET__SYNTAX
1758 
1759 // Call 'func' to get a CHDK short value and store in named parameter
1760 static void get_short_var_statement(int token, short (*func)(void))
1761 {
1762     int var;
1763     accept(token);
1764     var = tokenizer_variable_num();
1765     accept(TOKENIZER_VARIABLE);
1766     ubasic_set_variable(var, func());
1767     accept_cr();
1768 }
1769 
1770 // Call 'func' to get a CHDK int value and store in named parameter
1771 static void get_int_var_statement(int token, int (*func)(void))
1772 {
1773     int var;
1774     accept(token);
1775     var = tokenizer_variable_num();
1776     accept(TOKENIZER_VARIABLE);
1777     ubasic_set_variable(var, func());
1778     accept_cr();
1779 }
1780 
1781 static void get_prop_statement()
1782 {
1783     int var, var1;
1784     accept(TOKENIZER_GET_PROP);
1785     var = expr();
1786     var1 = tokenizer_variable_num();
1787     accept(TOKENIZER_VARIABLE);
1788     ubasic_set_variable(var1, shooting_get_prop(var));
1789         
1790     accept_cr();
1791 }
1792 
1793 #endif
1794 
1795 // Call CHDK function 'func' with one int parameter
1796 static void one_int_param_function(int token, void (*func)(int))
1797 {
1798     accept(token);
1799     func(expr());
1800     accept_cr();
1801 }
1802 
1803 // Call CHDK function 'func' with one short parameter
1804 static void one_short_param_function(int token, void (*func)(short))
1805 {
1806     accept(token);
1807     func(expr());
1808     accept_cr();
1809 }
1810 
1811 // Call CHDK function 'func' with one int parameter plus a second value 'p2'
1812 // static void one_int_param_plus_const_function(int token, void (*func)(int,short), short p2)
1813 // {
1814 //     accept(token);
1815 //     func(expr(),p2);
1816 //     accept_cr();
1817 // }
1818 
1819 // Call CHDK function 'func' with one short parameter plus a second value 'p2'
1820 // static void one_short_param_plus_const_function(int token, void (*func)(short,short), short p2)
1821 // {
1822 //     accept(token);
1823 //     func(expr(),p2);
1824 //     accept_cr();
1825 // }
1826 
1827 /*---------------------------------------------------------------------------*/
1828 
1829 
1830 static void set_ev_statement()
1831         {
1832             int to;
1833             accept(TOKENIZER_SET_EV);
1834             to = expr();
1835                 shooting_set_prop(camera_info.props.ev_correction_1, to);
1836                 shooting_set_prop(camera_info.props.ev_correction_2, to);
1837             accept_cr();
1838         }
1839 
1840 static void set_movie_status_statement()
1841 {
1842     accept(TOKENIZER_SET_MOVIE_STATUS);
1843     set_movie_status(expr());
1844     accept_cr();
1845 }
1846 
1847 // Set the property 'prop' value from the next expression
1848 static void set_propcase_statement(int token, int prop)
1849 {
1850     accept(token);
1851         shooting_set_prop(prop, expr());
1852     accept_cr();
1853 }
1854 
1855 
1856 static void set_mf_statement()
1857 {
1858    accept(TOKENIZER_SET_MF);
1859    if (expr() > 0) DoMFLock();
1860    else UnlockMF();
1861    accept_cr();
1862 }
1863 
1864 static void set_focus_statement()
1865 {
1866     accept(TOKENIZER_SET_FOCUS);
1867     int sd = expr();
1868     // if sd override not available now, fail immediately without calling set_focus
1869     // to avoid unexpected results with SET_LATER
1870     if(shooting_can_focus()) {
1871         // NOTE duplicated in modules/luascript.c and lib/ubasic/ubasic.c
1872         // in AF lock or MF (canon or set by MF functions), set focus now
1873         if (shooting_get_prop(camera_info.props.af_lock) 
1874           || shooting_get_focus_mode()
1875           || camera_info.state.mode_video)  // TODO video needs to be investigated, carried over from old code
1876         {
1877           shooting_set_focus(sd, SET_NOW);
1878         }
1879         else
1880         {
1881           // in an AF mode, set later
1882           shooting_set_focus(sd, SET_LATER);
1883         }
1884     }
1885     accept_cr();
1886 }
1887 
1888 static void set_led_statement()
1889 {
1890     int to, to1, to2;
1891     accept(TOKENIZER_SET_LED);
1892     to = expr();
1893     to1 = expr();
1894         to2 = 200;
1895         if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
1896                 to2 = expr();
1897     }
1898         camera_set_led(to, to1, to2);
1899     accept_cr();
1900 }
1901 
1902 static void set_prop_statement()
1903 {
1904     int to, to1;
1905     accept(TOKENIZER_SET_PROP);
1906     to = expr();
1907     to1 = expr();
1908         shooting_set_prop(to, to1);
1909     accept_cr();
1910 }
1911 
1912 /*---------------------------------------------------------------------------*/
1913 
1914 static void set_autostart_statement()
1915 {
1916     int to;
1917     accept(TOKENIZER_SET_SCRIPT_AUTOSTART);
1918     to = expr();
1919 #ifndef UBASIC_TEST
1920         if (to >= 0 && to <= 3) conf.script_startup=to;
1921         conf_save();
1922 #endif
1923     accept_cr();
1924 }
1925 
1926 static void set_capture_mode_canon_statement()
1927 {
1928     int to;
1929     accept(TOKENIZER_SET_CAPTURE_MODE_CANON);
1930     to = expr();
1931     // if the value as negative, assume it is a mistakenly sign extended PROPCASE_SHOOTING_MODE value
1932     if( to < 0) 
1933         to &= 0xFFFF;
1934     shooting_set_mode_canon(to);
1935     accept_cr();
1936 }
1937 
1938 static void reboot_statement() {
1939     accept(TOKENIZER_REBOOT);
1940     if(tokenizer_token() == TOKENIZER_STRING) {
1941         tokenizer_string(string, sizeof(string));
1942         tokenizer_next();
1943             reboot(string);
1944     } else {
1945             reboot(NULL);
1946     }
1947 }
1948 
1949 static void set_config_value_statement()
1950 {
1951     int id, value;
1952     tConfigVal configVal = {0};
1953     
1954     accept(TOKENIZER_SET_CONFIG_VALUE);
1955     id = expr();
1956     value = expr();
1957     if( conf_getValue(id, &configVal) == CONF_VALUE ) {
1958         configVal.numb = value;
1959         configVal.isNumb = 1;
1960         conf_setValue(id, configVal);
1961     }
1962     accept_cr();
1963 }
1964 
1965 /*---------------------------------------------------------------------------*/
1966 
1967 // Wait for a button to be pressed and released (or the timeout to expire)
1968 static int action_stack_AS_UBASIC_WAIT_CLICK()
1969 {
1970     // Check key pressed or timeout
1971     if ((get_tick_count() >= action_top(2)) || camera_info.state.kbd_last_clicked)
1972     {
1973         // If timed out set key state to "no_key", otherwise key pressed so set last checked time
1974         if (!camera_info.state.kbd_last_clicked)
1975             camera_info.state.kbd_last_clicked=0xFFFF;
1976         else
1977             camera_info.state.kbd_last_checked_time = camera_info.state.kbd_last_clicked_time;
1978 
1979         action_pop_func(1);
1980         return 1;
1981     }
1982 
1983     return 0;
1984 }
1985 
1986 static void wait_click_statement()
1987 {
1988     accept(TOKENIZER_WAIT_CLICK);
1989 
1990     int delay = -1;
1991     if ((tokenizer_token() != TOKENIZER_CR) && (tokenizer_token() != TOKENIZER_ELSE))
1992     {
1993         delay = expr();
1994         if (delay == 0) delay = -1;
1995     }
1996     delay = sleep_delay(delay);
1997 
1998     accept_cr();
1999 
2000     // Reset 'clicked' key if it has not changed since last time
2001     if (camera_info.state.kbd_last_clicked_time <= camera_info.state.kbd_last_checked_time)
2002     {
2003         camera_info.state.kbd_last_clicked = 0;
2004     }
2005 
2006     // Set up for wait or click testing
2007     action_push(delay);
2008     action_push_func(action_stack_AS_UBASIC_WAIT_CLICK);
2009 
2010     // Check for short delay or key already pressed by calling action stack routine once now
2011     if (action_stack_AS_UBASIC_WAIT_CLICK() == 0)
2012     {
2013         flag_yield=1;
2014     }
2015 }
2016 
2017 static void is_key_statement(void)
2018 {
2019     int var;
2020     accept(TOKENIZER_IS_KEY);
2021     var = tokenizer_variable_num();
2022     accept(TOKENIZER_VARIABLE);
2023     ubasic_set_variable(var, script_key_is_clicked(ubasic_get_key_arg()));
2024     DEBUG_PRINTF("End of is_key\n");
2025     accept_cr();
2026 }
2027 
2028 static void set_exit_key_statement()
2029 {
2030     int k;
2031     accept(TOKENIZER_SET_EXIT_KEY);
2032     if(tokenizer_token() == TOKENIZER_STRING) 
2033     {
2034         tokenizer_string(string, sizeof(string));
2035         k = script_keyid_by_name(string);
2036         if (k <= 0)
2037         {
2038           ubasic_error = UBASIC_E_UNK_KEY;
2039           ended = 1 ;
2040         }
2041         else
2042         {
2043             script_set_terminate_key(k,string);
2044         }
2045     } 
2046     else 
2047     {
2048        DEBUG_PRINTF("ubasic.c: set_exit_key no key specified\n");
2049        ended = 1;
2050        ubasic_error = UBASIC_E_UNK_KEY;
2051     }
2052     accept_cr() ;
2053 }
2054 
2055 static void get_config_value_statement()
2056 {
2057     int var, var1, var2;
2058     tConfigVal configVal;
2059     accept(TOKENIZER_GET_CONFIG_VALUE);
2060     var = expr();
2061     var1 = expr();
2062     var2 = tokenizer_variable_num();
2063     accept(TOKENIZER_VARIABLE);
2064     if( conf_getValue(var, &configVal) == CONF_VALUE ) {
2065         ubasic_set_variable(var2, configVal.numb);
2066     } else {
2067         ubasic_set_variable(var2, var1);
2068     }
2069     accept_cr();
2070 }
2071 
2072 static void on_off_statement(int token, void (*on)(void), void (*off)(void))
2073 {
2074   accept(token);
2075   if (expr() > 0) on();
2076   else off();
2077   accept_cr();
2078 }
2079 
2080 
2081 static void shutdown_statement(void){
2082   accept(TOKENIZER_SHUT_DOWN);
2083   camera_shutdown_in_a_second();
2084   accept_cr();
2085 }
2086 
2087 static void uB_set_av96(int param){
2088   shooting_set_av96( param, shooting_in_progress()?SET_NOW:SET_LATER );
2089   return ;
2090 }
2091 
2092 static void uB_set_av96_direct(int param){
2093   shooting_set_av96_direct( param, shooting_in_progress()?SET_NOW:SET_LATER );
2094   return ;
2095 }
2096 
2097 static void uB_set_tv96(int param){
2098   shooting_set_tv96( param, shooting_in_progress()?SET_NOW:SET_LATER );
2099   return ;
2100 }
2101 
2102 static void uB_set_tv96_direct(int param){
2103   shooting_set_tv96_direct( param, shooting_in_progress()?SET_NOW:SET_LATER);
2104   return ;
2105 }
2106 
2107 static void uB_set_sv96(int param){
2108   shooting_set_sv96( param, shooting_in_progress()?SET_NOW:SET_LATER );
2109   return ;
2110 }
2111 
2112 static void uB_set_nd_filter_state(int param) {
2113    shooting_set_nd_filter_state( param, shooting_in_progress()?SET_NOW:SET_LATER );
2114   return ;
2115 }
2116 
2117 static void uB_set_iso_real(int param) {
2118   shooting_set_iso_real( param, shooting_in_progress()?SET_NOW:SET_LATER );
2119   return ;
2120 }
2121 
2122 /*---------------------------------------------------------------------------*/
2123 
2124 static void md_get_cell_diff_statement()
2125 {
2126     int var, col, row;
2127     accept(TOKENIZER_MD_GET_CELL_DIFF);
2128 
2129     col=expr();tokenizer_next();
2130 
2131     row=expr();tokenizer_next();
2132 
2133     var = tokenizer_variable_num();
2134     accept(TOKENIZER_VARIABLE);
2135     accept_cr();
2136 
2137 #ifdef UBASIC_TEST
2138     // TODO: add something here for ubasic_test
2139 #else
2140     ubasic_set_variable(var, libmotiondetect->md_get_cell_diff(col,row));
2141 #endif
2142 }
2143 
2144 static void md_get_cell_val_statement()
2145 {
2146     int var, col, row;
2147     accept(TOKENIZER_MD_GET_CELL_VAL);
2148 
2149     col=expr();tokenizer_next();
2150 
2151     row=expr();tokenizer_next();
2152 
2153     var = tokenizer_variable_num();
2154     accept(TOKENIZER_VARIABLE);
2155     accept_cr();
2156 
2157 #ifdef UBASIC_TEST
2158     // TODO: add something here for ubasic_test
2159 #else
2160     ubasic_set_variable(var, libmotiondetect->md_get_cell_val(col,row));
2161 #endif
2162 }
2163 
2164 static void md_detect_motion_statement()
2165 {
2166     int columns;
2167     int rows;
2168     int pixel_measure_mode;
2169     int detection_timeout;
2170     int measure_interval;
2171     int threshold;
2172     int draw_grid=0;
2173     int clipping_region_mode=0;
2174     int clipping_region_row1=0;
2175     int clipping_region_column1=0;
2176     int clipping_region_row2=0;
2177     int clipping_region_column2=0;
2178     int parameters=0;
2179     int pixels_step=1;
2180     int msecs_before_trigger=0;
2181 
2182     accept(TOKENIZER_MD_DETECT_MOTION);
2183 
2184     columns=expr();tokenizer_next();
2185 
2186     rows=expr();tokenizer_next();
2187 
2188     pixel_measure_mode=expr();tokenizer_next();
2189 
2190     detection_timeout=expr();tokenizer_next();
2191 
2192     measure_interval=expr();tokenizer_next();
2193 
2194     threshold=expr();tokenizer_next();
2195 
2196     draw_grid=expr();tokenizer_next();
2197 
2198     ubasic_as_ret_var_num = tokenizer_variable_num();
2199 
2200     accept(TOKENIZER_VARIABLE);
2201 
2202     if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE) {
2203         // eat COMA     
2204         //                      tokenizer_next();
2205     }
2206 
2207     if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE) {
2208         tokenizer_next();
2209         clipping_region_mode = expr();
2210     }
2211     if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
2212         tokenizer_next();
2213         clipping_region_column1 = expr();
2214     }
2215     if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
2216         tokenizer_next();
2217         clipping_region_row1 = expr();
2218     }
2219     if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
2220         tokenizer_next();
2221         clipping_region_column2 = expr();
2222     }
2223     if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
2224         tokenizer_next();
2225         clipping_region_row2 = expr();
2226     }
2227     if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
2228         tokenizer_next();
2229         parameters = expr();
2230     }
2231     if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
2232         tokenizer_next();
2233         pixels_step = expr();
2234     }
2235 
2236     if (tokenizer_token() != TOKENIZER_CR && tokenizer_token() != TOKENIZER_ELSE ) {
2237         tokenizer_next();
2238         msecs_before_trigger = expr();
2239     }
2240 
2241     accept_cr();
2242 
2243 #ifdef UBASIC_TEST
2244     // TODO: add something here for ubasic_test
2245 #else
2246     libmotiondetect->md_init_motion_detector(
2247         columns, rows, pixel_measure_mode, detection_timeout, 
2248         measure_interval, threshold, draw_grid,
2249         clipping_region_mode,
2250         clipping_region_column1, clipping_region_row1,
2251         clipping_region_column2, clipping_region_row2,
2252         parameters, pixels_step, msecs_before_trigger);
2253 #endif
2254 
2255     flag_yield=1;
2256 }
2257 
2258 /*---------------------------------------------------------------------------*/
2259 static int _shot_histogram_set(int enable)
2260 {
2261 #ifdef UBASIC_TEST
2262     return 0;
2263 #else
2264     return libshothisto->shot_histogram_set(enable);
2265 #endif
2266 }
2267 
2268 /*---------------------------------------------------------------------------*/
2269 
2270 static void
2271 statement(void)
2272 {
2273   ubasic_token token;
2274 
2275   token = tokenizer_token();
2276 
2277   switch(token) {
2278   // aelock
2279   case TOKENIZER_SET_AELOCK:
2280       on_off_statement(token, DoAELock, UnlockAE);
2281       break;
2282   // aflock
2283   case TOKENIZER_SET_AFLOCK:
2284       on_off_statement(token, DoAFLock, UnlockAF);
2285       break;
2286 
2287   case TOKENIZER_PRINT_SCREEN:
2288       one_int_param_function(token, script_print_screen_statement);
2289       break;
2290   case TOKENIZER_PRINT:
2291       print_statement();
2292       break;
2293 
2294   case TOKENIZER_SLEEP:
2295       sleep_statement();
2296       break;
2297   case TOKENIZER_CLICK:
2298       click_statement();
2299       break;
2300   case TOKENIZER_PRESS:
2301       press_statement();
2302       break;
2303   case TOKENIZER_RELEASE:
2304       release_statement();
2305       break;
2306   case TOKENIZER_SHOOT:
2307       shoot_statement();
2308       break;
2309   case TOKENIZER_SET_CONSOLE_LAYOUT:
2310       set_console_layout();
2311       break;
2312   case TOKENIZER_SET_CONSOLE_AUTOREDRAW:
2313       set_console_autoredraw();
2314       break;
2315   case TOKENIZER_CONSOLE_REDRAW:
2316       console_redraw_statement();
2317       break;
2318 #ifdef INCLUDE_OLD_GET__SYNTAX
2319   case TOKENIZER_GET_TV96:
2320       get_short_var_statement(token, shooting_get_tv96);
2321       break;
2322   case TOKENIZER_GET_USER_TV96:
2323       get_short_var_statement(token, shooting_get_user_tv96);
2324       break;
2325   case TOKENIZER_GET_USER_TV_ID:
2326       get_int_var_statement(token, shooting_get_user_tv_id);
2327       break;
2328   case TOKENIZER_GET_AV96:
2329       get_short_var_statement(token, shooting_get_av96);
2330       break;
2331   case TOKENIZER_GET_USER_AV96:
2332       get_short_var_statement(token, shooting_get_user_av96);
2333       break;
2334   case TOKENIZER_GET_USER_AV_ID:
2335       get_int_var_statement(token, shooting_get_user_av_id);
2336       break;
2337   case TOKENIZER_GET_ZOOM:
2338       get_int_var_statement(token, shooting_get_zoom);
2339       break;
2340   case TOKENIZER_GET_FOCUS:
2341       get_int_var_statement(token, shooting_get_subject_distance);
2342       break;
2343   case TOKENIZER_GET_NEAR_LIMIT:
2344       get_int_var_statement(token, shooting_get_near_limit_of_acceptable_sharpness);
2345       break;
2346   case TOKENIZER_GET_FAR_LIMIT:
2347       get_int_var_statement(token, shooting_get_far_limit_of_acceptable_sharpness);
2348       break;
2349   case TOKENIZER_GET_DOF:
2350       get_int_var_statement(token, shooting_get_depth_of_field);
2351       break;
2352   case TOKENIZER_GET_HYPERFOCAL_DIST:
2353       get_int_var_statement(token, shooting_get_hyperfocal_distance);
2354       break;
2355   case TOKENIZER_GET_ISO_MARKET:
2356       get_short_var_statement(token, shooting_get_iso_market);
2357       break;
2358   case TOKENIZER_GET_ISO_REAL:
2359       get_short_var_statement(token, shooting_get_iso_real);
2360       break;
2361   case TOKENIZER_GET_BV96:
2362       get_short_var_statement(token, shooting_get_bv96);
2363       break;
2364   case TOKENIZER_GET_SV96:
2365       get_short_var_statement(token, shooting_get_sv96_real);
2366       break;
2367   case TOKENIZER_GET_ISO_MODE:
2368       get_int_var_statement(token, shooting_get_iso_mode);
2369       break;
2370   case TOKENIZER_GET_VBATT:
2371       get_int_var_statement(token, (int (*)(void))stat_get_vbatt);
2372       break;
2373   case TOKENIZER_GET_DISK_SIZE:
2374       get_int_var_statement(token, (int (*)(void))GetTotalCardSpaceKb);
2375       break;
2376   case TOKENIZER_GET_FREE_DISK_SPACE:
2377       get_int_var_statement(token, (int (*)(void))GetFreeCardSpaceKb);
2378       break;
2379   case TOKENIZER_GET_JPG_COUNT:
2380       get_int_var_statement(token, (int (*)(void))GetJpgCount);
2381       break;
2382   case TOKENIZER_GET_RAW_COUNT:
2383       get_int_var_statement(token, (int (*)(void))GetRawCount);
2384       break;
2385   case TOKENIZER_GET_PROP:
2386       get_prop_statement();
2387       break;
2388 #endif
2389   case TOKENIZER_SET_TV96_DIRECT:
2390       one_int_param_function(token, uB_set_tv96_direct);
2391       break;
2392   case TOKENIZER_SET_TV96:
2393       one_int_param_function(token, uB_set_tv96);
2394       break;
2395   case TOKENIZER_PLAY_SOUND:
2396       one_int_param_function(token, (void (*)(int))play_sound);
2397       break;
2398   case TOKENIZER_SET_USER_TV96:
2399       one_short_param_function(token, shooting_set_user_tv96);
2400       break;
2401   case TOKENIZER_SET_USER_TV_BY_ID:
2402       one_int_param_function(token, shooting_set_user_tv_by_id);
2403       break;
2404   case TOKENIZER_SET_USER_TV_BY_ID_REL:
2405       one_int_param_function(token, shooting_set_user_tv_by_id_rel);
2406       break;
2407   case TOKENIZER_SET_AV96_DIRECT:
2408       one_int_param_function(token, uB_set_av96_direct );
2409       break;
2410   case TOKENIZER_SET_AV96:
2411       one_int_param_function(token, uB_set_av96 );
2412       break;
2413     
2414   case TOKENIZER_SET_USER_AV96:
2415       one_short_param_function(token, shooting_set_user_av96);
2416       break;
2417   case TOKENIZER_SET_USER_AV_BY_ID:
2418       one_int_param_function(token, shooting_set_user_av_by_id);
2419       break;
2420   case TOKENIZER_SET_USER_AV_BY_ID_REL:
2421       one_int_param_function(token, shooting_set_user_av_by_id_rel);
2422       break;
2423    
2424   case TOKENIZER_SET_ND_FILTER:
2425       one_int_param_function(token, uB_set_nd_filter_state );
2426       break;
2427   
2428   case TOKENIZER_SET_ZOOM:
2429       one_int_param_function(token, shooting_set_zoom);
2430       break;
2431   case TOKENIZER_SET_ZOOM_REL:
2432       one_int_param_function(token, shooting_set_zoom_rel);
2433       break;
2434   case TOKENIZER_SET_ZOOM_SPEED:
2435       one_int_param_function(token, shooting_set_zoom_speed);
2436       break;
2437   case TOKENIZER_SET_FOCUS:
2438       set_focus_statement();
2439       break;
2440   case TOKENIZER_SET_MF:
2441       set_mf_statement();
2442       break;
2443 
2444 /*
2445   case TOKENIZER_SET_ISO_MARKET:
2446       one_int_param_function(token, shooting_set_iso_market);
2447       break;
2448   case TOKENIZER_SET_ISO_DL_F_B:
2449       one_int_param_function(token, shooting_set_iso_real_delta_from_base);
2450       break;
2451 */  
2452   //ARM End
2453   
2454   case TOKENIZER_SET_ISO_REAL:
2455       one_int_param_function(token, uB_set_iso_real );
2456       break;
2457   case TOKENIZER_SET_SV96:
2458       one_int_param_function(token, uB_set_sv96 );
2459       break;
2460 
2461   case TOKENIZER_SET_ISO_MODE:
2462       one_int_param_function(token, shooting_set_iso_mode);
2463       break;
2464 
2465   case TOKENIZER_SET_PROP:
2466       set_prop_statement();
2467       break;
2468   case TOKENIZER_SET_LED:
2469       set_led_statement();
2470       break;
2471 
2472   case TOKENIZER_SET_EV:
2473      set_ev_statement();
2474      break;
2475 
2476   case TOKENIZER_SET_MOVIE_STATUS:
2477       set_movie_status_statement();
2478       break;
2479   case TOKENIZER_SET_RESOLUTION:
2480       set_propcase_statement(token, camera_info.props.resolution);
2481       break;
2482   case TOKENIZER_SET_QUALITY:
2483       set_propcase_statement(token, camera_info.props.quality);
2484       break;
2485 
2486   case TOKENIZER_WAIT_CLICK:
2487       wait_click_statement();
2488       break;
2489   case TOKENIZER_IS_KEY:
2490       is_key_statement();
2491       break;
2492   case TOKENIZER_SET_EXIT_KEY:
2493       set_exit_key_statement();
2494       break;
2495 
2496   case TOKENIZER_WHEEL_LEFT:
2497       accept(token);
2498       JogDial_CCW();
2499       accept_cr();
2500       break;
2501   case TOKENIZER_WHEEL_RIGHT:
2502       accept(token);
2503       JogDial_CW();
2504       accept_cr();
2505       break;
2506 
2507   case TOKENIZER_IF:
2508       if_statement();
2509       break;
2510   case TOKENIZER_ELSE:
2511       else_statement();
2512       break;
2513   case TOKENIZER_ENDIF:
2514       endif_statement();
2515       break;
2516   case TOKENIZER_SELECT:
2517       select_statement();
2518       break;
2519   case TOKENIZER_CASE:
2520       case_statement();
2521       break;
2522   case TOKENIZER_CASE_ELSE:
2523       case_else_statement();
2524       break;
2525   case TOKENIZER_GOTO:
2526       goto_statement();
2527       break;
2528   case TOKENIZER_GOSUB:
2529       gosub_statement();
2530       break;
2531   case TOKENIZER_RETURN:
2532       return_statement();
2533       break;
2534   case TOKENIZER_FOR:
2535       for_statement();
2536       break;
2537   case TOKENIZER_NEXT:
2538       next_statement();
2539       break;
2540   case TOKENIZER_DO:
2541       do_statement();
2542       break;
2543   case TOKENIZER_UNTIL:
2544       until_statement();
2545       break;
2546   case TOKENIZER_WHILE:
2547       while_statement();
2548       break;
2549   case TOKENIZER_WEND:
2550       wend_statement();
2551       break;
2552   case TOKENIZER_END:
2553       end_statement();
2554       break;
2555   case TOKENIZER_LET:
2556       accept(TOKENIZER_LET);
2557       /* Fall through. */
2558   case TOKENIZER_VARIABLE:
2559       let_statement();
2560       break;
2561   case TOKENIZER_REM:
2562       rem_statement();
2563       break;
2564   case TOKENIZER_CLS:
2565       cls_statement();
2566       break;
2567   case TOKENIZER_SET_RAW:
2568       accept(token);
2569       conf.save_raw = expr();
2570       accept_cr();
2571       break;
2572   case TOKENIZER_SET_RAW_NR:
2573       accept(token);
2574       conf.raw_nr = expr();
2575       accept_cr();
2576       break;
2577   case TOKENIZER_SET_SCRIPT_AUTOSTART:
2578       set_autostart_statement();
2579       break;
2580   case TOKENIZER_EXIT_ALT:
2581       accept(token);
2582       exit_alt();
2583       accept_cr();
2584       break;
2585   case TOKENIZER_ENTER_ALT:
2586       accept(token);
2587       enter_alt(1);
2588       accept_cr();
2589       break;      
2590   case TOKENIZER_SHUT_DOWN:
2591       shutdown_statement();
2592   case TOKENIZER_SET_BACKLIGHT:
2593       on_off_statement(token, TurnOnBackLight, TurnOffBackLight);
2594       break;
2595   case TOKENIZER_SET_LCDDISPLAY:
2596       on_off_statement(token, TurnOnDisplay, TurnOffDisplay);
2597       break;
2598   case TOKENIZER_SET_DRAW_TITLE_LINE:
2599       accept(token);
2600       camera_info.state.osd_title_line=expr()?1:0;
2601       accept_cr();
2602       break;
2603       
2604       // >> mx3 . motion detector
2605   case   TOKENIZER_MD_DETECT_MOTION:
2606       md_detect_motion_statement();
2607       break;
2608   case  TOKENIZER_MD_GET_CELL_DIFF:
2609       md_get_cell_diff_statement();
2610       break;
2611   case  TOKENIZER_MD_GET_CELL_VAL:
2612       md_get_cell_val_statement();
2613       break;
2614       // << mx3 . motion_detector
2615 
2616   case TOKENIZER_MD_AF_LED_CONTROL:
2617       accept(token);
2618       camera_info.perf.md_af_on_delay = expr();
2619       camera_info.perf.md_af_on_time = expr();
2620       if ((camera_info.perf.md_af_on_time > 0) && (camera_info.cam_af_led >= 0)) {
2621           camera_info.perf.md_af_tuning = 1;        // Enable MD testing with AF LED
2622           // clear previous values
2623           memset(&camera_info.perf.af_led,0,sizeof(camera_info.perf.af_led));
2624           camera_info.perf.af_led.min = 0xFFFFFFFF;
2625       } else {
2626           camera_info.perf.md_af_tuning = 0;        // Disable MD testing
2627       }
2628       accept_cr();
2629       break;
2630 
2631   case TOKENIZER_SHOT_HISTO_ENABLE:
2632       one_int_param_function(token, (void (*)(int))_shot_histogram_set);
2633       break;
2634 
2635   case TOKENIZER_SET_RECORD:
2636       one_int_param_function(token, shooting_set_playrec_mode);
2637       break;
2638 
2639   case TOKENIZER_SET_CANON_IMAGE_FORMAT:
2640       one_int_param_function(token, (void (*)(int))shooting_set_canon_image_format);
2641       break;
2642 
2643   case TOKENIZER_SET_CAPTURE_MODE:
2644       one_int_param_function(token, (void (*)(int))shooting_set_mode_chdk);
2645       break;
2646 
2647   case TOKENIZER_SET_CAPTURE_MODE_CANON:
2648       set_capture_mode_canon_statement();
2649       break;
2650 
2651   case TOKENIZER_REBOOT:
2652       reboot_statement();
2653       break;
2654 
2655   case TOKENIZER_GET_CONFIG_VALUE:
2656     get_config_value_statement();
2657     break;
2658 
2659   case TOKENIZER_SET_CONFIG_VALUE:
2660     set_config_value_statement();
2661     break;
2662   case TOKENIZER_SET_YIELD:
2663     set_yield_statement();
2664     break;
2665 
2666   case TOKENIZER_USB_SYNC_WAIT:
2667     accept(TOKENIZER_USB_SYNC_WAIT);
2668 #ifdef UBASIC_TEST
2669     // TODO: add something here for ubasic_test
2670 #else
2671     if (expr()) usb_sync_wait_flag = 1;
2672     else        usb_sync_wait_flag = 0;
2673 #endif
2674     accept_cr();
2675     break;
2676 
2677   case TOKENIZER_SET_REMOTE_TIMING:
2678     accept(TOKENIZER_SET_REMOTE_TIMING);
2679 #ifdef UBASIC_TEST
2680     // TODO: add something here for ubasic_test
2681 #else
2682     int hpenable= expr();
2683     if ( hpenable > 0) start_usb_HPtimer(hpenable);
2684     else stop_usb_HPtimer();
2685 #endif
2686     accept_cr();
2687     break;
2688 
2689   default:
2690       DEBUG_PRINTF("ubasic.c: statement(): not implemented %d\n", token);
2691       ended = 1;
2692       ubasic_error = UBASIC_E_UNK_STATEMENT;
2693   }
2694 }
2695 
2696 /*---------------------------------------------------------------------------*/
2697 static void
2698 line_statement(void)
2699 {
2700   /* line numbers have been removed */
2701   DEBUG_PRINTF("----------- Line number %d ---------\n", tokenizer_line_number());
2702   /*    current_linenum = tokenizer_num();*/
2703 #if 0
2704   if (tokenizer_token() == TOKENIZER_LABEL) {
2705 #ifdef DEBUG
2706       tokenizer_label(string, sizeof(string));
2707       DEBUG_PRINTF("line_statement: label: %s\n", string );
2708 #endif
2709       accept(TOKENIZER_LABEL);
2710       accept(TOKENIZER_CR);
2711       return;
2712   }
2713 #endif 
2714   /* reyalp - eat up to 100 labels or rems at a time so they don't cost 10ms each */
2715   int count = 100;
2716   do {
2717     int r=tokenizer_token();
2718     if ( r == TOKENIZER_LABEL ) {
2719       /* hit limit and we are on a label, return */
2720       if( count == 1 )
2721         return;
2722 #ifdef DEBUG
2723       tokenizer_label(string, sizeof(string));
2724       DEBUG_PRINTF("line_statement: label: %s\n", string );
2725 #endif
2726       accept(TOKENIZER_LABEL);
2727       accept(TOKENIZER_CR);
2728     }
2729     else if ( r == TOKENIZER_REM ) {
2730       rem_statement();
2731     }
2732     else {
2733       break;
2734     }
2735   } while(--count);
2736   statement();
2737   return;
2738 }
2739 /*---------------------------------------------------------------------------*/
2740 int ubasic_run(void)
2741 {
2742     unsigned start_tick = get_tick_count();
2743     unsigned lines = 0;
2744     flag_yield = 0;
2745 
2746     do
2747     {
2748         if ( ended || tokenizer_finished() )
2749         {
2750             DEBUG_PRINTF("uBASIC program finished\n");
2751             if (ubasic_error)
2752             {
2753                 // Generate error message
2754                 char buf[100];
2755                 const char *msg;
2756                 if (ubasic_error >= UBASIC_E_ENDMARK)
2757                 {
2758                     msg = ubasic_errstrings[UBASIC_E_UNKNOWN_ERROR];
2759                 }
2760                 else
2761                 {
2762                     msg = ubasic_errstrings[ubasic_error];
2763                 }
2764                 sprintf(buf, "uBASIC:%d %s ", ubasic_linenumber(), msg);
2765                 // Show error message
2766                 script_console_add_error((long)buf);
2767                 script_console_add_error(LANG_CONSOLE_TEXT_TERMINATED);
2768                 return SCRIPT_RUN_ERROR;
2769             }
2770             // Show 'Finished' message
2771             script_console_add_error(LANG_CONSOLE_TEXT_FINISHED);
2772             return SCRIPT_RUN_ENDED;
2773         }
2774 
2775         line_statement();
2776 
2777         // Return control to CHDK only if external processing required  
2778         if ( flag_yield )
2779             return SCRIPT_RUN_RUNNING;
2780 
2781         lines++;
2782     } while (lines < yield_max_lines && get_tick_count() - start_tick < yield_max_ms);
2783 
2784     return SCRIPT_RUN_RUNNING;
2785 }
2786 /*---------------------------------------------------------------------------*/
2787 void
2788 ubasic_set_variable(int varnum, int value)
2789 {
2790   if(varnum >= 0 && varnum < MAX_VARNUM) {
2791     variables[varnum] = value;
2792   }
2793 }
2794 /*---------------------------------------------------------------------------*/
2795 int
2796 ubasic_get_variable(int varnum)
2797 {
2798   if(varnum >= 0 && varnum < MAX_VARNUM) {
2799     return variables[varnum];
2800   }
2801   return 0;
2802 }
2803 /*---------------------------------------------------------------------------*/
2804 void
2805 ubasic_end() {
2806 }
2807 /*---------------------------------------------------------------------------*/
2808 
2809 // Save Action Stack 'return' value in selected variable
2810 void ubasic_set_as_ret(int md_ret)
2811 {
2812     if (ubasic_as_ret_var_num >= 0)
2813         ubasic_set_variable(ubasic_as_ret_var_num, md_ret);
2814 }

/* [<][>][^][v][top][bottom][index][help] */