root/lib/ubasic/tokenizer.c

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

DEFINITIONS

This source file includes following definitions.
  1. singlechar
  2. get_next_token
  3. tokenizer_init
  4. tokenizer_token
  5. tokenizer_next
  6. tokenizer_num
  7. tokenizer_string
  8. tokenizer_label
  9. tokenizer_error_print
  10. tokenizer_finished
  11. tokenizer_variable_num
  12. tokenizer_line_number

   1 /*
   2  * Copyright (c) 2006, Adam Dunkels
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  * 3. Neither the name of the author nor the names of its contributors
  14  *    may be used to endorse or promote products derived from this software
  15  *    without specific prior written permission.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  *
  29  */
  30 
  31 #if DEBUG
  32 #define DEBUG_PRINTF(...)  printf(__VA_ARGS__)
  33 #else
  34 #define DEBUG_PRINTF(...)
  35 #endif
  36 
  37 #include "stdlib.h"
  38 #include "stddef.h"
  39 #include "string.h"
  40 #include "ctype.h"
  41 #include "stdio.h"
  42 
  43 #include "tokenizer.h"
  44 
  45 static char const *ptr, *nextptr;
  46 
  47 #define MAX_NUMLEN 6
  48 
  49 struct keyword_token {
  50   const char *keyword;
  51   int token;
  52 };
  53 
  54 static ubasic_token current_token = TOKENIZER_ERROR;
  55 static int current_line = 0;
  56 
  57 static const struct keyword_token keywords[] = {
  58   {"<>",                                  TOKENIZER_NE},
  59   {"<=",                                  TOKENIZER_LE},
  60   {">=",                                  TOKENIZER_GE},
  61   {"<",                           TOKENIZER_LT},
  62   {">",                       TOKENIZER_GT},
  63   {"not",                     TOKENIZER_LNOT},
  64   {"or",                      TOKENIZER_LOR},
  65   {"and",                     TOKENIZER_LAND},
  66 
  67   {"let",                     TOKENIZER_LET},
  68   {"if",                      TOKENIZER_IF},
  69   {"then",                    TOKENIZER_THEN},
  70   {"else",                    TOKENIZER_ELSE},
  71   {"endif",                   TOKENIZER_ENDIF},
  72   {"select",                  TOKENIZER_SELECT},
  73   {"case_else",               TOKENIZER_CASE_ELSE},
  74   {"case",                    TOKENIZER_CASE},
  75   {"end_select",              TOKENIZER_END_SELECT},
  76   {"force_analog_av",         TOKENIZER_FORCE_ANALOG_AV}, // has to come before "for"
  77   {"for",                     TOKENIZER_FOR},
  78   {"to",                      TOKENIZER_TO},
  79   {"next",                    TOKENIZER_NEXT},
  80   {"step",                    TOKENIZER_STEP},
  81   {"do",                      TOKENIZER_DO},
  82   {"until",                   TOKENIZER_UNTIL},
  83   {"while",                   TOKENIZER_WHILE},
  84   {"wend",                    TOKENIZER_WEND},
  85   {"goto",                    TOKENIZER_GOTO},
  86   {"gosub",                   TOKENIZER_GOSUB},
  87   {"return",                  TOKENIZER_RETURN},
  88   {"rem",                     TOKENIZER_REM},
  89   {"cls",                     TOKENIZER_CLS},
  90   {"print_screen",            TOKENIZER_PRINT_SCREEN},
  91   {"print",                   TOKENIZER_PRINT},
  92   {"random",                  TOKENIZER_RANDOM},
  93   {"click",                   TOKENIZER_CLICK},
  94   {"playsound",               TOKENIZER_PLAY_SOUND},
  95   {"press",                   TOKENIZER_PRESS},
  96   {"release",                 TOKENIZER_RELEASE},
  97   //{"shot",                    TOKENIZER_SHOOT}, // for compatibility
  98   {"shoot",                   TOKENIZER_SHOOT},
  99   {"set_console_layout",      TOKENIZER_SET_CONSOLE_LAYOUT},
 100   {"set_console_autoredraw",  TOKENIZER_SET_CONSOLE_AUTOREDRAW},
 101   {"console_redraw",          TOKENIZER_CONSOLE_REDRAW},
 102   {"sleep",                   TOKENIZER_SLEEP},
 103 
 104   /* WARNING due to tokenizer limitation longest match must be first */
 105 // GET
 106   {"get_av96",                TOKENIZER_GET_AV96},
 107   {"get_av",                  TOKENIZER_GET_USER_AV_ID}, //FOR COMPATIBILITY
 108   {"get_bv96",                TOKENIZER_GET_BV96},
 109   {"get_canon_image_format",  TOKENIZER_GET_CANON_IMAGE_FORMAT},
 110   {"get_canon_raw_support",   TOKENIZER_GET_CANON_RAW_SUPPORT},
 111   {"get_capture_mode",        TOKENIZER_GET_CAPTURE_MODE},
 112   {"get_current_av96",        TOKENIZER_GET_CURRENT_AV96},
 113   {"get_current_tv96",        TOKENIZER_GET_CURRENT_TV96},
 114   {"get_current_base_sv96",   TOKENIZER_GET_CURRENT_BASE_SV96},
 115   {"get_current_delta_sv96",  TOKENIZER_GET_CURRENT_DELTA_SV96},
 116   {"get_digic",               TOKENIZER_GET_DIGIC},
 117   {"get_display_mode",        TOKENIZER_GET_DISPLAY_MODE},
 118   {"get_day_seconds",         TOKENIZER_GET_DAY_SECONDS},
 119   {"get_disk_size",           TOKENIZER_GET_DISK_SIZE},
 120   {"get_dof",                 TOKENIZER_GET_DOF},
 121   {"get_far_limit",           TOKENIZER_GET_FAR_LIMIT},
 122   {"get_free_disk_space",     TOKENIZER_GET_FREE_DISK_SPACE},
 123   {"get_focal_length",        TOKENIZER_GET_FOCAL_LENGTH},
 124   {"get_focus_mode",          TOKENIZER_GET_FOCUS_MODE},
 125   {"get_focus_ok",            TOKENIZER_GET_FOCUS_OK},
 126   {"get_focus_state",         TOKENIZER_GET_FOCUS_STATE},
 127   {"get_focus",               TOKENIZER_GET_FOCUS},
 128   {"get_sd_over_modes",       TOKENIZER_GET_SD_OVER_MODES},
 129   {"get_hyp_dist",            TOKENIZER_GET_HYPERFOCAL_DIST},
 130   {"get_imager_active",       TOKENIZER_GET_IMAGER_ACTIVE},
 131   {"get_iso_market",          TOKENIZER_GET_ISO_MARKET},
 132   {"get_iso_mode",            TOKENIZER_GET_ISO_MODE},
 133   {"get_iso_real",            TOKENIZER_GET_ISO_REAL},
 134   {"get_iso",                 TOKENIZER_GET_ISO_MODE}, //FOR COMPATIBILITY
 135   {"get_jpg_count",           TOKENIZER_GET_JPG_COUNT},
 136   {"get_max_av96",            TOKENIZER_GET_MAX_AV96},
 137   {"get_min_av96",            TOKENIZER_GET_MIN_AV96},
 138   {"get_min_stack_dist",      TOKENIZER_GET_MIN_STACK_DIST},
 139   {"get_movie_status",        TOKENIZER_GET_MOVIE_STATUS},
 140   {"get_mode",                            TOKENIZER_GET_MODE},  // Returns 0 in recordmode, 1 in playmode
 141   {"get_nd_value_ev96",           TOKENIZER_GET_ND_VALUE_EV96},
 142   {"get_nd_current_ev96",         TOKENIZER_GET_ND_CURRENT_EV96},
 143   {"get_near_limit",          TOKENIZER_GET_NEAR_LIMIT},
 144   {"get_platform_id",         TOKENIZER_GET_PLATFORM_ID},
 145   {"get_propset",             TOKENIZER_GET_PROPSET},
 146   {"get_prop",                TOKENIZER_GET_PROP},
 147   {"get_quality",             TOKENIZER_GET_QUALITY},
 148   {"get_raw_support",         TOKENIZER_GET_RAW_SUPPORT},
 149   {"get_raw_count",           TOKENIZER_GET_RAW_COUNT},
 150   {"get_raw_nr",              TOKENIZER_GET_RAW_NR},
 151   {"get_raw",                 TOKENIZER_GET_RAW},
 152   {"get_resolution",          TOKENIZER_GET_RESOLUTION},
 153   {"get_sv96",                TOKENIZER_GET_SV96},
 154   {"get_temperature",         TOKENIZER_GET_TEMPERATURE},
 155   {"get_tick_count",          TOKENIZER_GET_TICK_COUNT},
 156   {"get_time",                    TOKENIZER_GET_TIME},
 157   {"get_tv96",                TOKENIZER_GET_TV96},
 158   {"get_user_av_id",          TOKENIZER_GET_USER_AV_ID},
 159   {"get_user_av96",           TOKENIZER_GET_USER_AV96},
 160   {"get_user_tv_id",          TOKENIZER_GET_USER_TV_ID},
 161   {"get_user_tv96",           TOKENIZER_GET_USER_TV96},
 162   {"get_video_recording",     TOKENIZER_GET_VIDEO_RECORDING},
 163   {"get_video_button",        TOKENIZER_GET_VIDEO_BUTTON},
 164   {"get_vbatt",               TOKENIZER_GET_VBATT},
 165   {"get_zoom_steps",          TOKENIZER_GET_ZOOM_STEPS},
 166   {"get_zoom",                TOKENIZER_GET_ZOOM},
 167   {"get_exp_count",           TOKENIZER_GET_EXP_COUNT},
 168   {"get_config_value",        TOKENIZER_GET_CONFIG_VALUE},
 169   {"swap_partitions",         TOKENIZER_SWAP_PARTITIONS},
 170 //SET
 171   {"set_av96_direct",         TOKENIZER_SET_AV96_DIRECT},
 172   {"set_av_rel",              TOKENIZER_SET_USER_AV_BY_ID_REL}, //FOR COMPATIBILITY
 173   {"set_av96",                TOKENIZER_SET_AV96},
 174   {"set_av",                  TOKENIZER_SET_USER_AV_BY_ID}, //FOR COMPATIBILITY
 175   {"set_canon_image_format",  TOKENIZER_SET_CANON_IMAGE_FORMAT},
 176   {"set_capture_mode_canon",  TOKENIZER_SET_CAPTURE_MODE_CANON},
 177   {"set_capture_mode",        TOKENIZER_SET_CAPTURE_MODE},
 178   {"set_backlight",           TOKENIZER_SET_BACKLIGHT},
 179   {"set_lcd_display",         TOKENIZER_SET_LCDDISPLAY},
 180   {"set_draw_title_line",     TOKENIZER_SET_DRAW_TITLE_LINE},
 181   {"get_draw_title_line",     TOKENIZER_GET_DRAW_TITLE_LINE},
 182   {"set_focus",               TOKENIZER_SET_FOCUS},
 183   {"set_iso_mode",            TOKENIZER_SET_ISO_MODE},
 184   {"set_iso_real",            TOKENIZER_SET_ISO_REAL},
 185   {"set_iso",                 TOKENIZER_SET_ISO_MODE}, //FOR COMPATIBILITY
 186   {"set_led",                 TOKENIZER_SET_LED},
 187   {"set_movie_status",        TOKENIZER_SET_MOVIE_STATUS},
 188   {"set_nd_filter",           TOKENIZER_SET_ND_FILTER},
 189   {"set_prop",                TOKENIZER_SET_PROP},
 190   {"set_quality",             TOKENIZER_SET_QUALITY},
 191   {"set_raw_nr",              TOKENIZER_SET_RAW_NR},
 192   {"set_raw",                 TOKENIZER_SET_RAW},
 193   {"set_resolution",          TOKENIZER_SET_RESOLUTION},
 194   {"set_remote_timing",       TOKENIZER_SET_REMOTE_TIMING},
 195   {"set_sv96",                    TOKENIZER_SET_SV96},
 196   {"set_tv96_direct",         TOKENIZER_SET_TV96_DIRECT},
 197   {"set_tv_rel",              TOKENIZER_SET_USER_TV_BY_ID_REL}, //FOR COMPATIBILITY
 198   {"set_tv96",                TOKENIZER_SET_TV96},
 199   {"set_tv",                  TOKENIZER_SET_USER_TV_BY_ID}, //FOR COMPATIBILITY
 200   {"set_user_av_by_id_rel",   TOKENIZER_SET_USER_AV_BY_ID_REL},
 201   {"set_user_av_by_id",       TOKENIZER_SET_USER_AV_BY_ID},
 202   {"set_user_av96",           TOKENIZER_SET_USER_AV96},
 203   {"set_user_tv_by_id_rel",   TOKENIZER_SET_USER_TV_BY_ID_REL},
 204   {"set_user_tv_by_id",       TOKENIZER_SET_USER_TV_BY_ID},
 205   {"set_user_tv96",           TOKENIZER_SET_USER_TV96},
 206   {"set_zoom_speed",          TOKENIZER_SET_ZOOM_SPEED},
 207   {"set_zoom_rel",            TOKENIZER_SET_ZOOM_REL},
 208   {"set_zoom",                TOKENIZER_SET_ZOOM},
 209   {"set_record",              TOKENIZER_SET_RECORD},
 210   {"set_config_value",        TOKENIZER_SET_CONFIG_VALUE},
 211   {"set_yield",               TOKENIZER_SET_YIELD},
 212 
 213   {"wait_click",              TOKENIZER_WAIT_CLICK},
 214   {"is_pressed",              TOKENIZER_IS_PRESSED},
 215   {"is_key",                  TOKENIZER_IS_KEY},
 216   {"set_exit_key",            TOKENIZER_SET_EXIT_KEY},
 217 
 218   {"wheel_right",             TOKENIZER_WHEEL_RIGHT},
 219   {"wheel_left",              TOKENIZER_WHEEL_LEFT},
 220 
 221   {"@title",                  TOKENIZER_REM},
 222   {"@subtitle",               TOKENIZER_REM},
 223   {"@param",                  TOKENIZER_REM},
 224   {"@default",                TOKENIZER_REM},
 225   {"@range",                  TOKENIZER_REM},
 226   {"@values",                 TOKENIZER_REM},
 227   {"@chdk_version",           TOKENIZER_REM},
 228 
 229   {"md_detect_motion",        TOKENIZER_MD_DETECT_MOTION},
 230   {"md_get_cell_diff",        TOKENIZER_MD_GET_CELL_DIFF},
 231   {"md_get_cell_val",         TOKENIZER_MD_GET_CELL_VAL},
 232   {"md_af_led_control",       TOKENIZER_MD_AF_LED_CONTROL},
 233   {"autostarted",             TOKENIZER_SCRIPT_AUTOSTARTED},
 234   {"get_autostart",           TOKENIZER_GET_SCRIPT_AUTOSTART},
 235   {"set_autostart",           TOKENIZER_SET_SCRIPT_AUTOSTART},
 236   {"get_usb_power",           TOKENIZER_GET_USB_POWER},
 237   {"usb_force_active",        TOKENIZER_FORCE_USB_PRESENT},
 238   {"usb_sync_wait",           TOKENIZER_USB_SYNC_WAIT},
 239   {"exit_alt",                TOKENIZER_EXIT_ALT},
 240   {"enter_alt",               TOKENIZER_ENTER_ALT},
 241   {"get_alt_mode",            TOKENIZER_GET_ALT_MODE},
 242   {"shut_down",               TOKENIZER_SHUT_DOWN},
 243 
 244   {"get_shooting",            TOKENIZER_GET_SHOOTING},
 245   {"get_drive_mode",          TOKENIZER_GET_DRIVE_MODE},
 246   {"get_flash_mode",          TOKENIZER_GET_FLASH_MODE},
 247   {"get_flash_ready",         TOKENIZER_GET_FLASH_READY},
 248   {"get_IS_mode",             TOKENIZER_GET_IS_MODE},
 249   {"set_ev",                  TOKENIZER_SET_EV},
 250   {"get_ev",                  TOKENIZER_GET_EV},
 251   {"get_orientation_sensor",  TOKENIZER_GET_ORIENTATION_SENSOR},
 252   {"get_nd_present",          TOKENIZER_GET_ND_PRESENT},
 253   {"get_histo_range",         TOKENIZER_GET_HISTO_RANGE},
 254   {"shot_histo_enable",       TOKENIZER_SHOT_HISTO_ENABLE},
 255   {"set_aelock",              TOKENIZER_SET_AELOCK},
 256   {"set_aflock",              TOKENIZER_SET_AFLOCK},
 257   {"set_mf",                  TOKENIZER_SET_MF},
 258   {"is_capture_mode_valid",   TOKENIZER_IS_CAPTURE_MODE_VALID},
 259   {"reboot",                  TOKENIZER_REBOOT},
 260 
 261   // APEX functions
 262   {"iso_to_sv96",             TOKENIZER_ISO_TO_SV96},
 263   {"sv96_to_iso",             TOKENIZER_SV96_TO_ISO},
 264   {"iso_real_to_market",      TOKENIZER_ISO_REAL_TO_MARKET},
 265   {"iso_market_to_real",      TOKENIZER_ISO_MARKET_TO_REAL},
 266   {"sv96_real_to_market",     TOKENIZER_SV96_REAL_TO_MARKET},
 267   {"sv96_market_to_real",     TOKENIZER_SV96_MARKET_TO_REAL},
 268   {"aperture_to_av96",        TOKENIZER_APERTURE_TO_AV96},
 269   {"av96_to_aperture",        TOKENIZER_AV96_TO_APERTURE},
 270   {"usec_to_tv96",            TOKENIZER_USEC_TO_TV96},
 271   {"tv96_to_usec",            TOKENIZER_TV96_TO_USEC},
 272   {"seconds_to_tv96",         TOKENIZER_SECONDS_TO_TV96},
 273 
 274   {"end",                     TOKENIZER_END},
 275 
 276   {NULL,                      TOKENIZER_ERROR}
 277 };
 278 
 279 /*---------------------------------------------------------------------------*/
 280 static int
 281 singlechar(void)
 282 {
 283   if(*ptr == '\n') {
 284     return TOKENIZER_CR;
 285   } else if(*ptr == ',') {
 286     return TOKENIZER_COMMA;
 287   } else if(*ptr == ';') {
 288     return TOKENIZER_SEMICOLON;
 289   } else if(*ptr == '+') {
 290     return TOKENIZER_PLUS;
 291   } else if(*ptr == '-') {
 292     return TOKENIZER_MINUS;
 293   } else if(*ptr == '&') {
 294     return TOKENIZER_AND;
 295   } else if(*ptr == '|') {
 296     return TOKENIZER_OR;
 297   } else if(*ptr == '^') {
 298     return TOKENIZER_XOR;
 299   } else if(*ptr == '*') {
 300     return TOKENIZER_ASTR;
 301   } else if(*ptr == '/') {
 302     return TOKENIZER_SLASH;
 303   } else if(*ptr == '%') {
 304     return TOKENIZER_MOD;
 305   } else if(*ptr == '(') {
 306     return TOKENIZER_LEFTPAREN;
 307   } else if(*ptr == ')') {
 308     return TOKENIZER_RIGHTPAREN;
 309   } else if(*ptr == '=') {
 310     return TOKENIZER_EQ;
 311   }
 312   return 0;
 313 }
 314 /*---------------------------------------------------------------------------*/
 315 static int
 316 get_next_token(void)
 317 {
 318   struct keyword_token const *kt;
 319   int i;
 320 
 321   DEBUG_PRINTF("get_next_token(): '%s'\n", ptr);
 322 
 323   // eat all whitespace
 324   while(*ptr == ' ' || *ptr == '\t' || *ptr == '\r') ptr++;
 325 
 326   if(*ptr == 0) {
 327     return TOKENIZER_ENDOFINPUT;
 328   }
 329 
 330     // UnknStatement should have size, otherwise hanging-up in ubasic.c possible for some cases
 331     nextptr = ptr + 1;
 332 
 333   if(isdigit(*ptr)) {
 334     for(i = 0; i < (MAX_NUMLEN+1); ++i) {
 335       if(!isdigit(ptr[i])) {
 336         if(i > 0) {
 337           nextptr = ptr + i;
 338           return TOKENIZER_NUMBER;
 339         } else {
 340           DEBUG_PRINTF("get_next_token: error due to too short number\n");
 341           return TOKENIZER_ERROR;
 342         }
 343       }
 344       if(!isdigit(ptr[i])) {
 345         DEBUG_PRINTF("get_next_token: error due to malformed number\n");
 346         return TOKENIZER_ERROR;
 347       }
 348     }
 349     DEBUG_PRINTF("get_next_token: error due to too long number\n");
 350     return TOKENIZER_ERROR;
 351   } else if(*ptr == ':') {
 352     // label
 353     nextptr = ptr;
 354     do {
 355       ++nextptr;
 356     } while(*nextptr != ' ' && *nextptr != '\r' && *nextptr != '\n' && *nextptr != '\t');
 357     return TOKENIZER_LABEL;
 358   } else if((i=singlechar()) != 0) {
 359     if (i == TOKENIZER_CR){
 360       // move to next line, and skip all following empty lines as well
 361       while (singlechar() == TOKENIZER_CR)
 362       {
 363         current_line++;
 364         ptr++;
 365         // eat all whitespace
 366         while(*ptr == ' ' || *ptr == '\t' || *ptr == '\r') ptr++;
 367       };
 368       ptr--;
 369       // dangelo: now the last char might point to a whitespace instead of
 370       // a CR. I hope that doesn't break anything.
 371     }
 372     nextptr = ptr + 1;
 373     return i;
 374   } else if(*ptr == '"') {
 375     nextptr = ptr;
 376     do {
 377       ++nextptr;
 378     } while(*nextptr != '"');
 379     ++nextptr;
 380     return TOKENIZER_STRING;
 381   } else {
 382     for(kt = keywords; kt->keyword != NULL; ++kt) {
 383       if(strncmp(ptr, kt->keyword, strlen(kt->keyword)) == 0) {
 384         nextptr = ptr + strlen(kt->keyword);
 385         if (kt->token == TOKENIZER_REM) {
 386            while(*nextptr != 0 && *nextptr != '\r' && *nextptr != '\n') ++nextptr;
 387         }
 388         return kt->token;
 389       }
 390     }
 391   }
 392 
 393   if((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= 'A' && *ptr <= 'Z')) {
 394     nextptr = ptr + 1;
 395     return TOKENIZER_VARIABLE;
 396   }
 397 
 398 
 399   return TOKENIZER_ERROR;
 400 }
 401 /*---------------------------------------------------------------------------*/
 402 void
 403 tokenizer_init(const char *program)
 404 {
 405   ptr = program;
 406   current_line = 1;
 407   current_token = get_next_token();
 408   while (current_token==TOKENIZER_CR && !tokenizer_finished()) tokenizer_next();
 409 }
 410 /*---------------------------------------------------------------------------*/
 411 int
 412 tokenizer_token(void)
 413 {
 414   return current_token;
 415 }
 416 /*---------------------------------------------------------------------------*/
 417 void
 418 tokenizer_next(void)
 419 {
 420 
 421   if(tokenizer_finished()) {
 422     return;
 423   }
 424 
 425   DEBUG_PRINTF("tokenizer_next: %p\n", nextptr);
 426   ptr = nextptr;
 427   while((*ptr == ' ') || (*ptr == '\t')) {
 428     ++ptr;
 429   }
 430   current_token = get_next_token();
 431   DEBUG_PRINTF("tokenizer_next: '%s' %d\n", ptr, current_token);
 432   return;
 433 }
 434 /*---------------------------------------------------------------------------*/
 435 int
 436 tokenizer_num(void)
 437 {
 438   return atoi(ptr);
 439 }
 440 /*---------------------------------------------------------------------------*/
 441 void
 442 tokenizer_string(char *dest, int len)
 443 {
 444   char *string_end;
 445   int string_len;
 446 
 447   if(tokenizer_token() != TOKENIZER_STRING) {
 448     return;
 449   }
 450   string_end = strchr(ptr + 1, '"');
 451   if(string_end == NULL) {
 452     return;
 453   }
 454   string_len = string_end - ptr - 1;
 455   if(len < string_len) {
 456     string_len = len;
 457   }
 458   memcpy(dest, ptr + 1, string_len);
 459   dest[string_len] = 0;
 460 }
 461 /*---------------------------------------------------------------------------*/
 462 void
 463 tokenizer_label(char *dest, int len)
 464 {
 465   char *string_end;
 466   int string_len;
 467 
 468   if(tokenizer_token() != TOKENIZER_LABEL) {
 469     return;
 470   }
 471   // allow string \r, \n, tabulation and space to end labels
 472   string_end = strpbrk(ptr + 1, " \t\r\n");
 473 
 474   if(string_end == NULL) {
 475     return;
 476   }
 477   string_len = string_end - ptr - 1;
 478   if(len < string_len) {
 479     string_len = len;
 480   }
 481   memcpy(dest, ptr + 1, string_len);
 482   dest[string_len] = 0;
 483 }
 484 /*---------------------------------------------------------------------------*/
 485 void
 486 tokenizer_error_print(void)
 487 {
 488   DEBUG_PRINTF("tokenizer_error_print: '%s'\n", ptr);
 489 }
 490 /*---------------------------------------------------------------------------*/
 491 int
 492 tokenizer_finished(void)
 493 {
 494   return *ptr == 0 || current_token == TOKENIZER_ENDOFINPUT;
 495 }
 496 /*---------------------------------------------------------------------------*/
 497 int
 498 tokenizer_variable_num(void)
 499 {
 500   return *ptr - (*ptr>='a'?'a':('A'-26));
 501 }
 502 /*---------------------------------------------------------------------------*/
 503 int tokenizer_line_number(void)
 504 {
 505   return current_line;
 506 }

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