diff options
Diffstat (limited to 'src/user/app/kbasic')
-rw-r--r-- | src/user/app/kbasic/Makefile | 9 | ||||
-rw-r--r-- | src/user/app/kbasic/basic.h | 75 | ||||
-rw-r--r-- | src/user/app/kbasic/commands.c | 103 | ||||
-rw-r--r-- | src/user/app/kbasic/control.c | 511 | ||||
-rw-r--r-- | src/user/app/kbasic/expr.c | 153 | ||||
-rw-r--r-- | src/user/app/kbasic/kbasic.txt | 19 | ||||
-rw-r--r-- | src/user/app/kbasic/lex.c | 197 | ||||
-rw-r--r-- | src/user/app/kbasic/main.c | 55 | ||||
-rw-r--r-- | src/user/app/kbasic/pppg.bas | 14 | ||||
-rw-r--r-- | src/user/app/kbasic/tables.bas | 15 | ||||
-rw-r--r-- | src/user/app/kbasic/var.c | 19 |
11 files changed, 1170 insertions, 0 deletions
diff --git a/src/user/app/kbasic/Makefile b/src/user/app/kbasic/Makefile new file mode 100644 index 0000000..22bf991 --- /dev/null +++ b/src/user/app/kbasic/Makefile @@ -0,0 +1,9 @@ +Obj = main.o lex.o control.o commands.o var.o expr.o +Out = kbasic.elf + + +include $(SrcPath)/user/app/common.make + +LDFLAGS += -Map kbasic.map +CFLAGS += -Wno-error=missing-braces + diff --git a/src/user/app/kbasic/basic.h b/src/user/app/kbasic/basic.h new file mode 100644 index 0000000..b3491da --- /dev/null +++ b/src/user/app/kbasic/basic.h @@ -0,0 +1,75 @@ +/* A tiny BASIC interpreter */ + +/* + Thank the Internet for providing me with this program. + Please report any bugs/security holes to: katchup@adnab.fr.nf +*/ + +#ifndef DEF_BASIC_H +#define DEF_BASIC_H + + +// Token types +#define DELIMITER 1 +#define VARIABLE 2 +#define NUMBER 3 +#define COMMAND 4 +#define STRING 5 +#define QUOTE 6 + +// Keywords +#define EOL 98 // Special characters +#define FINISHED 99 +#define IF 1 // Control structures +#define THEN 2 +#define FOR 3 +#define NEXT 4 +#define TO 5 +#define GOTO 6 +#define GOSUB 7 +#define RETURN 8 +#define END 9 +#define EXEC 10 +#define LOAD 11 +#define RUN 12 +#define LIST 13 +#define PRINT 20 // Built-in commands +#define INPUT 21 +#define RND 50 // Built-in functions + +// Buffer size definitions +#define TOK_LEN 80 +#define LAB_LEN 10 // Control structures +#define NUM_LAB 100 +#define FOR_NEST 25 +#define SUB_NEST 25 + +// Lexer +extern char *program; // Data for program +extern char *prog_ip; // Program instructino pointer +extern char token[TOK_LEN]; +extern int token_type, tok; +int get_token(); +void putback(); +void find_eol(); +char *load_file(char *fname); + +// Data structures +int* find_var(char *s); // returns a pointer to the variable + +// Program structure +void init(); +extern char *interp_name; /* given by command line argument 0 */ +void load_program(char *); // load and scan labels +void insert_line(char *l, int n); // add line to program +int start(char *entry); // start execution at given point +void serror(int); + +// BASIC commands +void exec_print(), input(); +void assignment(); +void get_exp(int*); + + +#endif + diff --git a/src/user/app/kbasic/commands.c b/src/user/app/kbasic/commands.c new file mode 100644 index 0000000..f60f32a --- /dev/null +++ b/src/user/app/kbasic/commands.c @@ -0,0 +1,103 @@ +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#include "basic.h" + +/* Assign a variable a value. */ +void assignment() +{ + int *var; + int value; + + /* get the variable name */ + get_token(); + if(!isalpha(*token)) { + serror(4); + return; + } + + var = find_var(token); + + /* get the equals sign */ + get_token(); + if(*token!='=') { + serror(3); + return; + } + + /* get the value to assign to var */ + get_exp(&value); + + /* assign the value */ + *var = value; +} + + + +/* Execute a simple version of the BASIC PRINT statement */ +void exec_print() +{ + int answer; + int len=0, spaces; + char last_delim; + + do { + get_token(); /* get next list item */ + if(tok==EOL || tok==FINISHED) break; + if(token_type==QUOTE) { /* is string */ + printf("%s", token); + len += strlen(token); + get_token(); + } + else { /* is expression */ + putback(); + get_exp(&answer); + get_token(); + len += printf("%d", answer); + } + last_delim = *token; + + if(*token==';') { + /* compute number of spaces to move to next tab */ + spaces = 8 - (len % 8); + len += spaces; /* add in the tabbing position */ + while(spaces) { + printf(" "); + spaces--; + } + } + else if(*token==',') /* do nothing */; + else if(tok!=EOL && tok!=FINISHED) serror(0); + } while (*token==';' || *token==','); + + if(tok==EOL || tok==FINISHED) { + if(last_delim != ';' && last_delim!=',') printf("\n"); + } + else serror(0); /* error is not , or ; */ + +} + +/* Execute a simple form of the BASIC INPUT command */ +void input() +{ + int *var; + int tmp; + + get_token(); /* see if prompt string is present */ + if(token_type==QUOTE) { + printf("%s", token); /* if so, print it and check for comma */ + get_token(); + if(*token!=',') serror(1); + get_token(); + } + else printf("? "); /* otherwise, prompt with / */ + + var = find_var(token); /* get the input var */ + + scanf("%d\n", var); /* read input */ + + /* flush input */ + while ((tmp = getchar()) != '\n' && tmp != EOF); +} + diff --git a/src/user/app/kbasic/control.c b/src/user/app/kbasic/control.c new file mode 100644 index 0000000..1ab22ff --- /dev/null +++ b/src/user/app/kbasic/control.c @@ -0,0 +1,511 @@ +#include <stdio.h> +#include <string.h> +// #include <sys/wait.h> +// #include <unistd.h> +#include <ctype.h> +#include <stdlib.h> +#include <setjmp.h> + +#include "basic.h" + +struct label { + char name[LAB_LEN]; + char *p; /* points to place to go in source file*/ +}; +struct for_stack { + int *var; /* counter variable */ + int target; /* target value */ + char *loc; +}; + +struct label label_table[NUM_LAB]; + +char *gstack[SUB_NEST]; /* stack for gosub */ +struct for_stack fstack[FOR_NEST]; /* stack for FOR/NEXT loop */ + +int ftos; /* index to top of FOR stack */ +int gtos; /* index to top of GOSUB stack */ + +char *program, *prog_ip; /* holds expression to be analyzed */ + +char *interp_name; + +jmp_buf e_buf; /* hold environment for longjmp() */ + +char *find_label(); +void scan_labels(); +struct for_stack fpop(); +char *gpop(); +int get_next_label(char *); +void fpush(struct for_stack); +void gosub(), greturn(), gpush(char*), label_init(); +void exec_if(), exec_for(), next(), exec_goto(); +void exec_exec(), exec_load(); +void exec_list(); + +/* initialize variables */ +void init() { + program = NULL; + prog_ip = NULL; + label_init(); +} + +/* Load program and scans labels */ +void load_program (char *p_buf) { + if (program != NULL) { + free(program); + } + + program = p_buf; + scan_labels(); /* find the labels in the program */ +} + +/* Insert line at the right place of program */ +void insert_line(char *l, int n) { + char *a, *b, *p; + int i_n, t, k; + + + if (program == NULL) { + load_program(strdup(l)); + } else { + int prog_l = strlen(program); + + // lookup insert position + // find smallest label above line number + a = (n == 0 ? program : program + prog_l); + i_n = -1; b = program + prog_l; + + for (t = 0; t < NUM_LAB; t++) { + if (label_table[t].name[0]) { + k = atoi(label_table[t].name); + if (k == n) { + a = label_table[t].p; + while (*a != '\n' && a > program) a--; // back to beginning of line + if (*a == '\n') a++; + } + if (k > n && (k < i_n || i_n == -1)) { + i_n = k; + b = label_table[t].p; + while (*b != '\n' && b > program) b--; // back to beginning of line + if (*b == '\n') b++; + if (b < a) a = b; + } + } + } + + p = malloc(prog_l + strlen(l) + 3); + + strncpy(p, program, (a - program)); // copy [0, a[ + p[a - program] = 0; + // if l is an empty line, do not copy. + for (i_n = 0; l[i_n]; i_n++) { + if (!isdigit(l[i_n]) && l[i_n] != '\n' && l[i_n] != '\r') { + strcpy(p + (a - program), l); // copy l + break; + } + } + strcat(p + (a - program), b); // copy [b, end[ + + load_program(p); // reparse labels + } +} + +/* start program execution at given entry point (not necessarily in loaded program) + return values : + - 0 : return on end of input + - 1 : return on error + - 2 : return on "END" statement + - 3 : return on "LOAD" statement +*/ +int start(char *entry) { + ftos = 0; /* initialize the FOR stack index */ + gtos = 0; /* initialize the GOSUB stack index */ + + prog_ip = entry; + if(setjmp(e_buf)) return 1; /* initialize the long jump buffer */ + + do { + token_type = get_token(); + /* check for assignment statement */ + if(token_type==VARIABLE) { + putback(); /* return the var to the input stream */ + assignment(); /* must be assignment statement */ + } + else /* is command */ + switch(tok) { + case LIST: + exec_list(); + break; + case PRINT: + exec_print(); + break; + case GOTO: + exec_goto(); + break; + case IF: + exec_if(); + break; + case FOR: + exec_for(); + break; + case NEXT: + next(); + break; + case INPUT: + input(); + break; + case GOSUB: + gosub(); + break; + case RETURN: + greturn(); + break; + case EXEC: + exec_exec(); + break; + case LOAD: + exec_load(); + return 3; + case RUN: // (re)start program at begining + ftos = gtos = 0; + prog_ip = program; + break; + case END: // end program execution + return 2; + } + } while (prog_ip != NULL && tok != FINISHED); + + return 0; +} + +/* display an error message */ +void serror(int error) +{ + static char *e[]= { + "syntax error", + "unbalanced parentheses", + "no expression present", + "equals sign expected", + "not a variable", + "Label table full", + "duplicate label", + "undefined label", + "THEN expected", + "TO expected", + "too many nested FOR loops", + "NEXT without FOR", + "too many nested GOSUBs", + "RETURN without GOSUB" + }; + printf ("[near '%s' %d %d] E: %s\n", token, tok, token_type, e[error]); + + longjmp(e_buf, 1); /* return to save point */ + exit(0); + +} + +/* Find all labels. */ +void scan_labels() +{ + int addr; + + label_init(); /* zero all labels */ + + if (program == 0) return; /* if no program is loaded, nothing to do. */ + + prog_ip = program; /* prog_ip will go through the program */ + + /* if the first token in the file is a label */ + get_token(); + if(token_type==NUMBER) { + strcpy(label_table[0].name,token); + label_table[0].p=prog_ip; + } + + find_eol(); + do { + get_token(); + if(token_type==NUMBER) { + addr = get_next_label(token); + if(addr==-1 || addr==-2) { + (addr==-1) ?serror(5):serror(6); + } + strncpy(label_table[addr].name, token, LAB_LEN); + label_table[addr].name[LAB_LEN-1] = 0; // null terminate + label_table[addr].p = prog_ip; /* current point in program */ + } + /* if not on a blank line, find next line */ + if(tok!=EOL) find_eol(); + } while(tok!=FINISHED); +} + +/* Return index of next free position in label array. + A -1 is returned if the array is full. + A -2 is returned when duplicate label is found. + */ +int get_next_label(char *s) +{ + register int t; + + for(t=0;t<NUM_LAB;++t) { + if(label_table[t].name[0]==0) return t; + if(!strcmp(label_table[t].name,s)) return -2; /* dup */ + } + + return -1; +} + +/* Find location of given label. A null is returned if + label is not found; otherwise a pointer to the position + of the label is returned. + */ +char *find_label(char *s) +{ + register int t; + + for(t=0; t<NUM_LAB; ++t) + if(!strcmp(label_table[t].name,s)) return label_table[t].p; + return '\0'; /* error condition */ +} + +/* Execute a GOTO statement. */ +void exec_goto() +{ + + char *loc; + + get_token(); /* get label to go to */ + /* find the location of the label */ + loc = find_label(token); + if(loc=='\0') + serror(7); /* label not defined */ + + else prog_ip=loc; /* start program running at that loc */ +} + +/* Initialize the array that holds the labels. + By convention, a null label name indicates that + array position is unused. + */ +void label_init() +{ + register int t; + + for(t=0; t<NUM_LAB; ++t) label_table[t].name[0]='\0'; +} + +/* Execute an IF statement. */ +void exec_if() +{ + int x , y, cond; + char op; + + get_exp(&x); /* get left expression */ + + get_token(); /* get the operator */ + if(!strchr("=<>", *token)) { + serror(0); /* not a legal operator */ + return; + } + op=*token; + + get_exp(&y); /* get right expression */ + + /* determine the outcome */ + cond = 0; + switch(op) { + case '<': + if(x<y) cond=1; + break; + case '>': + if(x>y) cond=1; + break; + case '=': + if(x==y) cond=1; + break; + } + if(cond) { /* is true so process target of IF */ + get_token(); + if(tok!=THEN) { + serror(8); + return; + }/* else program execution starts on next line */ + } + else find_eol(); /* find start of next line */ +} + +/* Execute a FOR loop. */ +void exec_for() +{ + struct for_stack i; + int value; + + get_token(); /* read the control variable */ + if(!isalpha(*token)) { + serror(4); + return; + } + + i.var=find_var(token); /* save its index */ + + get_token(); /* read the equals sign */ + if(*token!='=') { + serror(3); + return; + } + + get_exp(&value); /* get initial value */ + + *(i.var) = value; + + get_token(); + if(tok!=TO) serror(9); /* read and discard the TO */ + + get_exp(&i.target); /* get target value */ + + /* if loop can execute at least once, push info on stack */ + if(value>=*(i.var)) { + i.loc = prog_ip; + fpush(i); + } + else /* otherwise, skip loop code altogether */ + while(tok!=NEXT) get_token(); +} + +/* Execute a NEXT statement. */ +void next() +{ + struct for_stack i; + + i = fpop(); /* read the loop info */ + + (*(i.var))++; + if(*(i.var)>i.target) return; /* all done */ + fpush(i); /* otherwise, restore the info */ + prog_ip = i.loc; /* loop */ +} + +/* Push function for the FOR stack. */ +void fpush(struct for_stack i) +{ + if(ftos>FOR_NEST) + serror(10); + + fstack[ftos]=i; + ftos++; +} + +struct for_stack fpop() +{ + ftos--; + if(ftos<0) serror(11); + return(fstack[ftos]); +} + +/* Execute a GOSUB command. */ +void gosub() +{ + char *loc; + + get_token(); + /* find the label to call */ + loc = find_label(token); + if(loc=='\0') + serror(7); /* label not defined */ + else { + gpush(prog_ip); /* save place to return to */ + prog_ip = loc; /* start program running at that loc */ + } +} + +/* Return from GOSUB. */ +void greturn() +{ + prog_ip = gpop(); +} + +/* GOSUB stack push function. */ +void gpush(char *s) +{ + gtos++; + + if(gtos==SUB_NEST) { + serror(12); + return; + } + + gstack[gtos]=s; + +} + +/* GOSUB stack pop function. */ +char *gpop() +{ + if(gtos==0) { + serror(13); + return 0; + } + + return(gstack[gtos--]); +} + + +/* EXEC function + Forks and runs another instance of the interpreter + */ +void exec_exec() { + + /* TODO + int pid; + + get_token(); + if (token_type==QUOTE) { + pid = fork(); + if (pid < 0) { + printf("Error: could not fork.\n"); + } else { + if (pid == 0) { + execlp(interp_name, interp_name, token, 0); + printf("Error: could not exec.\n"); + exit(0); + } else { + wait(0); + } + } + get_token(); + } else { + serror(0); + } + */ + printf("EXEC not available.\n"); +} + +/* LOAD function + loads a program into interpreter and ends anything currently executing */ +void exec_load() { + char *p_buf; + + get_token(); + if (token_type==QUOTE) { + if (!(p_buf = load_file(token))) { + printf("Error: could not load file %s\n", token); + } else { + load_program(p_buf); + } + } else { + serror(0); + } +} + +/* LIST function + dumps program source text */ +void exec_list() { + get_token(); + + if (program == NULL) { + printf("No program loaded.\n"); + } else { + printf("%s", program); + } +} diff --git a/src/user/app/kbasic/expr.c b/src/user/app/kbasic/expr.c new file mode 100644 index 0000000..3b8d558 --- /dev/null +++ b/src/user/app/kbasic/expr.c @@ -0,0 +1,153 @@ +#include <stdlib.h> + +#include "basic.h" + +void level2(int*), level3(int*), level4(int*), level5(int*), level6(int*), primitive(int*); +void unary(char, int*), arith(char, int*, int*); + +/* Entry point into parser. */ +void get_exp(int *result) +{ + get_token(); + if(!*token) { + serror(2); + return; + } + level2(result); + putback(); /* return last token read to input stream */ +} + +/* Add or subtract two terms. */ +void level2(int *result) +{ + register char op; + int hold; + + level3(result); + while((op = *token) == '+' || op == '-') { + get_token(); + level3(&hold); + arith(op, result, &hold); + } +} + +/* Multiply or divide two factors. */ +void level3(int *result) +{ + register char op; + int hold; + + level4(result); + while((op = *token) == '*' || op == '/' || op == '%') { + get_token(); + level4(&hold); + arith(op, result, &hold); + } +} + +/* Process integer exponent. */ +void level4(int *result) +{ + int hold; + + level5(result); + if(*token== '^') { + get_token(); + level4(&hold); + arith('^', result, &hold); + } +} + +/* Is a unary + or -. */ +void level5(int *result) +{ + register char op; + + op = 0; + if((token_type==DELIMITER) && (*token=='+' || *token=='-')) { + op = *token; + get_token(); + } + level6(result); + if(op) + unary(op, result); +} + +/* Process parenthesized expression. */ +void level6(int *result) +{ + if((*token == '(') && (token_type == DELIMITER)) { + get_token(); + level2(result); + if(*token != ')') + serror(1); + get_token(); + } + else + primitive(result); +} + +/* Find value of number or variable. */ +void primitive(int *result) +{ + + switch(token_type) { + case VARIABLE: + *result = *find_var(token); + get_token(); + return; + case NUMBER: + *result = atoi(token); + get_token(); + return; + case COMMAND: + switch(tok) { + case RND: + *result = rand(); + get_token(); + return; + } + default: + serror(0); + } +} + +/* Perform the specified arithmetic. */ +void arith(char o, int *r, int *h) +{ + register int t, ex; + + switch(o) { + case '-': + *r = *r-*h; + break; + case '+': + *r = *r+*h; + break; + case '*': + *r = *r * *h; + break; + case '/': + *r = (*r)/(*h); + break; + case '%': + t = (*r)/(*h); + *r = *r-(t*(*h)); + break; + case '^': + ex = *r; + if(*h==0) { + *r = 1; + break; + } + for(t=*h-1; t>0; --t) *r = (*r) * ex; + break; + } +} + +/* Reverse the sign. */ +void unary(char o, int *r) +{ + if(o=='-') *r = -(*r); +} + diff --git a/src/user/app/kbasic/kbasic.txt b/src/user/app/kbasic/kbasic.txt new file mode 100644 index 0000000..19131ed --- /dev/null +++ b/src/user/app/kbasic/kbasic.txt @@ -0,0 +1,19 @@ +KBASIC commands + +EXEC "<filename.bas>" fork and run file in a new process +LOAD "<filename.bas>" reset interpreter context and load file, ends all execution +RUN start loaded program at begining +END end execution of program +LIST list program text + +GOTO <label> +IF <a> [=><] <b> THEN <expr> +GOSUB <label> +RETURN +FOR <var> = <a> to <b> +NEXT + +PRINT +INPUT + +RND diff --git a/src/user/app/kbasic/lex.c b/src/user/app/kbasic/lex.c new file mode 100644 index 0000000..055b502 --- /dev/null +++ b/src/user/app/kbasic/lex.c @@ -0,0 +1,197 @@ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> + +#include "basic.h" + +struct commands { /* keyword lookup table */ + char command[20]; + char tok; +} table[] = { /* Commands must be entered lowercase */ + {"print", PRINT}, /* in this table. */ + {"input", INPUT}, + + {"if", IF}, + {"then", THEN}, + {"goto", GOTO}, + {"for", FOR}, + {"next", NEXT}, + {"to", TO}, + {"gosub", GOSUB}, + {"return", RETURN}, + + {"end", END}, + {"run", RUN}, + {"load", LOAD}, + {"list", LIST}, + {"exec", EXEC}, + + {"rnd", RND}, + {"", END} /* mark end of table */ +}; + +char token[TOK_LEN]; +int token_type, tok; + +int look_up(char *s); // lookup keyword +int iswhite(char c); +int isdelim(char c); + + +/* Load a file into a buffer. */ +char* load_file(char *fname) { + FILE *fp; + char *p; + int size; + + if(!(fp=fopen(fname, "rb"))) return 0; + + // Get file size + fseek(fp, 0, SEEK_END); + size = ftell(fp); + p = (char*)malloc(size + 2); + fseek(fp, 0, SEEK_SET); + + // Read file contents + fread(p, size, 1, fp); + fclose(fp); + + /* null terminate the program */ + if (p[size-1] != '\n') p[size++] = '\n'; + p[size] = 0; + + return p; +} + + +/* Find the start of the next line. */ +void find_eol() +{ + while(*prog_ip!='\n' && *prog_ip!='\0') ++prog_ip; + if(*prog_ip) prog_ip++; +} + +/* Get a token. */ +int get_token() +{ + + register char *temp; + + token_type=0; tok=0; + temp=token; + + if(*prog_ip=='\0') { /* end of file */ + *token=0; + tok = FINISHED; + return(token_type=DELIMITER); + } + + while(iswhite(*prog_ip)) ++prog_ip; /* skip over white space */ + + if(*prog_ip=='\r') { /* crlf */ + ++prog_ip; ++prog_ip; + tok = EOL; *token='\r'; + token[1]='\n'; token[2]=0; + return (token_type = DELIMITER); + } + if (*prog_ip=='\n') { /* lf (unix newline) */ + ++prog_ip; + tok = EOL; *token='\n'; token[1] = 0; + return (token_type = DELIMITER); + } + + if(strchr("+-*^/%=;(),><", *prog_ip)){ /* delimiter */ + *temp=*prog_ip; + prog_ip++; /* advance to next position */ + temp++; + *temp=0; + return (token_type=DELIMITER); + } + + if(*prog_ip=='"') { /* quoted string */ + prog_ip++; + while(*prog_ip!='"'&& *prog_ip!='\r' && *prog_ip!='\n') { + if (temp - token < TOK_LEN - 1) *temp++=*prog_ip; + prog_ip++; + } + if(*prog_ip=='\r' || *prog_ip=='\n') serror(1); + prog_ip++;*temp=0; + return(token_type=QUOTE); + } + + if(isdigit(*prog_ip)) { /* number */ + while(!isdelim(*prog_ip)) { + if (temp - token < TOK_LEN - 1) *temp++=*prog_ip; + prog_ip++; + } + *temp = '\0'; + return(token_type = NUMBER); + } + + if(isalpha(*prog_ip)) { /* var or command */ + while(!isdelim(*prog_ip)) { + if (temp - token < TOK_LEN - 1) *temp++=*prog_ip; + prog_ip++; + } + token_type=STRING; + } + + *temp = '\0'; + + /* see if a string is a command or a variable */ + if(token_type==STRING) { + tok=look_up(token); /* convert to internal rep */ + if(!tok) token_type = VARIABLE; + else token_type = COMMAND; /* is a command */ + } + return token_type; +} + + + +/* Return a token to input stream. */ +void putback() +{ + + char *t; + + t = token; + for(; *t; t++) prog_ip--; +} + +/* Look up a a token's internal representation in the + token table. + */ +int look_up(char *s) +{ + register int i; + char *p; + + /* convert to lowercase */ + p = s; + while(*p){ *p = tolower(*p); p++; } + + /* see if token is in table */ + for(i=0; *table[i].command; i++) + if(!strcmp(table[i].command, s)) return table[i].tok; + return 0; /* unknown command */ +} + +/* Return true if c is a delimiter. */ +int isdelim(char c) +{ + if(strchr(" ;,+-<>/*%^=()", c) || c==9 || c=='\r' || c=='\n' || c==0) + return 1; + return 0; +} + +/* Return 1 if c is space or tab. */ +int iswhite(char c) +{ + if(c==' ' || c=='\t') return 1; + else return 0; +} + + + diff --git a/src/user/app/kbasic/main.c b/src/user/app/kbasic/main.c new file mode 100644 index 0000000..1003a7b --- /dev/null +++ b/src/user/app/kbasic/main.c @@ -0,0 +1,55 @@ +#include <stdio.h>
+#include <stdlib.h>
+#include <readline.h>
+
+#include "basic.h"
+
+int main(int argc, char **argv) {
+ char *p_buf;
+
+ srand(0); // not very usefull...
+
+ readline_history hist;
+ hist.str = 0; hist.max = 10;
+
+ interp_name = argv[0];
+ init();
+
+ if(argc == 2) {
+ /* load the program to execute */
+ if(!(p_buf = load_file(argv[1]))) exit(1);
+
+ load_program(p_buf);
+ start(p_buf);
+ } else if (argc == 1) {
+ printf("KBASIC 0.1\n"
+ "Press ^D to quit interpreter.\n\n");
+
+ for (;;) {
+ printf("> ");
+ char *l = freadline(stdin, &hist);
+ if (l == NULL) break;
+
+ if (!strcmp(l, "exit")) {
+ free(l);
+ break;
+ }
+
+ prog_ip = l;
+ get_token();
+ if (token_type == NUMBER) { // label. insert line.
+ insert_line(l, atoi(token));
+ } else { // directly execute
+ start(l);
+ }
+ free(l);
+ }
+ } else {
+ printf("usage:\n\t%s <filename>\trun BASIC file\n", argv[0]);
+ printf("\n\t%s\t\t\tinteractive BASIC interpreter\n", argv[0]);
+ exit(1);
+ }
+
+ return 0;
+}
+
diff --git a/src/user/app/kbasic/pppg.bas b/src/user/app/kbasic/pppg.bas new file mode 100644 index 0000000..32fc050 --- /dev/null +++ b/src/user/app/kbasic/pppg.bas @@ -0,0 +1,14 @@ + +n = RND % 100 +e = 0 + +20 input "Devinez le nombre: ", i +e = e + 1 +if i > n then print "Trop grand !" +if i < n then print "Trop petit !" +if i = n then goto 42 +goto 20 + +42 print "Bravo, vous avez trouvé en ", e, " essais!" +end + diff --git a/src/user/app/kbasic/tables.bas b/src/user/app/kbasic/tables.bas new file mode 100644 index 0000000..31e9ce3 --- /dev/null +++ b/src/user/app/kbasic/tables.bas @@ -0,0 +1,15 @@ +input "Taille de la table: ", k +print "Table d'addition:" +for i = 0 to k + for j = 0 to k + print i+j; + next + print +next +print "Table de multiplication:" +for i = 1 to k + for j = 1 to k + print i * j; + next + print +next diff --git a/src/user/app/kbasic/var.c b/src/user/app/kbasic/var.c new file mode 100644 index 0000000..a49ce61 --- /dev/null +++ b/src/user/app/kbasic/var.c @@ -0,0 +1,19 @@ +#include <ctype.h> + +#include "basic.h" + +int variables[26]= { /* 26 user variables, A-Z */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; + +/* Find a pointer to the value of a variable. */ +int* find_var(char *s) +{ + if(!isalpha(*s)){ + serror(4); /* not a variable */ + return 0; + } + return variables + (toupper(*s)-'A'); +} |