source: trunk/core/script.c @ 515

Revision 515, 13.8 KB checked in by reyalp, 5 years ago (diff)

set svn:eol-style and fix files that had mixed line endings. See http://chdk.setepontos.com/index.php/topic,2145.15.html

  • Property svn:eol-style set to native
Line 
1#include "stdlib.h"
2#include "keyboard.h"
3#include "platform.h"
4#include "core.h"
5#include "gui.h"
6#include "gui_draw.h"
7#include "conf.h"
8#include "script.h"
9
10//-------------------------------------------------------------------
11
12#define SCRIPT_BUF_SIZE             8192
13#define SCRIPT_PARAM_BUF_SIZE       2048
14#define SCRIPT_CONSOLE_NUM_LINES    5
15#define SCRIPT_CONSOLE_LINE_LENGTH  25
16#define SCRIPT_CONSOLE_X            0
17#define SCRIPT_CONSOLE_Y            (14-SCRIPT_CONSOLE_NUM_LINES)
18
19//-------------------------------------------------------------------
20const char *state_ubasic_script;
21char cfg_name[100] = "\0";
22char cfg_set_name[100] = "\0";
23
24static char ubasic_script_buf[SCRIPT_BUF_SIZE];
25static char ubasic_scriptparam_buf[SCRIPT_PARAM_BUF_SIZE];
26static const char *ubasic_script_default =
27#if 0
28    "@title Default script\n"
29    "@param a Shoot count\n"
30    "@default a 2\n"
31    "@param b Step\n"
32    "@default b 3\n"
33
34    "sleep 1000\n"
35
36    "if a<1 then let a=2\n"
37    "if b<1 then let b=3\n"
38
39    "for s=1 to a\n"
40      "shoot\n"
41      "for n=1 to b\n"
42        "click \"right\"\n"
43      "next n\n"
44    "next s\n"
45    "shoot\n"
46
47    "for n=1 to a*b\n"
48      "click \"left\"\n"
49    "next n\n"
50
51    "end\n";
52#else
53    "@title Default Script\n"
54    "@param a Times to Repeat\n"
55    "@default a 5\n"
56    "@param b Display Delay\n"
57    "@default b 3\n"
58
59    "if a<1 then let a=1\n"
60    "if b<1 then let b=1\n"
61
62    "for n=1 to a\n"
63        "if n>1 then print \"*****\"\n"
64        "print \"This is a default script.\"\n"
65        "sleep 1000\n"
66        "print \"Scripts run when shutter\"\n"
67        "sleep 1000\n"
68        "print \"is pressed in ALT mode.\"\n"
69        "sleep 1000\n"
70        "print \"Press shutter to exit.\"\n"
71        "sleep b*1000\n"
72    "next n\n"
73
74    "end\n";
75#endif
76
77char script_title[36];
78char script_params[SCRIPT_NUM_PARAMS][28];
79int script_param_order[SCRIPT_NUM_PARAMS];
80char script_params_update[SCRIPT_NUM_PARAMS];
81int script_loaded_params[SCRIPT_NUM_PARAMS];
82char script_console_buf[SCRIPT_CONSOLE_NUM_LINES][SCRIPT_CONSOLE_LINE_LENGTH+1];
83static int script_console_lines=0;
84//-------------------------------------------------------------------
85static void process_title(const char *title) {
86    register const char *ptr = title;
87    register int i=0;
88
89    while (ptr[0]==' ' || ptr[0]=='\t') ++ptr; // whitespaces
90    while (i<(sizeof(script_title)-1) && ptr[i] && ptr[i]!='\r' && ptr[i]!='\n') {
91        script_title[i]=ptr[i];
92        ++i;
93    }
94    script_title[i]=0;
95}
96
97//-------------------------------------------------------------------
98static int process_param(const char *param, int update) {
99    register const char *ptr = param;
100    register int n, i=0;
101
102    while (ptr[0]==' ' || ptr[0]=='\t') ++ptr; // whitespaces
103    if (ptr[0] && (ptr[0]>='a' && ptr[0]<='a'+SCRIPT_NUM_PARAMS) && (ptr[1]==' ' || ptr[1]=='\t')) {
104        n=ptr[0]-'a';
105        ptr+=2;
106        while (ptr[0]==' ' || ptr[0]=='\t') ++ptr; // whitespaces
107                script_params_update[n] = 1;
108        while (i<(sizeof(script_params[0])-1) && ptr[i] && ptr[i]!='\r' && ptr[i]!='\n') {
109                        if (update)
110                        { if (script_params[n][i]!=ptr[i]) { script_params_update[n] = 0; break; }
111                        } else script_params[n][i]=ptr[i];
112            ++i;
113        }
114                if (!update) script_params[n][i]=0;
115        n++;
116    } else n=0; // ??? else produce error message   
117    return n; // n=1 if '@param a' was processed, n=2 for 'b' ... n=26 for 'z'. n=0 if failed.
118}
119
120//-------------------------------------------------------------------
121static void process_default(const char *param, char update) {
122    register const char *ptr = param;
123    register int n;
124
125    while (ptr[0]==' ' || ptr[0]=='\t') ++ptr; // whitespaces
126    if (ptr[0] && (ptr[0]>='a' && ptr[0]<='a'+SCRIPT_NUM_PARAMS) && (ptr[1]==' ' || ptr[1]=='\t')) {
127        n=ptr[0]-'a';
128        ptr+=2;
129                if (!update || script_params_update[n])
130        {
131                        conf.ubasic_vars[n] = strtol(ptr, NULL, 0);
132            script_loaded_params[n] = conf.ubasic_vars[n];
133        }
134    } // ??? else produce error message
135}
136
137//-------------------------------------------------------------------
138static void script_scan(const char *fn, int update_vars) {
139    register const char *ptr = state_ubasic_script;
140    register int i, j=0, n;
141    char *c;
142
143    c=strrchr(fn, '/');
144    strncpy(script_title, (c)?c+1:fn, sizeof(script_title));
145    script_title[sizeof(script_title)-1]=0;
146    for (i=0; i<SCRIPT_NUM_PARAMS; ++i) {
147        script_params[i][0]=0;
148        script_param_order[i]=0;
149    }
150
151    while (ptr[0]) {
152        while (ptr[0]==' ' || ptr[0]=='\t') ++ptr; // whitespaces
153        if (ptr[0]=='@') {
154            if (strncmp("@title", ptr, 6)==0) {
155                ptr+=6;
156                process_title(ptr);
157            } else if (strncmp("@param", ptr, 6)==0) {
158                ptr+=6;
159                n=process_param(ptr, 0); // n=1 if '@param a' was processed, n=2 for 'b' ... n=26 for 'z'. n=0 if failed.
160                if (n>0 && n<=SCRIPT_NUM_PARAMS) {
161                  script_param_order[j]=n;
162                  j++;
163                }
164            } else if (update_vars && strncmp("@default", ptr, 8)==0) {
165                ptr+=8;
166                process_default(ptr, 0);
167            }
168        }
169        while (ptr[0] && ptr[0]!='\n') ++ptr; // unless end of line
170        if (ptr[0]) ++ptr;
171    }
172
173    /*for (i=0; i<SCRIPT_NUM_PARAMS; ++i) {
174        if (script_params[i][0]) break;
175    }
176    if (i==SCRIPT_NUM_PARAMS) { // there was no @param in script
177        for (i=0; i<3; ++i) {
178            strcpy(script_params[i], "Var. ? value");
179            script_params[i][5]='a'+i;
180        }
181    }*/
182}
183
184void set_params_values_name(const char *fn, int param_set)
185{
186        int shift;
187        register char *ptr = (param_set >= 0 ? cfg_set_name : cfg_name);
188        const char *name;
189       
190        if (fn == NULL || fn[0] == 0) { ptr[0] = 0; return; }
191       
192        strncpy(ptr, SCRIPT_DATA_PATH, 100); ptr[99]=0;
193        shift = strlen(SCRIPT_DATA_PATH);
194        name = strrchr(fn, '/');
195        if (name) name++; else name=fn;
196        strncpy(ptr+shift, name, 100-shift); ptr[99]=0;
197        shift = strlen(ptr); if (shift >= 100) shift=99;
198
199        if (param_set >= 0)
200                sprintf(ptr+shift-4, "_%d\0", param_set); else
201                strcpy(ptr+shift-3, "cfg\0");
202}
203
204//-------------------------------------------------------------------
205int load_params_values(const char *fn, int update_vars, int read_param_set)
206{
207        int i, fd=-1, rcnt;
208        register const char *ptr;       
209       
210        if (fn == NULL || fn[0] == 0) return 0;
211        if (read_param_set)
212        {
213                set_params_values_name(fn, -1);
214                // find param set
215                fd = open(cfg_name, O_RDONLY, 0777);
216                if (fd >= 0)
217                {
218                        rcnt = read(fd, ubasic_scriptparam_buf, SCRIPT_PARAM_BUF_SIZE);
219                        ubasic_scriptparam_buf[rcnt] = 0;
220                        close(fd);
221                        conf.script_param_set = strtol(ubasic_scriptparam_buf, NULL, 0);
222                } else conf.script_param_set = 0;
223        }
224        set_params_values_name(fn, conf.script_param_set);
225        if (!update_vars) return 0;
226       
227        // open and read file
228        fd = open(cfg_set_name, O_RDONLY, 0777);
229        if (fd < 0) return 0;
230        rcnt = read(fd, ubasic_scriptparam_buf, SCRIPT_PARAM_BUF_SIZE);
231        ubasic_scriptparam_buf[rcnt] = 0;
232        close(fd);
233
234        for(i = 0; i < SCRIPT_NUM_PARAMS; ++i) script_params_update[i]=0;
235    ptr = ubasic_scriptparam_buf;
236
237    while (ptr[0])
238        {
239        while (ptr[0]==' ' || ptr[0]=='\t') ++ptr; // whitespaces
240        if (ptr[0]=='@')
241                {
242            if (strncmp("@param", ptr, 6) == 0)
243                        {
244                ptr+=6;
245                                process_param(ptr, 1);
246            } else if (strncmp("@default", ptr, 8)==0) {
247                ptr+=8;
248                                process_default(ptr, 1);
249            }
250        }
251        while (ptr[0] && ptr[0]!='\n') ++ptr; // unless end of line
252        if (ptr[0]) ++ptr;
253    }
254        return 1;
255}
256
257//-------------------------------------------------------------------
258void save_params_values(int unconditional)
259{
260        int i, n, fd, changed=0;
261
262        for(i = 0; i < SCRIPT_NUM_PARAMS; i++)
263        {
264                if (script_loaded_params[i] != conf.ubasic_vars[i]) changed++;
265                script_loaded_params[i] = conf.ubasic_vars[i];
266        }
267        if (!unconditional && !changed) return;
268
269        if (cfg_name[0] == 0) set_params_values_name(conf.script_file, -1);
270        fd = open(cfg_name, O_WRONLY|O_CREAT, 0777);
271        if (fd >= 0)
272        {
273                sprintf(ubasic_scriptparam_buf, " %d\n\0", conf.script_param_set);
274                write(fd, ubasic_scriptparam_buf, strlen(ubasic_scriptparam_buf));
275                close(fd);
276        }
277       
278        // open and read file
279        set_params_values_name(conf.script_file, conf.script_param_set);
280        fd = open(cfg_set_name, O_WRONLY|O_CREAT, 0777);
281        if (fd < 0) return;
282        ubasic_scriptparam_buf[0] = 0;
283        for(n = 0; n < SCRIPT_NUM_PARAMS; ++n)
284        {
285                if (script_params[n][0] != 0)
286                {
287                        strcat(ubasic_scriptparam_buf, "@param ");
288                        i = strlen(ubasic_scriptparam_buf);
289                        ubasic_scriptparam_buf[i] = 'a'+n;
290                        strcpy(ubasic_scriptparam_buf+i+1, " \0");
291                        strcat(ubasic_scriptparam_buf, script_params[n]);
292                        strcat(ubasic_scriptparam_buf, "\n@default ");
293                        i = strlen(ubasic_scriptparam_buf);
294                        ubasic_scriptparam_buf[i] = 'a'+n;
295                        sprintf(ubasic_scriptparam_buf+i+1, " %d\n\0", conf.ubasic_vars[n]);
296                }
297        }
298        write(fd, ubasic_scriptparam_buf, strlen(ubasic_scriptparam_buf));
299        close(fd);
300}
301
302
303
304//-------------------------------------------------------------------
305void script_load(const char *fn, int saved_params) {
306    int fd=-1, i, update_vars;
307   
308//    save_params_values(0);
309
310    state_ubasic_script = ubasic_script_default;
311    update_vars = (strcmp(fn, conf.script_file) != 0) || !saved_params || (saved_params == 2);  // update if new file
312
313    if (!fn[0]) { // load internal script
314        if (!conf.script_file[0]) { // internal script was used last time
315            fd = open(SCRIPT_DEFAULT_FILENAME, O_RDONLY, 0777);
316            if (fd>=0) {
317                fn = SCRIPT_DEFAULT_FILENAME;
318                update_vars = 1;
319            }
320        }
321    } else {
322        fd = open(fn, O_RDONLY, 0777);
323        if (fd<0) {
324            conf.script_file[0]=0;
325            update_vars = 1;
326        }
327    }
328
329    if (fd>=0){
330        int rcnt = read(fd, ubasic_script_buf, SCRIPT_BUF_SIZE);
331        if (rcnt > 0){
332            if (rcnt == SCRIPT_BUF_SIZE) { /* FIXME TODO script is too big? */
333                ubasic_script_buf[SCRIPT_BUF_SIZE-1] = 0;
334            } else
335                ubasic_script_buf[rcnt] = 0;
336            state_ubasic_script = ubasic_script_buf;
337        }
338        close(fd);
339        strcpy(conf.script_file, fn);
340    }
341
342    if (update_vars) {
343        for (i=0; i<SCRIPT_NUM_PARAMS; ++i) {
344            conf.ubasic_vars[i] = 0;
345            script_loaded_params[i] = 0;
346        }
347    }
348    script_scan(fn, update_vars);
349        if (saved_params) load_params_values(fn, update_vars, (saved_params!=2));       
350    gui_update_script_submenu();
351}
352
353//-------------------------------------------------------------------
354void script_console_clear() {
355    register int i;
356
357    for (i=0; i<SCRIPT_CONSOLE_NUM_LINES; ++i) {
358        script_console_buf[i][0]=0;
359    }
360    script_console_lines=0;
361    draw_restore();
362}
363
364//-------------------------------------------------------------------
365void script_console_draw() {
366    register int i, l;
367    static char buf[8];
368
369    for (i=0; i<script_console_lines; ++i) {
370        l=strlen(script_console_buf[i]);
371        draw_txt_string(SCRIPT_CONSOLE_X, SCRIPT_CONSOLE_Y+SCRIPT_CONSOLE_NUM_LINES-script_console_lines+i, script_console_buf[i], MAKE_COLOR(COLOR_BG, COLOR_FG));
372        for (; l<SCRIPT_CONSOLE_LINE_LENGTH; ++l)
373            draw_txt_char(SCRIPT_CONSOLE_X+l, SCRIPT_CONSOLE_Y+SCRIPT_CONSOLE_NUM_LINES-script_console_lines+i, ' ', MAKE_COLOR(COLOR_BG, COLOR_FG));
374    }
375
376}
377
378static int  print_screen_p;             // print_screen predicate: 0-off 1-on.
379static int  print_screen_d = -1;        // print_screen file descriptor.
380//static const char print_screen_file[] ="A/CHDK/SCRIPTS/PR_SCREEN.TXT";
381static const char print_screen_file_prefix[] = "A/CHDK/LOGS/LOG_";
382char print_screen_file[25];
383static const char extension_txt[] = ".TXT";
384
385void script_print_screen_init()
386{
387  print_screen_p = 0;
388  if (print_screen_d >= 0) {
389    close(print_screen_d);
390    print_screen_d = -1;
391  }
392}
393
394void script_print_screen_end()
395{
396  if (print_screen_d >= 0) {
397    close(print_screen_d);
398    print_screen_d = -1;
399    print_screen_p = 0;
400  }
401}
402
403void script_print_screen_statement(int val)
404{
405  print_screen_p = val;
406  if (val) {
407    if (print_screen_d>=0) close(print_screen_d);
408    int i=0;
409    int c=0;
410    static char file_number[5];
411    strcpy(print_screen_file, print_screen_file_prefix);
412    if (val<0) val = -val;
413    while (val > 9999) val += -10000;
414    for (i=10; i<=1000; i=i*10) { if (val<i) ++c; }
415    for (i=1; i<=c; ++i) { sprintf(file_number, "%d", 0); strcat(print_screen_file, file_number); }
416    sprintf(file_number, "%d", val);
417    strcat(print_screen_file, file_number);
418    strcat(print_screen_file, extension_txt);
419    print_screen_d = open(print_screen_file, O_WRONLY|O_CREAT|O_TRUNC, 0777);
420  }
421}
422
423//-------------------------------------------------------------------
424
425static void script_console_add_impl(const char *str) {
426    register int i;
427
428    if (script_console_lines == SCRIPT_CONSOLE_NUM_LINES ) {
429        for (i=1; i<SCRIPT_CONSOLE_NUM_LINES; ++i) {
430            strcpy(script_console_buf[i-1], script_console_buf[i]);
431        }
432        --script_console_lines;
433    }
434
435    if (strlen(str) > SCRIPT_CONSOLE_LINE_LENGTH) {
436      // let overlong lines wrap to the next line
437      memcpy(script_console_buf[script_console_lines], str, SCRIPT_CONSOLE_LINE_LENGTH);
438      script_console_buf[script_console_lines][SCRIPT_CONSOLE_LINE_LENGTH]=0;
439      ++script_console_lines;
440      script_console_add_impl(str+SCRIPT_CONSOLE_LINE_LENGTH);
441      return;
442    }
443    else
444      strcpy(script_console_buf[script_console_lines], str);
445   
446    ++script_console_lines;
447}
448
449void script_console_add_line(const char *str) {
450    script_console_add_impl(str);
451
452    if (print_screen_p && print_screen_d>=0) {
453      char nl = '\n';
454      write(print_screen_d, str, strlen(str) );
455      write(print_screen_d, &nl, 1);
456    }
457
458    script_console_draw();
459}
460
461//-------------------------------------------------------------------
462//-------------------------------------------------------------------
463//-------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.