scripting challenge, easy mode |
scripting challenge, easy mode |
![]()
Post
#1
|
|
![]() /人◕‿‿◕人\ ![]() ![]() ![]() ![]() ![]() ![]() ![]() Group: Official Member Posts: 8,283 Joined: Dec 2007 Member No: 602,927 ![]() |
1. think up your own esoteric language.
2. write a hello world script with it. 3. explain the code. 4. show the output. 5. ??? 6. profit! Mine: a brainfuck-esque language that uses four commands and seven characters. Useful for learning binary in an extreme way. CODE .[->+>+>->+>->->->->+>+>->->+>->+>->+>+>->+>+>->->->+>+>->+>+>->->->+>+>->+>+>+>+>->->+>->->->->->->+>+>+>->+>+>->+>+>->+>+>+>+>->+>+>+>->->+>->->+>+>->+>+>->->->+>+>->->+>->->->->+>->->->->+]~[->+>+>+>+>+>+>->->->+>->+>+>+>+>->+>+>->+>->->->->+>+>->->+>->+>->+>+>->+>+>->->->+>+>->+>+>->->->+>+>->+>+>+>+>->+>+>+>->+>+>+>->+>+>->+>+>+>+>->+>+>+>->->+>->->+>+>->+>+>->->->+>+>->->+>->->->->+>->+>+>+>->->+>+>+>->+>->->->+>+>+>+>->->->->+>+>+>->+>->-] This code creates "~/helloworld.txt" and writes "hello world!" to it. .[(string)]~[(location)] = write (string) to (location) - = turn bit off + = turn bit on > = next bit You can make a compiler if you really want to. |
|
|
![]() |
![]()
Post
#2
|
|
![]() Senior Member ![]() ![]() ![]() ![]() ![]() ![]() Group: Administrator Posts: 2,648 Joined: Apr 2008 Member No: 639,265 ![]() |
I wrote an interpreter in C for this language. I've named the interpreter "buttf*ck" since this is a f*cked-up version of brainf*ck. The interpreter is pretty minimal. I made no attempt to write "good" code, I used unsafe C functions like strcpy(), and I made no attempt to free memory (but it gets freed after the program exits anyway). The parser also doesn't really report errors correctly, unless you compile a debug version. Oh, and in some cases it'll break on really large programs/strings. But here it is anyway, all 413 lines of sexy interpreter code:
CODE /* * buttf*ck.c - Interpreter for the Buttf*ck programming language. * <http://www.createblog.com/forums/index.php?showtopic=240400> * Compile: * $ gcc -o buttf*ck buttf*ck.c */ #include <ctype.h> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define TKN_BUF_SIZE 256 #define MAX_PATH 256 #define FIRST_LINE 1 #define FIRST_COL 1 typedef enum {ERR_BAD_ARGS = 1, ERR_OUT_OF_MEMORY, ERR_BAD_FILE} bf_memory_error; typedef enum {TKN_STRING = 0, TKN_LOCATION, TKN_EOF, TKN_ERROR} bf_token_type; typedef enum { S_START, S_DONE, S_EOF, S_STRING, S_LOCATION, S_TILDE, S_DATA, S_ERROR } bf_token_state; const char *TOKEN_NAMES[] = {"STRING", "LOCATION", "EOF", "ERROR"}; #define PLUS_MASK 0xffffffff #define MINUS_MASK 0x0 typedef struct { bf_token_type type; unsigned int line; unsigned int col; char *val; } bf_token; typedef struct { const char *path; FILE *stream; unsigned int line; unsigned int col; } bf_tokenizer; typedef struct { bf_tokenizer *stream; char *path; char *str; } bf_parser; static char *expand_tildes(char *origpath, char *newpath) { char *home = NULL; char *xpath = NULL; home = getenv("HOME"); xpath = strchr(origpath, '~'); xpath++; sprintf(newpath, "%s%s", home, xpath); return newpath; } static bf_token *bf_create_token(bf_token_type type, unsigned int line, unsigned int col) { bf_token *tkn = NULL; tkn = (bf_token *) malloc(sizeof(bf_token)); if (!tkn) { perror("bf_create_token"); exit(ERR_OUT_OF_MEMORY); } tkn->type = type; tkn->line = FIRST_LINE; tkn->col = FIRST_COL; tkn->val = NULL; return tkn; } static void bf_free_token(bf_token *t) { free(t->val); free(t); } static char *bf_token_format(bf_token *t) { char *s; s = (char *) malloc(64); if (!s) { perror("bf_token_format"); exit(ERR_OUT_OF_MEMORY); } s = strcpy(s, TOKEN_NAMES[t->type]); if (t->val) { sprintf(s, "%s(%s)", s, t->val); } sprintf(s, "%s [%u]", s, t->line); return s; } static bf_tokenizer *bf_create_tokenizer(const char *path) { bf_tokenizer *t = NULL; FILE *fh = NULL; t = (bf_tokenizer *) malloc(sizeof(bf_tokenizer)); if (!t) { perror("bf_create_tokenizer"); exit(ERR_OUT_OF_MEMORY); } t->path = path; fh = fopen(path, "r"); if (!fh) { perror("bf_create_tokenizer"); exit(ERR_BAD_FILE); } t->stream = fh; t->line = 0; t->col = 0; return t; } static void bf_free_tokenizer(bf_tokenizer *t) { fclose(t->stream); t->stream = NULL; free(t); } static unsigned char bf_getc(bf_tokenizer *t) { int c; c = getc(t->stream); t->col++; switch (c) { case '\t': c = ' '; t->col += 7; break; case '\n': c = ' '; t->line++; break; case EOF: c = '\'; break; } return (unsigned char) c; } static unsigned char bf_ungetc(bf_tokenizer *t, unsigned char ch) { int c; c = ungetc(ch, t->stream); return c != EOF ? (unsigned char) c : '\'; } static bf_token *bf_next_token(bf_tokenizer *t) { bf_token_type type; bf_token *tkn = NULL; bf_token_state state = S_START; char *buf = NULL; unsigned int bufpos = 0; unsigned int bitpos = 0; unsigned int masked = 0; unsigned int bitmask = 0; buf = (char *) malloc(TKN_BUF_SIZE); if (!buf) { perror("bf_next_token"); exit(ERR_OUT_OF_MEMORY); } while (state != S_DONE) { unsigned char ch = bf_getc(t); switch (state) { case S_START: switch (ch) { case '\': state = S_DONE; tkn = bf_create_token(TKN_EOF, t->line, t->col); break; case '.': state = S_START; break; case '[': state = S_STRING; break; case '~': state = S_TILDE; break; default: #ifdef DEBUG fprintf(stderr, "Error (START), expected EOF, '.', '[', or '~', got %c\n", ch); #endif state = S_ERROR; buf[bufpos++] = ch; break; } break; case S_DATA: switch (ch) { case '[': state = S_DATA; break; case '>': bitpos++; if (bitpos > 7) { unsigned char bc = (unsigned char) masked; if (!isprint(bc)) { fprintf(stderr, "Warning: non-printable character %#x, " "line %u, col %u\n", bc, t->line, t->col); } buf[bufpos++] = bc; bitpos = 0; masked = 0; } bitmask = (unsigned int) pow(2, (7 - bitpos)); break; case '+': state = S_DATA; masked |= (PLUS_MASK & bitmask); break; case '-': state = S_DATA; masked |= (MINUS_MASK & bitmask); break; case ']': state = S_DONE; buf[bufpos++] = (unsigned char) masked; tkn = bf_create_token(type, t->line, t->col); break; default: #ifdef DEBUG fprintf(stderr, "Error (%s), expected '[', '>', '+', '-', ']', got %c\n", (type == TKN_STRING ? "STRING" : "LOCATION"), ch); #endif state = S_ERROR; buf[bufpos++] = ch; break; } break; case S_TILDE: switch (ch) { case '[': state = S_LOCATION; break; default: #ifdef DEBUG fprintf(stderr, "Error, expected '~', got %c\n", ch); #endif state = S_ERROR; buf[bufpos++] = ch; break; } break; case S_STRING: state = S_DATA; type = TKN_STRING; break; case S_LOCATION: state = S_DATA; type = TKN_LOCATION; break; case S_ERROR: if (ch == '\') { state = S_DONE; tkn = bf_create_token(TKN_ERROR, t->line, t->col); } else { buf[bufpos++] = ch; } break; } } buf[bufpos] = '\'; /* Terminate that string, son! */ tkn->val = buf; return tkn; } static bf_parser *bf_create_parser(bf_tokenizer *t) { bf_parser *p = NULL; p = (bf_parser *) malloc(sizeof(bf_parser)); if (!p) { perror("bf_create_parser"); exit(ERR_OUT_OF_MEMORY); } p->stream = t; p->path = NULL; p->str = NULL; return p; } static void bf_free_parser(bf_parser *p) { bf_free_tokenizer(p->stream); free(p->path); free(p->str); free(p); } static void bf_parse_string(bf_parser *p) { bf_token *t = NULL; t = bf_next_token(p->stream); switch (t->type) { case TKN_STRING: p->str = t->val; break; default: fprintf(stderr, "Error: Line %u, Col %u\n", t->line, t->col); break; } } static void bf_parse_location(bf_parser *p) { bf_token *t = NULL; t = bf_next_token(p->stream); switch (t->type) { case TKN_LOCATION: p->path = t->val; break; case TKN_EOF: break; default: fprintf(stderr, "Error: Line %u, Col %u\n", t->line, t->col); break; } } static int bf_parser_run(bf_parser *p) { FILE *fh = NULL; char path[MAX_PATH]; size_t len = 0; bf_parse_string(p); bf_parse_location(p); fprintf(stderr, "Path: %s\n", p->path); fprintf(stderr, "String: %s\n", p->str); expand_tildes(p->path, path); fh = fopen(path, "w"); if (!fh) { perror("bf_parser_run"); exit(ERR_BAD_FILE); } len = strlen(p->str); if (fwrite(p->str, len, 1, fh) < 1) { perror("bf_parser_run"); exit(ERR_BAD_FILE); } fclose(fh); return 0; } int main(int argc, char **argv) { bf_tokenizer *tokenizer = NULL; bf_parser *parser = NULL; if (argc < 2) { fprintf(stderr, "Usage: buttf*ck source.bf\n"); exit(ERR_BAD_ARGS); } tokenizer = bf_create_tokenizer(argv[1]); parser = bf_create_parser(tokenizer); return bf_parser_run(parser); } Source file: buttf*ck.c (because CB's code box messes up the format a bit) (That URL doesn't really have a '*' in it; I assume you know how to change it.) P.S. Your code is a bit off in some places -- "hello, world!" isn't printed. "hello, v????B" is printed instead, where '?' are unprintable characters. I think the problem starts with the 'v' -- looks like you may have skipped a bit. This post has been edited by mipadi: Oct 29 2009, 11:28 PM
Reason for edit: use bit.ly for urls
|
|
|
![]() ![]() |