/* pbrain interpreter in old-style C This is an interpreter for Paul M. Parks's pbrain programming language, a variant of Urban Mueller's programming language. Do anything you want with this program. I welcome bug reports and feature requests. Daniel B Cristofani (http://www.hevanet.com/cristofd/) 20130327, extended and put into service as cbrain 20210410, core parts moved to CMS VM/370 CE cbrain btiffin (https://sourceforge.net/users/btiffin) Tectonics: global txtlib gcclib gcc cbrain (cms load cbrain start | start * prog genmod cbrain cbrain prog */ #include #include #include #include #include #define VERSION 0.6 #define SIZE 65536 #define PROCEDURES 256 #define NUMBITS sizeof(long)*8 #define CA(x) case x: fprintf(stderr, "Error: " long a[SIZE], memreg; int s[SIZE], sp, ptable[PROCEDURES], t[SIZE], p, q, length; int c, tmp, scale, tracer, tracing; char code[SIZE], *f, bin[NUMBITS+1]; FILE *input; const char *long_to_binary(unsigned long x) { unsigned long i=1UL << NUMBITS-1; char *d=bin; while (i>>=1) *d++=(i & x)?'1':'0'; *d++='\0'; return bin; } int e(int i){ switch(i){ CA(2) "call to undefined procedure (%hu) with %d at %d of %s", a[p], p, q, f); break; CA(3) "pointer too far %s at %d of %s", p>0?"right":"left", q, f); break; CA(4) "unmatched '[' at byte %d of %s", s[sp], f); break; CA(5) "unmatched ']' at byte %d of %s", q, f); break; CA(6) "unmatched '(' at byte %d of %s", s[sp], f); break; CA(7) "unmatched ')' at byte %d of %s", q, f); break; CA(8) "can't open %s", f); break; CA(9) "unmatched '{' at byte %d of %s", s[sp], f); break; CA(10) "unmatched '}' at byte %d of %s", q, f); break; CA(11) "unmatched '\"' at byte %d of %s", q, f); break; CA(12) "divide by zero at byte %d of %s", q, f); break; } printf(".\n"); scale=0; return(i); } int callcms(int val) { int cnt = 0; int lim = 130; char cmsstr[130], *d=cmsstr; int r=0; while ((tmp=(code[++q]!='"')) && (q < [ ] , .\n"); printf("pbrain: ( ) :\n"); printf("cbrain: { } 0 1 2 3 4 5 6 7 8 9\n"); printf(" * / ??' & | ??- %% @ ! # = \"\n"); printf(" a b c d f g h l m n o q\n"); printf(" r s t x\n"); printf("HELP | FILE name type\n"); printf("See FSHELP CBRAIN for more details\n"); return; } int cbrain(long *a, char *args){ if (strncmp("HELP", args, 4) == 0) { cbhelp(); return 0; } else if (strncmp("FILE ", args, 5) == 0) { if (args[strlen(args)-1] == '\n') args[strlen(args)-1] = '\0'; args += 5; if(!(input = fopen(f=args, "r"))) { e(8); return(0); } length = fread(code, 1, SIZE, input); fclose(input); memset(a, 0, SIZE); } else { f = "cbrain"; length=strlen(args); strncpy(code, args, SIZE); } /* Start up cbrain */ scale=0; for(q=0;q': if(++p>=SIZE) {e(3); p=SIZE; return(-1);} scale=0; break; case '.': putchar(a[p]==10?'\n':a[p]); scale=0; break; case ',': if((c=getchar())!=EOF) a[p]=c=='\n'?10:c; scale=0; break; case '[': if(!a[p]) q=t[q]; scale=0; break; case ']': if(a[p]) q=t[q]; scale=0; break; /* pbrain */ case '(': ptable[a[p]]=q; q=t[q]; scale=0; break; case ')': q=s[--sp]; scale=0; break; case ':': s[sp++]=q; if((q=ptable[a[p]])<0) e(2); scale=0; break; /* cbrain */ case '{': tmp=1; while(tmp&&q++>=a[p+1]; scale=0; break; case 'l': case 'L': if(p<1) {e(3); return(0);} a[--p]<<=a[p+1]; scale=0; break; case '0': a[p]*=(scale++>0)?10:0; break; case '1': a[p]*=(scale++>0)?10:0; a[p]+=1; break; case '2': a[p]*=(scale++>0)?10:0; a[p]+=2; break; case '3': a[p]*=(scale++>0)?10:0; a[p]+=3; break; case '4': a[p]*=(scale++>0)?10:0; a[p]+=4; break; case '5': a[p]*=(scale++>0)?10:0; a[p]+=5; break; case '6': a[p]*=(scale++>0)?10:0; a[p]+=6; break; case '7': a[p]*=(scale++>0)?10:0; a[p]+=7; break; case '8': a[p]*=(scale++>0)?10:0; a[p]+=8; break; case '9': a[p]*=(scale++>0)?10:0; a[p]+=9; break; case '=': scanf("%d", &a[p]); scale=0; break; case 'n': case 'N': fprintf(stdout, "%d", a[p]); scale=0; break; case 'h': case 'H': fprintf(stdout, "%x", a[p]); scale=0; break; case 'b': case 'B': fprintf(stdout, "%32s", long_to_binary(a[p])); scale=0; break; case 'f': case 'F': fprintf(stdout, "%f", (float)a[p]); scale=0; break; case '#': fprintf(stdout, "%010ld ", a[p]); scale=0; break; case 'x': case 'X': tmp=a[p];a[p]=a[p-1];a[p-1]=tmp; scale=0; break; case 'c': case 'C': if(p>=SIZE) {e(3); return(0);} a[++p]=a[p-1]; scale=0; break; case 'o': case 'O': if(p<1||p>=SIZE) {e(3); return(0);} a[++p]=a[p-2]; scale=0; break; case '@': memreg=a[p]; scale=0; break; case '!': a[p]=memreg; scale=0; break; case '"': a[p]=callcms(a[p]); scale=0; break; case '?': tmp=p; while(tmp-->=0) printf("[%05d is %020ld]\n", tmp+1, a[tmp+1]); scale=0; break; case 't': case 'T': tracer=(tracer?0:1); scale=0; break; case 'g': case 'G': return (p); case 'q': case 'Q': return(-1); default: scale=0; } if (tracing && !isspace(code[q])) { fprintf(stderr, " after %05d is %020ld]\n", p, a[p]); tracing=0; } } return(p); } int main(int argc, char *argv[]) { char *line; int rc = 0; line = malloc(255); if (line && (argc > 1)) { line[0] = '\0'; strcat(line, "FILE "); strncat(line, argv[1], 8); strcat(line, " CB A"); rc = cbrain(a, line); fflush(stdout); } while (line && (rc != -1)) { line = fgets(line, 255, stdin); rc = cbrain(a, line); fflush(stdout); clearerr(stdin); } free(line); return rc; }