/* * naive implementation of "gets" * (big difference from fgets == strips newline character) */ char* sgets(char *s) { char *retval = s; char ch; while ((ch = (char)xgetchar())) { if (ch == 0x0d) /* user typed enter */ { printf("\n"); break; } else if (ch == 0x08) /* user typed backspace */ { printf ("\b"); printf (" "); printf ("\b"); s--; } else /* user typed another character */ { printf("%c", ch); *s++ = ch; } } *s = '\0'; return retval; }
/* Read one line, including the newline, into s. Safely avoids buffer * overruns (but that's kind of pointless because there are several * other places where I'm not so careful). */ static void getline_(char *s) { int c; char *p; fflush(stdout); p = s; while (p < s + INPUT_BUFFER_SIZE - 1) if ((*p++ = xgetchar()) == '\n') { *p = '\0'; return; } p[-1] = '\n'; p[0] = '\0'; while ((c = xgetchar()) != '\n') ; printf("Line too long, truncated to %s\n", s - INPUT_BUFFER_SIZE); }
char *xgets(char *s) { int c; char *buf; xfflush(NULL); buf = s; while ((c = xgetchar()) != EOF && c != '\n') { *buf++ = c; } *buf = '\0'; return (c == EOF && buf == s) ? NULL : s; }
void panic(const char *fmt,...) { va_list ap; printf("panic: "); va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); printf("\n"); printf("--> Press a key on the console to reboot <--\n"); xgetchar(); printf("Rebooting...\n"); exit(1); }
int pager_output(const char *cp) { int action; if (cp == NULL) return(0); for (;;) { if (*cp == 0) return(0); putchar(*cp); /* always emit character */ if (*(cp++) == '\n') { /* got a newline? */ p_freelines--; if (p_freelines <= 0) { printf("%s", pager_prompt1); action = 0; while (action == 0) { switch(xgetchar()) { case '\r': case '\n': p_freelines = 1; action = 1; break; case ' ': p_freelines = p_maxlines; action = 1; break; case 'q': case 'Q': action = 2; break; default: break; } } printf("\r%s\r", pager_blank); if (action == 2) return(1); } } } }
static int process(void) { int val1, val2; if(context.stringmode) { if(matrix[context.pos.y][context.pos.x] == '"') context.stringmode = 0; else push(matrix[context.pos.y][context.pos.x]); return 0; } if(matrix[context.pos.y][context.pos.x] == ' ') return 0; switch(matrix[context.pos.y][context.pos.x]) { /* @ (end) ends program */ case '@': return EOP; case '>': case '<': case '^': case 'v': context.direction = car2dir(matrix[context.pos.y][context.pos.x]); break; /* _ (horizontal if) <boolean value> PC->left if <value>, else PC->right */ case '_': context.direction = (pop() ? LEFT : RIGHT); break; /* | (vertical if) <boolean value> PC->up if <value>, else PC->down */ case '|': context.direction = (pop() ? UP : DOWN); break; /* : (dup) <value> <value> <value> */ case ':': push(val1 = pop()); push(val1); break; /* ? (random) PC -> right? left? up? down? ??? */ case '?': context.direction = rand() % DIRMAX; break; case '+': case '-': case '*': case '/': case '%': val1 = pop(), val2 = pop(); push(binaryfuncs[binaryopcar2index(matrix[context.pos.y][context.pos.x])](val2, val1)); break; case '!': push(!pop()); break; /* ` (greater) <value1> <value2> <1 if value1 > value2, 0 otherwise> */ case '`': push(pop() < pop()); break; /* \ (swap) <value1> <value2> <value2> <value1> */ case '\\': val1 = pop(), val2 = pop(); push(val1); push(val2); break; /* $ (pop) <value> pops <value> but does nothing */ case '$': (void) pop(); break; /* . (pop) <value> outputs <value> as integer */ case '.': printf("%d", pop()); break; /* , (pop) <value> outputs <value> as ASCII */ case ',': putchar(pop()); break; /* # (bridge) 'jumps' PC one farther; skips over next command */ case '#': nextcell(); break; /* ~ (input character) <character user entered> */ case '~': push(xgetchar()); break; case '"': context.stringmode = !context.stringmode; break; /* & (input value) <value user entered> */ case '&': push(getint()); break; case 'p': val1 = pop(), val2 = pop(); matrix[val1][val2] = pop(); break; case 'g': val1 = pop(), val2 = pop(); push(matrix[val1][val2]); break; default: if(isdigit(matrix[context.pos.y][context.pos.x])) push(matrix[context.pos.y][context.pos.x] - '0'); } return 0; }