Mercurial > repo
view interps/adjust/adjust.c @ 9554:23f43464694e
<Zarutian> le/rn Frams\xc3\xb3knarflokkurinn/A, now defunct, political party in Iceland. Like its sister party Sj\xc3\xa1lfst\xc3\xa6\xc3\xb0isflokkurinn it is named by the antonym of what it is. (The name means the Progressive Party but they have nearly always been highly regressive). Think dumb Hill-Billies in ill fitting suits and you get their constiuents.
author | HackBot |
---|---|
date | Sun, 30 Oct 2016 14:33:24 +0000 |
parents | 859f9b4339e6 |
children |
line wrap: on
line source
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> typedef unsigned char cell; cell *read_arbitrary_length_string(FILE *fp); void run(cell **code, int lines, int maxline); int main(int argc, char *argv[]) { cell **code; FILE *src; int codespace, codelines = 0, maxline = 0; if (argc != 2) { fprintf(stderr, "Incorrect invocation\n"); return 1; } src = fopen(argv[1], "r"); if (src == NULL) { fprintf(stderr, "Unreadable file\n"); return 2; } codespace = 10; code = malloc(codespace * sizeof(cell*)); if (!code) return 3; for (;;) { int len; if (codelines == codespace) { codespace *= 2; code = realloc(code, codespace * sizeof(cell*)); if (!code) return 4; } code[codelines] = read_arbitrary_length_string(src); if (code[codelines] == NULL) break; len = strlen(code[codelines]); if (len > maxline) maxline = len; codelines++; } fclose(src); run(code, codelines, maxline); free(code); return 0; } cell *addmem(cell *mem, int cursize, int newsize) { mem = realloc(mem, newsize); if (!mem) { fprintf(stderr, "Out of memory\n"); exit(-1); } memset(&mem[cursize], 0, newsize - cursize); return mem; } /* For 2 <= n <= 126, next[n] = n / gpf[n]. */ cell next[127] = { 0, 0, 1, 1, 2, 1, 2, 1, 4, 3, 2, 1, 4, 1, 2, 3, 8, 1, 6, 1, 4, 3, 2, 1, 8, 5, 2, 9, 4, 1, 6, 1, 16, 3, 2, 5, 12, 1, 2, 3, 8, 1, 6, 1, 4, 9, 2, 1, 16, 7, 10, 3, 4, 1, 18, 5, 8, 3, 2, 1, 12, 1, 2, 9, 32, 5, 6, 1, 4, 3, 10, 1, 24, 1, 2, 15, 4, 7, 6, 1, 16, 27, 2, 1, 12, 5, 2, 3, 8, 1, 18, 7, 4, 3, 2, 5, 32, 1, 14, 9, 20, 1, 6, 1, 8, 15, 2, 1, 36, 1, 10, 3, 16, 1, 6, 5, 4, 9, 2, 7, 24, 11, 2, 3, 4, 25, 18 }; /* For 2 <= n <= 126, gpf[n] is n's greatest prime factor. */ cell gpf[127] = { 0, 0, 2, 3, 2, 5, 3, 7, 2, 3, 5, 11, 3, 13, 7, 5, 2, 17, 3, 19, 5, 7, 11, 23, 3, 5, 13, 3, 7, 29, 5, 31, 2, 11, 17, 7, 3, 37, 19, 13, 5, 41, 7, 43, 11, 5, 23, 47, 3, 7, 5, 17, 13, 53, 3, 11, 7, 19, 29, 59, 5, 61, 31, 7, 2, 13, 11, 67, 17, 23, 7, 71, 3, 73, 37, 5, 19, 11, 13, 79, 5, 3, 41, 83, 7, 17, 43, 29, 11, 89, 5, 13, 23, 31, 47, 19, 3, 97, 7, 11, 5, 101, 17, 103, 13, 7, 53, 107, 3, 109, 11, 37, 7, 113, 19, 23, 29, 13, 59, 17, 5, 11, 61, 41, 31, 5, 7 }; cell bitsset[256] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 }; #define LEFT 0 #define UP_LEFT 1 #define UP 2 #define UP_RIGHT 3 #define RIGHT 4 #define DOWN_RIGHT 5 #define DOWN 6 #define DOWN_LEFT 7 #define RIGHT135(d) ((d) = right135((d))) #define RIGHT90(d) ((d) = right90((d))) #define RIGHT45(d) ((d) = right45((d))) #define LEFT45(d) ((d) = left45((d))) #define LEFT90(d) ((d) = left90((d))) static inline int right135(int dir) { return (dir+3)%8; } static inline int right90(int dir) { return (dir+2)%8; } static inline int right45(int dir) { return (dir+1)%8; } static inline int left45(int dir) { return (dir-1)%8; } static inline int left90(int dir) { return (dir-2)%8; } static inline void movefwd(int *x, int *y, int dir, int steps) { if (dir == LEFT || dir == UP_LEFT || dir == DOWN_LEFT) *x -= steps; else if (dir == RIGHT || dir == UP_RIGHT || dir == DOWN_RIGHT) *x += steps; if (dir == UP || dir == UP_LEFT || dir == UP_RIGHT) *y -= steps; else if (dir == DOWN || dir == DOWN_LEFT || dir == DOWN_RIGHT) *y += steps; } #ifdef UNSAFE static inline void checkmove(int x, int y, int w, int h) {} #else static inline void checkmove(int x, int y, int w, int h) { if (x < 0 || y < 0 || x >= w || y >= h) { fprintf(stderr, "Out of bounds\n"); exit(-1); } } #endif static inline void push(cell val, cell **pstack, int *items, int *space) { if (*items == *space) { *pstack = addmem(*pstack, *space, 2**space); *space *= 2; } (*pstack)[(*items)++] = val; } static inline int pop(cell *stack, int *items) { if (*items == 0) return -1; return stack[--(*items)]; } static inline int peek(cell *stack, int items) { if (items == 0) return -1; return stack[items - 1]; } void run(cell **code, int lines, int maxline) { cell acc, *stack1 = NULL, *stack2 = NULL; int stack1size = 10, stack2size = 10; int stack1pos = 0, stack2pos = 0; int dir = UP_RIGHT, codex, codey; int i, *lengths; stack1 = addmem(stack1, 0, stack1size); stack2 = addmem(stack2, 0, stack2size); acc = 0; codex = 0; codey = lines - 1; lengths = malloc(sizeof(int) * lines); for (i = 0; i < lines; i++) lengths[i] = strlen(code[i]); for (;;) { cell c; if (codex >= lengths[codey]) c = '!'; /* lines are padded with ! */ else { c = code[codey][codex]; #ifndef UNSAFE if (c < 32 || c > 126) { fprintf(stderr, "Invalid character\n"); exit(-1); } #endif } /* run the commands */ for (; c > 1; c = next[(size_t) c]) switch(gpf[(size_t) c]) { case 2: { cell tmp; tmp = (acc & 7) << 5; acc >>= 3; acc |= tmp; break; } case 3: { int s1, s2; s1 = peek(stack1, stack1pos); s2 = peek(stack2, stack2pos); if (s2 < s1) { push(acc, &stack2, &stack2pos, &stack2size); LEFT45(dir); movefwd(&codex, &codey, dir, 1); break; } push(acc, &stack1, &stack1pos, &stack1size); if (s2 == s1) { RIGHT45(dir); movefwd(&codex, &codey, dir, 1); break; } if (acc) LEFT90(dir); else RIGHT135(dir); movefwd(&codex, &codey, dir, 1); break; } case 5: { if (acc & 1) acc--; else acc++; break; } case 7: { movefwd(&codex, &codey, dir, bitsset[(size_t) acc]); break; } case 11: { int s1, s2; s1 = peek(stack1, stack1pos); s2 = peek(stack2, stack2pos); if (s1 > s2) acc = pop(stack1, &stack1pos); else if (s2 == -1) acc = 0; else acc = pop(stack2, &stack2pos); break; } case 13: { int s2; s2 = pop(stack2, &stack2pos); if (s2 != -1) putchar(s2); break; } case 17: case 19: { int ch; if (gpf[(size_t) c] == 17) ch = getchar(); else ch = pop(stack2, &stack2pos); if (ch < 0 || ch > 255) /* empty stack/EOF */ { int steps = 0; if (acc & (1<<2)) RIGHT90(dir); steps += (acc & (1<<3)); steps += (acc & (1<<4)); steps += (acc & (1<<7)); movefwd(&codex, &codey, dir, steps); break; } push(ch, &stack1, &stack1pos, &stack1size); break; } case 23: { acc <<= 5; break; } case 29: { int s1, s2, steps = 2; if (acc != 0) break; LEFT45(dir); s1 = peek(stack1, stack1pos); s2 = peek(stack2, stack2pos); if (s2 < s1) steps++; movefwd(&codex, &codey, dir, steps); RIGHT45(dir); break; } case 31: { movefwd(&codex, &codey, dir, 1); break; } case 37: { int s1, s2; s1 = peek(stack1, stack1pos); s2 = peek(stack2, stack2pos); if (s1 == s2) break; if (s1 < s2) push(s1, &stack2, &stack2pos, &stack2size); else push(s2, &stack1, &stack1pos, &stack1size); break; } case 41: { int s1, s2; s1 = peek(stack1, stack1pos); s2 = peek(stack2, stack2pos); if (s1 == s2) break; if (s1 > s2) pop(stack1, &stack1pos); else pop(stack2, &stack2pos); break; } case 43: { acc >>= 1; if (!acc) { movefwd(&codex, &codey, dir, 1); LEFT90(dir); } break; } case 47: { int s1, s2; s1 = peek(stack1, stack1pos); s2 = peek(stack2, stack2pos); if (s1 == s2) break; if (s1 < s2) acc = pop(stack1, &stack1pos); else acc = pop(stack2, &stack2pos); break; } case 53: { int s1, s2; s1 = peek(stack1, stack1pos); s2 = peek(stack2, stack2pos); if (s1 < s2) { cell tmp; tmp = acc & 0xf0; if (acc & 1) tmp |= 8; if (acc & 2) tmp |= 4; if (acc & 4) tmp |= 2; if (acc & 8) tmp |= 1; acc = tmp; } else { cell tmp; tmp = acc & 0x0f; if (acc & 16) tmp |= 128; if (acc & 32) tmp |= 64; if (acc & 64) tmp |= 32; if (acc & 128) tmp |= 16; acc = tmp; } break; } case 59: { int n; n = bitsset[(size_t) acc] % 8; while(n--) RIGHT45(dir); break; } case 61: { cell *tmps; int tmp; tmps = stack1; stack1 = stack2; stack2 = tmps; tmp = stack1size; stack1size = stack2size; stack2size = tmp; tmp = stack1pos; stack1pos = stack2pos; stack2pos = tmp; break; } case 67: goto quit; default: acc = gpf[(size_t) c]; } movefwd(&codex, &codey, dir, 1); checkmove(codex, codey, maxline, lines); } quit: free(lengths); free(stack1); free(stack2); } cell *read_arbitrary_length_string(FILE *fp) { cell *p = NULL, *q; int size = 50; if ((p = malloc(size)) == NULL) return NULL; if (fgets(p, size, fp) == NULL) return NULL; while ((q = strchr(p, '\n')) == NULL) { size *= 2; if ((p = realloc(p, size)) == NULL) return NULL; if (fgets(&p[size/2-1], size/2+1, fp) == NULL) return NULL; /* invalid; file must end with newline */ } *q = '\0'; return p; }