source: tags/arb_5.3/AISC/aisc_commands.c

Last change on this file was 5968, checked in by westram, 15 years ago
  • new flag -w to aisc_mkpt (add include wrapper)
  • uniform style for several include wrappers
  • removed duplicated includes
  • removed useless nt_concatenate.hxx
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.7 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <stdarg.h>
4#include <string.h>
5#include <unistd.h>
6/* #include <malloc.h> */
7#include <memory.h>
8
9#include "aisc.h"
10
11int contains_tabs = 0;
12static int error_count = 0;
13
14void print_error_internal(const char *err, const char *launcher_file, int launcher_line) {
15    fprintf(stderr, "./%s:%i: Error: %s\n", gl->pc->path, gl->pc->linenr, err);
16    if (launcher_file) fprintf(stderr, "../AISC/%s:%i: error was launched from here\n", launcher_file, launcher_line);
17    error_count++;
18}
19
20void print_warning_internal(const char *err, const char *launcher_file, int launcher_line) {
21    fprintf(stderr, "./%s:%i: Warning: %s\n", gl->pc->path, gl->pc->linenr, err);
22    if (launcher_file) fprintf(stderr, "../AISC/%s:%i: error was launched from here\n", launcher_file, launcher_line);
23}
24
25#define ERRBUFSIZE 200
26const char *formatted(const char *format, ...) {
27    /* goes to header:  __ATTR__FORMAT(1) */
28
29    static char *errbuf = 0;
30    if (!errbuf) { errbuf = (char*)malloc(ERRBUFSIZE+1); }
31
32    va_list argPtr;
33    va_start(argPtr, format);
34    int     chars = vsprintf(errbuf, format, argPtr);
35    if (chars>ERRBUFSIZE) {
36        fprintf(stderr, "%s:%i: Error: Buffer overflow!\n", __FILE__, __LINE__);
37        vfprintf(stderr, format, argPtr);
38        fputc('\n', stderr);
39
40        va_end(argPtr);
41        exit(EXIT_FAILURE);
42    }
43    va_end(argPtr);
44
45    return errbuf;
46}
47#undef ERRBUFSIZE
48
49static void memcopy(char *dest, const char *source, int len)
50{
51    int         i;
52    const char *s;
53    char       *d;
54
55    i = len;
56    s = source;
57    d = dest;
58    if (s < d) {
59        s += i;
60        d += i;
61        while (i--) {
62            *(--d) = *(--s);
63        }
64    } else {
65        while (i--) {
66            *(d++) = *(s++);
67        }
68    }
69}
70
71static char *find_string(const char *str,const char *key)
72{
73    const char *p1,*p2;
74    for (p1=str,p2=key;*p1;) {
75        if (!*p2) {
76            return (char*)(str);
77        }else{
78            if (*p2==*p1){
79                p1 ++; p2++;
80            }else{
81                p2 = key;
82                p1 = (++str);
83            }
84        }
85    }
86    if (!*p2) return (char*)(str);
87    return 0;
88}
89
90static char *calc_rest_line(/*const*/ char *str, int size, int presize)
91{
92    /* wertet einen Puffer str aus , str[-1] muss exestieren !!! */
93    char *ld;
94    char *p;
95    char *br;
96    char *path;
97    char *fi;
98    int lenf, len;
99    char *lastbr;
100    char c;
101
102    ld = find_string(&str[2], "$(");
103    fi = 0;
104    if (ld) {
105        lastbr = calc_rest_line(ld, size - (ld - str),presize+2);
106        if (!lastbr)
107            return 0;
108    }else{
109        lastbr = str+2;
110    }
111    p = str+2;
112    READ_SPACES(p);
113    if (*p == 0) {
114        print_error("unbalanced brackets; EOL found");
115        return 0;
116    }
117    br = strchr(p, ')');
118    if (!br) {
119        fprintf(stderr, "%s#%s\n",str,lastbr);
120        print_error("unbalanced brackets; missing ')'");
121        return 0;
122    }
123    *br = 0;
124    br++;
125    if (*p == 0) {              /* empty $() */
126        fi = strdup("");
127    }else if (presize && (str[-1] == '$')) {    /* quoted */
128        br[-1] = ')';
129        c = *br; *br = 0;
130        fi = strdup(str+1);
131        /*printf("%s#%s\n",fi,br);*/
132        *br = c;
133    }else if (*p == '+') {
134        path = p + 1;
135        READ_SPACES(path);
136        fi = strpbrk(path, "+,");
137        if (!fi) {
138            print_error("NO '+,;' found in ADD FUNCTION");
139            return 0;
140        }
141        *(fi++) = 0;
142        READ_SPACES(fi);
143        sprintf(string_buf, "%li", atol(path) + atol(fi));
144        fi = strdup(string_buf);
145    }else if (*p == '*') {
146        path = p + 1;
147        READ_SPACES(path);
148        fi = strpbrk(path, "*,");
149        if (!fi) {
150            print_error("NO '*,;' found in ADD FUNCTION");
151            return 0;
152        }
153        *(fi++) = 0;
154        READ_SPACES(fi);
155        sprintf(string_buf, "%li", atol(path) * atol(fi));
156        fi = strdup(string_buf);
157    } else if (*p == '#') {
158        if (!strncmp(p, "#FILE", 5)) {
159            for (path = p + 5; gl->s2_tab[(unsigned)(path[0])]; path++) ;
160            fi = read_aisc_file(path);
161            if (!fi) return 0;
162
163            {
164                int         file_len      = strlen(fi);
165                const char *previous_file = gl->line_path ? gl->line_path : "unknown.file";
166                int         previous_line = gl->line_path ? gl->line_cnt : 0;
167                int         buflen        = file_len+strlen(path)+strlen(previous_file)+100;
168                char       *buffer        = (char *)malloc(buflen);
169
170                /* Inject code to restore correct code file and line (needed for proper error messages) */
171                int printed = sprintf(buffer, "@SETSOURCE %s,%i@%s@SETSOURCE %s,%i@", path, 1, fi, previous_file, previous_line);
172
173                if (printed >= buflen) {
174                    fprintf(stderr, "%s:%i: Error: buffer overflow\n", __FILE__, __LINE__);
175                }
176
177                free(fi);
178                fi = buffer;
179            }
180        }
181        else {
182            printf_error("unknown Var_Command '%s'", p);
183            return 0;
184        }
185    } else {
186        fi = get_var_string(p);
187    }
188    if (fi) {
189        lenf = strlen(fi);
190        len = strlen(br);
191        if (len + lenf > size) {
192            print_error("bufsize exceeded");
193            return 0;
194        }
195        memcopy(str + lenf, br, len + 1);
196        memcpy(str, fi, lenf);
197        free(fi);
198        ld = find_string(str, "$(");
199        if (ld) {
200            lastbr = calc_rest_line(ld, size - (ld - str),presize+(ld-str));
201            if (!lastbr)
202                return 0;
203        }
204        return str+lenf;
205    }
206    if (gl->pc->command != IF) {
207        printf_error("unknown Var_Reference '%s'", p);
208    }
209    return 0;
210}
211
212
213static int calc_line(char *str, char *buf)
214{
215    char           *ld;
216    int             len;
217    char            *lb;
218    len = strlen(str);
219    if (len > gl->bufsize)
220        len = gl->bufsize;
221    memcpy(buf, str, len + 1);
222    ld = find_string(buf, "$(");
223    if (!ld)
224        return 0;
225    contains_tabs = 0;
226    lb = calc_rest_line(ld, gl->bufsize - (ld - buf),ld-buf);
227    if (!lb) return 1;
228    return 0;
229}
230
231static int calc_line2(char *str, char *buf)
232{                               /* erstes $( nicht auswerten ) !!! */
233    char           *ld;
234    char           *lb;
235    int             len;
236    len = strlen(str);
237    if (len > gl->bufsize - 10)
238        len = gl->bufsize - 10;
239    memcpy(buf, str, len + 1);
240    ld = buf;
241    READ_SPACES(ld);
242    ld = find_string(buf, "$(");
243    if (strncmp(ld,"$(",2)) {
244        print_error("No Identifier specified");
245        return 1;
246    }
247    ld = find_string(ld + 2, "$(");
248    contains_tabs = 0;
249    if (ld) {
250        lb = calc_rest_line(ld, gl->bufsize - (ld - buf),2);
251        if (!lb) return 1;
252    }
253    return 0;
254}
255
256static void write_aisc(AD * ad, FILE * out, int deep)
257{
258    AD             *item, *line;
259    int             i;
260    int             flag;
261    for (line = ad; line; line = line->next_line) {
262        for (i = 0; i < deep; i++)
263            fprintf(out, "\t");
264        flag = 0;
265        for (item = line; item; item = item->next_item) {
266            if (flag)
267                fprintf(out, ",");
268            flag = 1;
269            if (item->sub) {
270                fprintf(out, "%s {\n", item->key);
271                write_aisc(item->sub, out, deep + 1);
272                for (i = 0; i <= deep; i++)
273                    fprintf(out, "\t");
274                fprintf(out, "}");
275            } else {
276                fprintf(out, "\t%s (~%s~)", item->key, item->val);
277            }
278        }
279        fprintf(out, ";\n");
280    }
281}
282
283/*
284static void write_prg(CL * cl, FILE * out, int deep)
285{
286    CL             *line;
287    int             i;
288    for (line = cl; line; line = line->next) {
289        for (i = 0; i < deep; i++)
290            fprintf(out, "\t");
291        fprintf(out, "%5i  %s\n", line->linenr, line->str);
292    }
293}
294*/
295
296static int do_com_dbg(char *str)
297{
298    write_aisc(gl->root, stdout, 0);
299    str = str;
300    return 0;
301}
302static int do_com_data(char *str)
303{
304    char           *in;
305    if (strlen(str) < 2) {
306        printf_error("no parameter '%s'", gl->pc->str);
307        return 1;
308    }
309    in = str;
310    gl->lastchar = ' ';
311    gl->line_cnt = 1;
312    gl->line_path = gl->pc->path;
313    gl->root = read_aisc(&in);
314    if (!gl->root) {
315        printf_error("occurred in following script-part: '%s'", gl->pc->str);
316        return 1;
317    }
318    return 0;
319}
320
321static int do_com_write(FILE * out, char *str)
322{
323    char *p;
324    char  c;
325    int   no_nl = 0;
326    int   pos;
327    int   lt, rt;
328
329    p = str;
330    while ( (c = *(p++)) ) {
331        if (c == '$') {
332            c = *(p++);
333            if (!c)
334                break;
335            if (!gl->outtab[(unsigned)(c)]) {
336                if (c == '\\') {
337                    no_nl = 1;
338                    continue;
339                }
340                if ((c >= '0') && (c <= '9')) {
341                    pos = gl->tabs[c - '0'];
342                    if (pos < gl->tabpos)
343                        continue;
344                    lt = gl->tabpos / gl->tabstop;
345                    rt = pos / gl->tabstop;
346                    while (lt < rt) {
347                        putc('\t', out);
348                        lt++;
349                        gl->tabpos /= gl->tabstop;
350                        gl->tabpos++;
351                        gl->tabpos *= gl->tabstop;
352                    }
353                    while (gl->tabpos < pos) {
354                        putc(' ', out);
355                        gl->tabpos++;
356                    }
357
358                    continue;
359                }
360                continue;
361            } else {
362                c = gl->outtab[(unsigned)(c)];
363            }
364        }
365        if (c == '\t') {
366            putc(c, out);
367            gl->tabpos /= gl->tabstop;
368            gl->tabpos++;
369            gl->tabpos *= gl->tabstop;
370        } else if (c == '\n') {
371            if (no_nl) {
372                no_nl = 0;
373            } else {
374                putc(c, out);
375                gl->tabpos = 0;
376            }
377        } else if (c == '@') {
378            if (strncmp(p, "SETSOURCE", 9) == 0) { /* skip '@SETSOURCE file, line@' */
379                p = strchr(p, '@');
380                if (!p) {
381                    print_error("expected '@' after '@SETSOURCE' (injected code)");
382                    return 1;
383                }
384                p++;
385            }
386            else {
387                putc(c, out);
388                gl->tabpos++;
389            }
390        } else {
391            putc(c, out);
392            gl->tabpos++;
393        }
394    }
395    if (!no_nl) {
396        putc('\n', out);
397        gl->tabpos = 0;
398    }
399    return 0;
400}
401
402static int do_com_print(char *str)
403{
404    do_com_write(gl->out, str);
405    return 0;
406}
407static int do_com_print2(char *str)
408{
409    do_com_write(stdout, str);
410    return 0;
411}
412
413static int do_com_tabstop(char *str)
414{
415    int             ts, i;
416    ts = atoi(str);
417    if ((ts < 1) || (ts > 1024)) {
418        print_error("wrong TABSTOP");
419        return 1;
420    }
421    gl->tabstop = ts;
422    for (i = 0; i < 9; i++)
423        gl->tabs[i] = i * ts;
424    return 0;
425}
426
427static int do_com_tab(char *str)
428{
429    int             ts, val;
430    char           *s1, *s2;
431    s1 = strtok(str, " \t,;");
432    s2 = strtok(0, " \t,;");
433    ts = atoi(s1);
434    val = atoi(s2);
435    if ((ts < 0) || (ts > 9)) {
436        print_error("wrong TABCOUNT");
437        return 1;
438    }
439    if ((val < 0) || (val > 1000)) {
440        print_error("wrong TABVALUE");
441        return 1;
442    }
443    gl->tabs[ts] = val;
444    return 0;
445}
446
447static int do_com_error(char *str)
448{
449    print_error(str);
450    return 1;
451}
452
453static int do_com_open(char *str)
454{
455    FILE           *file;
456    int             i;
457    char           *fn;
458    READ_SPACES(str);
459    str = strtok(str, " \t,;\n");
460    fn = strtok(0, " \t,;\n");
461    if (!fn) {
462        print_error("No Filename found (<3)");
463        return 1;
464    }
465    if (strlen(fn) < 3) {
466        printf_error("Filename '%s' too short (<3)", fn);
467        return 1;
468    }
469    for (i = 0; i < OPENFILES; i++) {
470        if (gl->fouts[i]) {
471            if (strcmp(gl->fouts[i], str) == 0) {
472                printf_error("File '%s' already opened", str);
473                return 1;
474            }
475        }
476    }
477    for (i = 0; i < OPENFILES; i++) {
478        if (!gl->fouts[i]) {
479            break;
480        }
481    }
482    if (i == OPENFILES) {
483        print_error("Too many open files");
484        return 1;
485    }
486    file = fopen(fn, "w");
487    if (!file) {
488        printf_error("Cannot open file '%s'", fn);
489        return 1;
490    }
491
492    gl->fouts[i]      = strdup(str);
493    gl->fouts_name[i] = strdup(fn);
494    gl->outs[i]       = file;
495
496    /* fprintf(stderr, "do_com_open creates file '%s' (type='%s')\n", gl->fouts_name[i], gl->fouts[i]); */
497
498    return 0;
499}
500void aisc_remove_files()
501{
502    int             i;
503    for (i = 0; i < OPENFILES; i++) {
504        if (gl->fouts[i]) {
505            fclose(gl->outs[i]);
506            if (gl->fouts_name[i]) {
507                fprintf(stderr, "Unlinking %s\n", gl->fouts_name[i]);
508                unlink(gl->fouts_name[i]);
509            }
510        }
511    }
512}
513
514static int do_com_close(char *str)
515{
516    int             i;
517    READ_SPACES(str);
518    str = strtok(str, " \t,;\n");
519    for (i = 0; i < OPENFILES; i++) {
520        if (gl->fouts[i]) {
521            if (!strcmp(gl->fouts[i], str)) {
522                fclose(gl->outs[i]);
523                /* fprintf(stderr, "do_com_close(%s)\n", gl->fouts_name[i]); */
524                free(gl->fouts[i]);
525                free(gl->fouts_name[i]);
526                gl->fouts[i]      = 0;
527                gl->fouts_name[i] = 0;
528                if (gl->outs[i] == gl->out) {
529                    gl->out = stdout;
530                }
531                return 0;
532            }
533        }
534    }
535    return 0;
536}
537
538static int do_com_out(char *str)
539{
540    int             i;
541    READ_SPACES(str);
542    str = strtok(str, " \t,;\n");
543    for (i = 0; i < OPENFILES; i++) {
544        if (gl->fouts[i]) {
545            if (!strcmp(gl->fouts[i], str)) {
546                gl->out = gl->outs[i];
547                return 0;
548            }
549        }
550    }
551    printf_error("File '%s' not opened for OUT Command", str);
552    return 1;
553}
554
555static int do_com_moveto(char *str)
556{
557    AD             *fo;
558    char           *st;
559    char           *co;
560    char *p;
561    st = find_string(str, "$(");
562    if (!st) {
563        print_error("no $( found");
564        return 1;
565    };
566    st += 2;
567    READ_SPACES(st);
568    co = strchr(st, ')');
569    if (!co) {
570        print_error("no ) found");
571        return 1;
572    };
573    *co = 0;
574    p = strrchr(st, '/');
575    if (p) {
576        fo = aisc_find_var_hier(gl->cursor, st, 0, 0, 0);
577    } else {
578        fo = aisc_find_var_hier(gl->cursor, st, 0, 1, 0);
579    }
580    if (!fo){
581    }else{
582        gl->cursor = fo;
583    }
584    return 0;
585}
586
587static int do_com_set(char *str)
588{
589    char           *st;
590    char           *co;
591    char           *def;
592    struct hash_struct *hs;
593
594    st = find_string(str, "$(");
595    if (!st) {
596        print_error("no $( found");
597        return 1;
598    };
599    st += 2;
600    co = strchr(st, ')');
601    if (!co) {
602        print_error("no ) found");
603        return 1;
604    };
605    *(co++) = 0;
606    def = read_hash_local(st,&hs);
607    if (!def) {
608        printf_error("undefined Ident '%s' in SET (use CREATE first)", st);
609        return 1;
610    }
611    READ_SPACES(co);
612    if (*co == '=') {
613        *(co++) = 0;
614        READ_SPACES(co);
615    }
616    write_hash(hs, st, co);
617    return 0;
618}
619
620static int do_com_create(char *str)
621{
622    char           *st;
623    char           *co;
624    char           *def;
625    st = find_string(str, "$(");
626    if (!st) {
627        print_error("no $( found");
628        return 1;
629    };
630    st += 2;
631    co = strchr(st, ')');
632    if (!co) {
633        print_error("no ) found");
634        return 1;
635    };
636    *(co++) = 0;
637    def = read_hash( gl->st->hs,st);
638    if (def) {
639        printf_error("Ident '%s' in CREATE already defined", st);
640        return 1;
641    }
642    READ_SPACES(co);
643    if (*co == '=') {
644        *(co++) = 0;
645        READ_SPACES(co);
646    }
647    write_hash(gl->st->hs, st, co);
648    return 0;
649}
650
651static int do_com_if(char *str)
652{
653    char           *equ;
654    char           *kom;
655    char           *la;
656    char           *kom2;
657
658    int op = 0;                                     /* 0=   1~ 2< 3> !+8 */
659    for (equ = str;*equ;equ++) {
660        if (*equ =='=') { op = 0; break;}
661        if (*equ =='~') { op = 1; break;}
662        /*if (*equ =='<') { op = 2; break;}
663          if (*equ =='>') { op = 3; break;}*/
664    }
665    la = equ;
666    if (!*la) { // no operator found -> assume condition true, even if empty or undefined
667        return 0;
668    }
669
670    aisc_assert(equ>str);
671    if (equ[-1] == '!') op += 8;
672
673    READ_RSPACES(la);
674    *(++la) = 0;
675    equ++;
676    while (equ) {
677        READ_SPACES(equ);
678        kom2 = kom = strchr(equ, ',');
679        if (kom) {
680            kom2++;
681            READ_RSPACES(kom);
682            *(++kom) = 0;
683        }
684        /* printf("- str='%s' equ='%s'\n", str, equ); */
685        switch (op) {
686            case 0:     if (!strcmp(str, equ)) return 0; break;
687            case 8:     if ( strcmp(str, equ)) return 0; break;
688            case 1:     if ( find_string(str, equ)) return 0; break;
689            case 9:     if (!find_string(str, equ)) return 0; break;
690                /* case 2:     if (strcmp(str, equ)< 0) return 0; break; */
691                /* case 10:if (strcmp(str, equ)>=0) return 0; break; */
692                /* case 3:     if (strcmp(str, equ)> 0) return 0; break; */
693                /* case 11:if (strcmp(str, equ) <= 0) return 0; break; */
694            default :
695                printf_error("Unhandled operator (op=%i)", op);
696                return 1;
697        }
698        equ = kom2;
699    }
700
701    // condition wrong -> goto else
702    gl->nextpc = gl->pc->ELSE->next; 
703    return 0;
704}
705
706static int do_com_for_add(CL *co)
707{
708    struct for_data_struct *fd;
709    fd = (struct for_data_struct *)calloc(sizeof(struct for_data_struct),1);
710    fd->next = co->fd;
711    co->fd = fd;
712    return 0;
713}
714
715static int do_com_for_sub(CL *co)
716{
717    struct for_data_struct *fd;
718    fd = co->fd;
719    if (fd->forstr)
720        free(fd->forstr);
721    co->fd = fd->next;
722    free((char *)fd);
723    return 0;
724}
725
726int do_com_push(const char *str)
727{
728    struct stack_struct *st;
729    st = (struct stack_struct *)calloc(sizeof(struct stack_struct),1);
730    st->cursor = gl->cursor;
731    st->pc = gl->pc;
732    if (gl->sp++ >= STACKSIZE) {
733        print_error("Stack size exceeded");
734        return 1;
735    }
736    st->hs = create_hash(HASHSIZE);
737    st->next = gl->st;
738    gl->st = st;
739    str = str;
740    return 0;
741}
742
743static int do_com_pop(const char *str)
744{
745    struct stack_struct *st;
746    st = gl->st;
747    free_hash(st->hs);
748    if (gl->sp-- <=1) {
749        print_error("Nothing to Pop");
750        return 1;
751    }
752    gl->cursor = st->cursor;
753    gl->st = st->next;
754    free((char *)st);
755    str = str;
756    return 0;
757}
758
759static int do_com_gosub(char *str)
760{
761    char *fn;
762    char *s;
763    char *params,*para,*fpara,*npara=0,*nfpara=0;
764    CL *fun;
765    int err;
766    if (do_com_push("")) return 1;
767    for (s = str; !gl->b_tab[(int)(*s)]; s++) ;
768    if (*s) {
769        *s = 0;
770        s++;
771        READ_SPACES(s);
772        params = strdup(s);
773    }else{
774        params = strdup("");
775    }
776    fn = read_hash(gl->fns,str);
777    if (!fn) {
778        printf_error("Function '%s' not found", str);
779        return 1;
780    }
781    gl->pc = fun = (CL *)atol(fn);
782
783    err = calc_line(gl->pc->str, gl->linebuf);
784    if (err)    return err;
785    fpara = gl->linebuf;
786    READ_SPACES(fpara);
787    for (para = params; *para;para=npara,fpara=nfpara){
788        if (!*fpara) {
789            printf_error("Too many Parameters %s",para);
790            return 1;
791        }
792        for (s = para; !gl->c_tab[(int)(*s)]; s++) ;
793        if (*s) {npara = s+1;READ_SPACES(npara);} else npara = s;
794        *s = 0;
795        for (s = fpara; !gl->c_tab[(int)(*s)]; s++) ;
796        if (*s) {nfpara = s+1;READ_SPACES(nfpara);} else nfpara = s;
797        *s = 0;
798        s = read_hash( gl->st->hs,para);
799        if (s) {
800            printf_error("duplicated formal parameter %s", para);
801            return 1;
802        }
803        write_hash(gl->st->hs, fpara, para);
804    }
805    if (*fpara) {
806        printf_error("Not enough parameters '%s'", fpara);
807        return 1;
808    }
809    gl->nextpc = fun ->next;
810    free(params);
811    return 0;
812}
813
814static int do_com_goto(char *str)
815{
816    char *fn;
817    fn = read_hash(gl->fns,str);
818    if (!fn) {
819        printf_error("Function '%s' not found", str);
820        return 1;
821    }
822    gl->nextpc = ( (CL *)atol(fn) ) ->next;
823    return 0;
824}
825
826static int do_com_return(char *str)
827{
828    gl->nextpc = gl->st->pc->next;
829    if (do_com_pop("")) return 1;
830    str = str;
831    return 0;
832}
833static int do_com_exit(char *str)
834{
835    str = str;
836    return 1;
837}
838
839static int do_com_for(char *str)
840{
841    AD             *fo;
842    char           *st;
843    char           *co;
844    char           *p;
845    char           *eq;
846    struct hash_struct *hs;
847    st = find_string(str, "$(");
848    st += 2;
849    READ_SPACES(st);
850    co = strchr(st, ')');
851    *(co++) = 0;
852    eq = strchr(co, '=');
853    if (eq) {
854        char           *to;
855        *(eq++) = 0;
856        READ_SPACES(eq);
857        to = find_string(eq, "TO");
858        if (!to) {
859            print_error("TO not found in FOR :( FOR $(i) = a TO b )");
860            return 1;
861        }
862        *to = 0;
863        to += 2;
864        READ_SPACES(to);
865        if (do_com_for_add(gl->pc)) return 1;
866        gl->pc->fd->forval = atol(eq);
867        gl->pc->fd->forend = atol(to);
868        if (gl->pc->fd->forval > gl->pc->fd->forend) {
869            gl->nextpc = gl->pc->NEXT->next;
870            return do_com_for_sub(gl->pc);
871        }
872        p = (char *) read_hash_local(st, &hs);
873        if (!p) {
874            printf_error("Undefined Ident '%s' in FOR (use CREATE first)", st);
875            return 1;
876        }
877        sprintf(string_buf, "%li", gl->pc->fd->forval);
878        write_hash(hs, st, string_buf);
879        gl->pc->fd->forstr = strdup(st);
880    } else {
881        p = strrchr(st, '/');
882        if (p)
883            str = p + 1;
884        else
885            str = st;
886        if (p) {
887            fo = aisc_find_var_hier(gl->cursor, st, 0, 0, 0);
888        } else {
889            fo = aisc_find_var_hier(gl->cursor, st, 0, 1, 0);
890        }
891        if (!fo) {
892            gl->nextpc = gl->pc->NEXT->next;
893            return 0;
894        }
895        do_com_for_add(gl->pc);
896        gl->pc->fd->forstr = strdup(str);
897        gl->pc->fd->forcursor = gl->cursor;
898        gl->cursor = fo;
899    }
900    return 0;
901}
902
903static int do_com_next(const char *str)
904{
905    AD             *fo;
906    char           *p;
907    struct hash_struct *hs;
908    if (gl->pc->FOR->fd->forcursor) {
909        fo = aisc_find_var(gl->cursor, gl->pc->FOR->fd->forstr, 1, 1, 0);
910        if (!fo) {
911            gl->cursor = gl->pc->FOR->fd->forcursor;
912            gl->nextpc = gl->pc->FOR->ENDFOR->next;
913            do_com_for_sub(gl->pc->FOR);
914        } else {
915            gl->nextpc = gl->pc->FOR->next;
916            gl->cursor = fo;
917        }
918    } else {
919        gl->pc->FOR->fd->forval++;
920        if (gl->pc->FOR->fd->forval > gl->pc->FOR->fd->forend) {
921            gl->nextpc = gl->pc->FOR->ENDFOR->next;
922            do_com_for_sub(gl->pc->FOR);
923        } else {
924            gl->nextpc = gl->pc->FOR->next;
925            p = read_hash_local(gl->pc->FOR->fd->forstr,&hs);
926            sprintf(string_buf, "%li", gl->pc->FOR->fd->forval);
927            write_hash(hs, gl->pc->FOR->fd->forstr, string_buf);
928        }
929
930    }
931    str = str;
932    return 0;
933}
934
935#define COMMAND(str,string,len,func)                            \
936    if ( string[0] == str[0] && !strncmp(string,str,len)) {     \
937        char *s=str+len;                                        \
938        READ_SPACES(s);                                         \
939        if (func(s)) break;                                     \
940        continue;                                               \
941    }
942
943#define COMMAND_NOFAIL(str,string,len,func)                     \
944    if ( string[0] == str[0] && !strncmp(string,str,len)) {     \
945        char *s=str+len;                                        \
946        READ_SPACES(s);                                         \
947        if (func(s)) return -1;                                 \
948        continue;                                               \
949    }
950
951#define COMMAND2(str,string,len,func)                           \
952    if ( string[0] == str[0] && !strncmp(string,str,len)) {     \
953        char *s=str+len;                                        \
954        if (func(s)) break;                                     \
955        continue;                                               \
956    }
957
958#define COMMAND2_NOFAIL(str,string,len,func)                    \
959    if (string[0] == str[0] && !strncmp(string,str,len)) {      \
960        char *s=str+len;                                        \
961        if (func(s)) return -1;                                 \
962        continue;                                               \
963    }
964
965int run_prg(void) {
966    int err;
967   
968    for (gl->pc = gl->prg; gl->pc; gl->pc = gl->nextpc) {
969        gl->nextpc = gl->pc->next;
970        if (gl->pc->command) {
971            switch (gl->pc->command) {
972                case IF:
973                    if (calc_line(gl->pc->str, gl->linebuf)) {
974                        gl->nextpc = gl->pc->ELSE->next;
975                        break;
976                    }
977                   
978                    if (do_com_if(gl->linebuf))
979                        return 1;
980                    break;
981                case FOR:
982                    if (calc_line2(gl->pc->str, gl->linebuf))
983                        return 1;
984                    if (do_com_for(gl->linebuf))
985                        return 1;
986                    break;
987                case ELSE:
988                    gl->nextpc = gl->pc->IF->ENDIF->next;
989                    break;
990                case NEXT:
991                    if (do_com_next(""))
992                        return 1;
993                    break;
994                case ENDFOR:
995                case ENDIF:
996                    break;
997                default:
998                    break;
999            }
1000            continue;
1001        }
1002        if (!strncmp(gl->pc->str, "MOVETO", 6)) {
1003            if (calc_line2(gl->pc->str + 7, gl->linebuf))
1004                break;
1005            if (do_com_moveto(gl->linebuf))
1006                break;
1007            continue;
1008        }
1009        if (!strncmp(gl->pc->str, "SET", 3)) {
1010            if (calc_line2(gl->pc->str + 4, gl->linebuf))
1011                break;
1012            if (do_com_set(gl->linebuf))
1013                break;
1014            continue;
1015        }
1016        if (!strncmp(gl->pc->str, "CREATE", 6)) {
1017            if (calc_line2(gl->pc->str + 7, gl->linebuf))
1018                break;
1019            if (do_com_create(gl->linebuf))
1020                break;
1021            continue;
1022        }
1023        gl->s_pos = 0;
1024        gl->line_path = 0;
1025        err = calc_line(gl->pc->str, gl->linebuf);
1026        if (err)
1027            return err;
1028
1029        COMMAND2(gl->linebuf,"PRINT",5,do_com_print);
1030        COMMAND2(gl->linebuf,"P ",2,do_com_print);
1031        COMMAND2(gl->linebuf,"P\t",2,do_com_print);
1032        COMMAND(gl->linebuf,"GOSUB",5,do_com_gosub);
1033        COMMAND(gl->linebuf,"CALL",4,do_com_gosub);
1034        COMMAND(gl->linebuf,"GOTO",4,do_com_goto);
1035        COMMAND(gl->linebuf,"RETURN",6,do_com_return);
1036        COMMAND(gl->linebuf,"PUSH",4,do_com_push);
1037        COMMAND(gl->linebuf,"POP",3,do_com_pop);
1038        COMMAND(gl->linebuf,"CONTINUE",8,do_com_next);
1039
1040
1041        COMMAND(gl->linebuf,"OPEN",4,do_com_open);
1042        COMMAND(gl->linebuf,"CLOSE",5,do_com_close);
1043        COMMAND(gl->linebuf,"OUT",3,do_com_out);
1044        COMMAND2_NOFAIL(gl->linebuf,"ERROR",5,do_com_error);
1045        COMMAND(gl->linebuf,"TABSTOP",7,do_com_tabstop);
1046        COMMAND(gl->linebuf,"TAB",3,do_com_tab);
1047        COMMAND(gl->linebuf,"PP",2,do_com_print2);
1048        COMMAND(gl->linebuf,"EXIT",4,do_com_exit);
1049        COMMAND_NOFAIL(gl->linebuf,"DATA",4,do_com_data);
1050        COMMAND(gl->linebuf,"DBG",3,do_com_dbg);
1051
1052        printf_error("Unknown Command '%s'", gl->pc->str);
1053        return -1;
1054    }
1055
1056    aisc_assert(error_count == 0);
1057    return 0;
1058}
Note: See TracBrowser for help on using the repository browser.