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

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