source: trunk/lib/ubasic/tokenizer.c @ 846

Revision 846, 15.3 KB checked in by reyalp, 3 years ago (diff)

fix ubasic test program

  • Property svn:eol-style set to native
Line 
1/*
2 * Copyright (c) 2006, Adam Dunkels
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30
31#if DEBUG
32#define DEBUG_PRINTF(...)  printf(__VA_ARGS__)
33#else
34#define DEBUG_PRINTF(...)
35#endif
36
37#ifdef UBASIC_TEST
38#include <string.h>
39#include <ctype.h>
40#endif
41
42#include "tokenizer.h"
43#include "stdlib.h"
44
45static char const *ptr, *nextptr;
46
47#define MAX_NUMLEN 6
48
49struct keyword_token {
50  const char *keyword;
51  int token;
52};
53
54static ubasic_token current_token = TOKENIZER_ERROR;
55static int current_line = 0;
56
57static 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  {"for",                     TOKENIZER_FOR},
77  {"to",                      TOKENIZER_TO},
78  {"next",                    TOKENIZER_NEXT},
79  {"step",                    TOKENIZER_STEP},
80  {"do",                      TOKENIZER_DO},
81  {"until",                   TOKENIZER_UNTIL},
82  {"while",                   TOKENIZER_WHILE},
83  {"wend",                    TOKENIZER_WEND},
84  {"goto",                    TOKENIZER_GOTO},
85  {"gosub",                   TOKENIZER_GOSUB},
86  {"return",                  TOKENIZER_RETURN},
87  {"call",                    TOKENIZER_CALL},
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  {"sleep",                   TOKENIZER_SLEEP},
100
101  /* WARNING due to tokenizer limitation longest match must be first */
102// GET 
103  {"get_av96",                TOKENIZER_GET_AV96},
104  {"get_av",                  TOKENIZER_GET_USER_AV_ID}, //FOR COMPATIBILITY
105  {"get_bv96",                TOKENIZER_GET_BV96},
106  {"get_display_mode",        TOKENIZER_GET_DISPLAY_MODE},
107  {"get_day_seconds",         TOKENIZER_GET_DAY_SECONDS},
108  {"get_disk_size",           TOKENIZER_GET_DISK_SIZE},
109  {"get_dof",                 TOKENIZER_GET_DOF},
110  {"get_far_limit",           TOKENIZER_GET_FAR_LIMIT},
111  {"get_free_disk_space",     TOKENIZER_GET_FREE_DISK_SPACE},
112  {"get_focus_mode",          TOKENIZER_GET_FOCUS_MODE},
113  {"get_focus",               TOKENIZER_GET_FOCUS},
114  {"get_hyp_dist",            TOKENIZER_GET_HYPERFOCAL_DIST},
115  {"get_iso_market",          TOKENIZER_GET_ISO_MARKET},
116  {"get_iso_mode",            TOKENIZER_GET_ISO_MODE},
117  {"get_iso_real",            TOKENIZER_GET_ISO_REAL},
118  {"get_iso",                 TOKENIZER_GET_ISO_MODE}, //FOR COMPATIBILITY
119  {"get_jpg_count",           TOKENIZER_GET_JPG_COUNT},
120  {"get_movie_status",        TOKENIZER_GET_MOVIE_STATUS},
121  {"get_mode",                                  TOKENIZER_GET_MODE},  // Returns 0 in recordmode, 1 in playmode
122  {"get_near_limit",          TOKENIZER_GET_NEAR_LIMIT},
123  {"get_platform_id",          TOKENIZER_GET_PLATFORM_ID},
124  {"get_propset",             TOKENIZER_GET_PROPSET},
125  {"get_prop",                TOKENIZER_GET_PROP},
126  {"get_quality",             TOKENIZER_GET_QUALITY},
127  {"get_raw_count",           TOKENIZER_GET_RAW_COUNT},
128  {"get_raw_nr",              TOKENIZER_GET_RAW_NR},
129  {"get_raw",                 TOKENIZER_GET_RAW},
130  {"get_resolution",          TOKENIZER_GET_RESOLUTION},
131  {"get_sv96",                TOKENIZER_GET_SV96},
132  {"get_temperature",         TOKENIZER_GET_TEMPERATURE},
133  {"get_tick_count",          TOKENIZER_GET_TICK_COUNT},
134  {"get_time",                                  TOKENIZER_GET_TIME},
135  {"get_tv96",                TOKENIZER_GET_TV96},
136  {"get_user_av_id",          TOKENIZER_GET_USER_AV_ID},
137  {"get_user_av96",           TOKENIZER_GET_USER_AV96},
138  {"get_user_tv_id",          TOKENIZER_GET_USER_TV_ID},
139  {"get_user_tv96",           TOKENIZER_GET_USER_TV96},
140  {"get_video_button",        TOKENIZER_GET_VIDEO_BUTTON},
141  {"get_vbatt",               TOKENIZER_GET_VBATT}, 
142  {"get_zoom_steps",          TOKENIZER_GET_ZOOM_STEPS},
143  {"get_zoom",                TOKENIZER_GET_ZOOM},
144  {"get_exp_count",           TOKENIZER_GET_EXP_COUNT},
145
146
147
148//SET 
149  {"set_av96_direct",         TOKENIZER_SET_AV96_DIRECT},
150  {"set_av_rel",              TOKENIZER_SET_USER_AV_BY_ID_REL}, //FOR COMPATIBILITY
151  {"set_av96",                TOKENIZER_SET_AV96},
152  {"set_av",                  TOKENIZER_SET_USER_AV_BY_ID}, //FOR COMPATIBILITY
153  {"set_backlight",           TOKENIZER_SET_BACKLIGHT},
154  {"set_focus",               TOKENIZER_SET_FOCUS},
155  {"set_iso_mode",            TOKENIZER_SET_ISO_MODE},
156  {"set_iso_real",            TOKENIZER_SET_ISO_REAL},
157  {"set_iso",                 TOKENIZER_SET_ISO_MODE}, //FOR COMPATIBILITY
158  {"set_led",                 TOKENIZER_SET_LED},
159  {"set_movie_status",        TOKENIZER_SET_MOVIE_STATUS}, 
160  {"set_nd_filter",           TOKENIZER_SET_ND_FILTER},
161  {"set_prop",                TOKENIZER_SET_PROP},
162  {"set_quality",                TOKENIZER_SET_QUALITY},
163  {"set_raw_nr",              TOKENIZER_SET_RAW_NR},
164  {"set_raw",                 TOKENIZER_SET_RAW},
165  {"set_resolution",          TOKENIZER_SET_RESOLUTION},
166    //{"set_shutter_speed",       TOKENIZER_SET_SHUTTER_SPEED},
167  {"set_sv96",                    TOKENIZER_SET_SV96},
168  {"set_tv96_direct",         TOKENIZER_SET_TV96_DIRECT},
169  {"set_tv_rel",              TOKENIZER_SET_USER_TV_BY_ID_REL}, //FOR COMPATIBILITY
170  {"set_tv96",                TOKENIZER_SET_TV96},
171  {"set_tv",                  TOKENIZER_SET_USER_TV_BY_ID}, //FOR COMPATIBILITY
172  {"set_user_av_by_id_rel",   TOKENIZER_SET_USER_AV_BY_ID_REL},
173  {"set_user_av_by_id",       TOKENIZER_SET_USER_AV_BY_ID},
174  {"set_user_av96",           TOKENIZER_SET_USER_AV96},
175  {"set_user_tv_by_id_rel",   TOKENIZER_SET_USER_TV_BY_ID_REL},
176  {"set_user_tv_by_id",       TOKENIZER_SET_USER_TV_BY_ID},
177  {"set_user_tv96",           TOKENIZER_SET_USER_TV96},
178  {"set_zoom_speed",          TOKENIZER_SET_ZOOM_SPEED},
179  {"set_zoom_rel",            TOKENIZER_SET_ZOOM_REL},
180  {"set_zoom",                TOKENIZER_SET_ZOOM},
181  {"set_record",              TOKENIZER_SET_RECORD},
182 
183 
184  {"wait_click",              TOKENIZER_WAIT_CLICK},
185  {"is_pressed",              TOKENIZER_IS_PRESSED},
186  {"is_key",                  TOKENIZER_IS_KEY},
187 
188  {"wheel_right",             TOKENIZER_WHEEL_RIGHT},
189  {"wheel_left",              TOKENIZER_WHEEL_LEFT},
190 
191  {"@title",                  TOKENIZER_REM},
192  {"@param",                  TOKENIZER_REM},
193  {"@default",                TOKENIZER_REM},
194
195  {"md_detect_motion",        TOKENIZER_MD_DETECT_MOTION},
196  {"md_get_cell_diff",        TOKENIZER_MD_GET_CELL_DIFF},
197  {"autostarted",             TOKENIZER_SCRIPT_AUTOSTARTED},
198  {"get_autostart",           TOKENIZER_GET_SCRIPT_AUTOSTART},
199  {"set_autostart",           TOKENIZER_SET_SCRIPT_AUTOSTART},
200  {"get_usb_power",           TOKENIZER_GET_USB_POWER},
201  {"exit_alt",                TOKENIZER_EXIT_ALT},
202  {"shut_down",               TOKENIZER_SHUT_DOWN},
203
204  {"get_shooting",            TOKENIZER_GET_SHOOTING},
205  {"get_drive_mode",          TOKENIZER_GET_DRIVE_MODE},
206  {"get_flash_mode",          TOKENIZER_GET_FLASH_MODE},
207  {"get_flash_ready",         TOKENIZER_GET_FLASH_READY},
208  {"get_IS_mode",             TOKENIZER_GET_IS_MODE},
209  {"set_ev",                  TOKENIZER_SET_EV},
210  {"get_ev",                  TOKENIZER_GET_EV},
211  {"get_orientation_sensor",  TOKENIZER_GET_ORIENTATION_SENSOR},
212  {"get_nd_present",          TOKENIZER_GET_ND_PRESENT},
213  {"get_histo_range",         TOKENIZER_GET_HISTO_RANGE},
214   {"shot_histo_enable",       TOKENIZER_SHOT_HISTO_ENABLE},
215   {"set_aflock",            TOKENIZER_SET_AFLOCK},
216 
217  {"end",                     TOKENIZER_END},
218
219  {NULL,                      TOKENIZER_ERROR}
220};
221
222/*---------------------------------------------------------------------------*/
223static int
224singlechar(void)
225{
226  if(*ptr == '\n') {
227    return TOKENIZER_CR;
228  } else if(*ptr == ',') {
229    return TOKENIZER_COMMA;
230  } else if(*ptr == ';') {
231    return TOKENIZER_SEMICOLON;
232  } else if(*ptr == '+') {
233    return TOKENIZER_PLUS;
234  } else if(*ptr == '-') {
235    return TOKENIZER_MINUS;
236  } else if(*ptr == '&') {
237    return TOKENIZER_AND;
238  } else if(*ptr == '|') {
239    return TOKENIZER_OR;
240  } else if(*ptr == '^') {
241    return TOKENIZER_XOR;
242  } else if(*ptr == '*') {
243    return TOKENIZER_ASTR;
244  } else if(*ptr == '/') {
245    return TOKENIZER_SLASH;
246  } else if(*ptr == '%') {
247    return TOKENIZER_MOD;
248  } else if(*ptr == '(') {
249    return TOKENIZER_LEFTPAREN;
250  } else if(*ptr == ')') {
251    return TOKENIZER_RIGHTPAREN;
252  } else if(*ptr == '=') {
253    return TOKENIZER_EQ;
254  }
255  return 0;
256}
257/*---------------------------------------------------------------------------*/
258static int
259get_next_token(void)
260{
261  struct keyword_token const *kt;
262  int i;
263
264  DEBUG_PRINTF("get_next_token(): '%s'\n", ptr);
265
266  // eat all whitespace
267  while(*ptr == ' ' || *ptr == '\t' || *ptr == '\r') ptr++;
268
269  if(*ptr == 0) {
270    return TOKENIZER_ENDOFINPUT;
271  }
272 
273  if(isdigit(*ptr)) {
274    for(i = 0; i < (MAX_NUMLEN+1); ++i) {
275      if(!isdigit(ptr[i])) {
276        if(i > 0) {
277          nextptr = ptr + i;
278          return TOKENIZER_NUMBER;
279        } else {
280          DEBUG_PRINTF("get_next_token: error due to too short number\n");
281          return TOKENIZER_ERROR;
282        }
283      }
284      if(!isdigit(ptr[i])) {
285        DEBUG_PRINTF("get_next_token: error due to malformed number\n");
286        return TOKENIZER_ERROR;
287      }
288    }
289    DEBUG_PRINTF("get_next_token: error due to too long number\n");
290    return TOKENIZER_ERROR;
291  } else if(*ptr == ':') {
292    // label
293    nextptr = ptr;
294    do {
295      ++nextptr;
296    } while(*nextptr != ' ' && *nextptr != '\r' && *nextptr != '\n' && *nextptr != '\t');
297    return TOKENIZER_LABEL;
298  } else if((i=singlechar()) != 0) {
299    if (i == TOKENIZER_CR){
300      // move to next line, and skip all following empty lines as well
301      while (singlechar() == TOKENIZER_CR)
302      {
303        current_line++;
304        ptr++;
305        // eat all whitespace
306        while(*ptr == ' ' || *ptr == '\t' || *ptr == '\r') ptr++;
307      };
308      ptr--;
309      // dangelo: now the last char might point to a whitespace instead of
310      // a CR. I hope that doesn't break anything.
311    }
312    nextptr = ptr + 1;
313    return i;
314  } else if(*ptr == '"') {
315    nextptr = ptr;
316    do {
317      ++nextptr;
318    } while(*nextptr != '"');
319    ++nextptr;
320    return TOKENIZER_STRING;
321  } else {
322    for(kt = keywords; kt->keyword != NULL; ++kt) {
323      if(strncmp(ptr, kt->keyword, strlen(kt->keyword)) == 0) {
324        nextptr = ptr + strlen(kt->keyword);
325        if (kt->token == TOKENIZER_REM) {
326           while(*nextptr != 0 && *nextptr != '\r' && *nextptr != '\n') ++nextptr;
327        }
328        return kt->token;
329      }
330    }
331  }
332
333  if((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= 'A' && *ptr <= 'Z')) {
334    nextptr = ptr + 1;
335    return TOKENIZER_VARIABLE;
336  }
337
338 
339  return TOKENIZER_ERROR;
340}
341/*---------------------------------------------------------------------------*/
342void
343tokenizer_init(const char *program)
344{
345  ptr = program;
346  current_line = 1;
347  current_token = get_next_token();
348}
349/*---------------------------------------------------------------------------*/
350int
351tokenizer_token(void)
352{
353  return current_token;
354}
355/*---------------------------------------------------------------------------*/
356void
357tokenizer_next(void)
358{
359
360  if(tokenizer_finished()) {
361    return;
362  }
363
364  DEBUG_PRINTF("tokenizer_next: %p\n", nextptr);
365  ptr = nextptr;
366  while((*ptr == ' ') || (*ptr == '\t')) {
367    ++ptr;
368  }
369  current_token = get_next_token();
370  DEBUG_PRINTF("tokenizer_next: '%s' %d\n", ptr, current_token);
371  return;
372}
373/*---------------------------------------------------------------------------*/
374int
375tokenizer_num(void)
376{
377  return atoi(ptr);
378}
379/*---------------------------------------------------------------------------*/
380void
381tokenizer_string(char *dest, int len)
382{
383  char *string_end;
384  int string_len;
385 
386  if(tokenizer_token() != TOKENIZER_STRING) {
387    return;
388  }
389  string_end = strchr(ptr + 1, '"');
390  if(string_end == NULL) {
391    return;
392  }
393  string_len = string_end - ptr - 1;
394  if(len < string_len) {
395    string_len = len;
396  }
397  memcpy(dest, ptr + 1, string_len);
398  dest[string_len] = 0;
399}
400/*---------------------------------------------------------------------------*/
401void
402tokenizer_label(char *dest, int len)
403{
404  char *string_end;
405  int string_len;
406 
407  if(tokenizer_token() != TOKENIZER_LABEL) {
408    return;
409  }
410  // allow string \r, \n, tabulation and space to end labels
411  string_end = strpbrk(ptr + 1, " \t\r\n");
412
413  if(string_end == NULL) {
414    return;
415  }
416  string_len = string_end - ptr - 1;
417  if(len < string_len) {
418    string_len = len;
419  }
420  memcpy(dest, ptr + 1, string_len);
421  dest[string_len] = 0;
422}
423/*---------------------------------------------------------------------------*/
424void
425tokenizer_error_print(void)
426{
427  DEBUG_PRINTF("tokenizer_error_print: '%s'\n", ptr);
428}
429/*---------------------------------------------------------------------------*/
430int
431tokenizer_finished(void)
432{
433  return *ptr == 0 || current_token == TOKENIZER_ENDOFINPUT;
434}
435/*---------------------------------------------------------------------------*/
436int
437tokenizer_variable_num(void)
438{
439  return *ptr - (*ptr>='a'?'a':('A'-26));
440}
441/*---------------------------------------------------------------------------*/
442int tokenizer_line_number(void)
443{
444  return current_line;
445}
Note: See TracBrowser for help on using the repository browser.