/********** gpm.c *****************************************************/ #define GPMBUILTIN_C_ #include "gpmdefs.h" #include "gpm.h" #include "gpmmain.h" #include "gpmmonitor.h" #include "gpmbuiltin.h" #ifdef DEBUG_MACROS static char *begin="\n------ BEGIN %s.\n\n"; static char *end ="\n------ END %s.\n\n"; #endif void do_def() { /* * length of "DEF" + 1 = 4 * D * E * F * length of first arg + 1 <-- P+6 * first arg * length of second arg + 1 * second arg * */ int start_of_args; int length1,length2; start_of_args=P+6; length1 = Stack[start_of_args]; if (length1==Marker) Monitor(BadDEF1); length2 = Stack[start_of_args + length1]; /* * Let's say somebody types {DEF|a}. Then the stack contains * * * D * E * F * ^B (value 2) * a * Marker * * Start_of_args points to the ^B. So if length2 == Marker, * we've got a DEF with no second argument. Bummer. */ if (length2==Marker) Monitor(BadDEF); Stack[start_of_args + length1 + length2] = Marker; if (H != 0) Stack[H] = Stack[H] - Stack[P - 1] + 6; Stack[P - 1] = 6; Stack[P + 5] = EnvPtr; EnvPtr = P + 5; } void do_update() { int r; /* * In a call to UPDATE, the stack looks like this: * * UPDATE arg0 <-- P * xxx admin * n length of arg1 * arg1 * m * arg2 * Marker */ Find(P + 9); A = P + 9 + Stack[P + 9]; if (Stack[A] > Stack[W]) Monitor9(); for (r = 1; r <= Stack[A]; r++) Stack[W + r] = Stack[A + r]; } void do_len() { LoadC(Stack[P+6]-1); } void do_ifdef() { int i; i=iFind(P+8); if (i<0) LoadC(0); else LoadC(1); } void do_val() { /* * Lookup the macro that is the first argument, * then copy it (Find leaves W pointing to the * definition.) to the stack. */ Find(P + 6); if (Stack[W]<0) { LoadS(""); return; } W=W+1; while (Stack[W] != Marker) { LoadC(Stack[W++]); } } void do_bin() { int Value=0; int StackScan; /* * Put the binary equivalent of argument 1 in value, and then push * it on the stack. The stack now looks like this: * * P -> 'B' * 'I' * 'N' * x * x 4 items of administration from the ArgSep * x * x * Argument 1 * * * So you can start from P+7 to check the argument. * */ /* * If there's a leading + or -, deal with it. */ if (Stack[P+7]=='+' || Stack[P+7]=='-') { StackScan=P+8; } else { StackScan=P+7; } while (Stack[StackScan] != Marker) { int x = Num(Stack[StackScan]); if (x < 0 || x > 9) Monitor10(); Value = 10 * Value + x; StackScan++; } /* * Now check the leading sign, if any, again, so that * the correct value is pushed to the stack. */ if (Stack[P+7]=='-') { Push(-Value); } else { Push(Value); } #ifdef DEBUG fprintf(stderr,"BIN has value %d.\n",Value); #endif } void do_dec() { char b[16]; if (Stack[P+6]!=2) { Monitor(BadDEC); LoadC('0'); return; } W = Stack[P + 7]; sprintf(b,"%d",W); LoadS(b); } void do_bar() { int result; int A; if (Stack[P+6]!=2 || Stack[P+8]!=2 || Stack[P+10]!=2) { Monitor(BadBARcall); LoadC(0); return; } W = Stack[P + 9]; A = Stack[P + 11]; switch(Stack[P+7]) { case '+' : result = W + A; break; case '-' : result = W - A; break; case '*' : result = W * A; break; case '/' : result = W / A; break; case 'R' : case '%' : result = W % A; break; case '=' : if (W==A) result=1; else result=0; break; case '<' : if (W' : if (W>A) result=1; else result=0; break; default : Monitor(BadBAROp); result=0; break; } LoadC(result); } void do_sub() { int begin,len; int argl; int i; /* Stack looks like this: * * SUB <- P * xxx administration * n length of arg1 * arg1 * m length of arg2 * arg2 * p length of arg3 * arg3 * Marker * * n and m must be two (numbers resulting from BAR). */ if (Stack[P+6]!=2) Monitor(BadSUBcall); begin=Stack[P+7]; if (Stack[P+8]!=2) Monitor(BadSUBcall); len=Stack[P+9]; argl=Stack[P+10]; /* Length of arg3 */ if (begin<1 || begin>argl) { Monitor(BadSUBshort); return; } if ((begin+len)>argl) { Monitor(BadSUBlong); len=argl-begin; } for (i=0; i127) { i=i-128; if (i<32) { sprintf(b,"M-^%c",i+64); return b; } if (i<128) { sprintf(b,"M-%c",i); return b; } b[0]=0; return b; } sprintf(b,"%c",i); return b; } void do_dumpf(int count) { static char *dump="Stack dump"; int i; fflush(stdout); fprintf(stderr,begin,dump); fprintf(stderr,"[%4d] ",count); while (count<=StackPtr) { for (i=0; i<4; i++) { fprintf(stderr,"%8d (%4s) ", Stack[count],do_dumpc(Stack[count])); count++; } if (count<=StackPtr) fprintf(stderr,"\n[%4d] ",count); } fprintf(stderr,"\n\nCurrent stack state is: \n\nSize=%8d Top =%8d\n", StackSize,StackPtr); fprintf(stderr,"In =%8d Out =%8d Env =%8d\n",InputPtr,OutputPtr,EnvPtr); fprintf(stderr,end,dump); } void do_dump() { /* Stack contents are: * * x <- P points here. * x * ^D (4) * D * U * M * P * <- if here is a marker, then the call was {DUMP} * if not, then this is the length of the first * argument. It should be two, since the argument * is a single *INTEGER* (result of BIN, probably). * * */ int start_args=P+7; int arg_len=Stack[start_args]; int start_dump=0; if (arg_len==Marker) { do_dumpf(start_dump); } else { if (arg_len==2) { start_dump=Stack[start_args+1]; if (start_dump>StackPtr || start_dump<0) { Monitor(BadDUMPrange); } else { do_dumpf(start_dump); } } else { do_dumpf(start_dump); Monitor(BadDUMP); } } } void do_output(FILE *stream) { #define ERRBUFSIZE (128) static char b[ERRBUFSIZE+10]; int bp=0; int scan=P+7; while(Stack[scan]!=Marker) { b[bp]=(char)Stack[scan++]; bp++; if (bp==ERRBUFSIZE) { b[bp]=0; fprintf(stream,"%s",b); bp=0; } } if (bp>0) { b[bp]=0; fprintf(stream,"%s",b); } #undef ERRBUFSIZE } void do_msg() { fflush(stdout); do_output(stderr); } void do_exit() { Monitor(Exit); } #endif