source: trunk/core/script.c @ 979

Revision 979, 11.8 KB checked in by reyalp, 3 years ago (diff)

decouple console from script, based on patch from ultimA in http://chdk.setepontos.com/index.php?topic=5793.msg57064#msg57064 with some modifications, see http://chdk.setepontos.com/index.php?topic=5793.msg57206#msg57206
note set_console_autoredraw has been made non-op in this patch, and will likely be removed completely.

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