Log In · Register

 
 
Reply to this topicStart new topic
scripting challenge, easy mode
heyo-captain-jac...
post Aug 22 2009, 04:59 PM
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.
 
mipadi
post Aug 24 2009, 01:05 PM
Post #2


Senior Member
******

Group: Administrator
Posts: 2,648
Joined: Apr 2008
Member No: 639,265



So how does it work? At first I assumed that the bit-flipping operations turned single bits in a byte on/off, and that the strings were encoded using ASCII, but that doesn't seem to be the case.
 
heyo-captain-jac...
post Aug 24 2009, 04:31 PM
Post #3


/人◕‿‿◕人\
*******

Group: Official Member
Posts: 8,283
Joined: Dec 2007
Member No: 602,927



The bit-flipping operations turn single bits on and off.

+ = 1 and - = 0, and the strings translate directly from binary to ascii.
 
mipadi
post Aug 24 2009, 07:08 PM
Post #4


Senior Member
******

Group: Administrator
Posts: 2,648
Joined: Apr 2008
Member No: 639,265



Oh, I see. I was looking for an encoded "~", but there isn't one (I guess that's just assumed).
 
Maccabee
post Aug 24 2009, 07:28 PM
Post #5


Senior Member
*******

Group: Official Designer
Posts: 5,880
Joined: Nov 2007
Member No: 593,382



How do you run it? And where is the file created?
 
heyo-captain-jac...
post Aug 24 2009, 07:29 PM
Post #6


/人◕‿‿◕人\
*******

Group: Official Member
Posts: 8,283
Joined: Dec 2007
Member No: 602,927



QUOTE
.[->+>+>->+>->->->->+>+>->->+>->+>->+>+>->+>+>->->->+>+>->+>+>->->->+>+>->+>+>+>+>->->+>->->->->->->+>+>+>->+>+>->+>+>->+>+>+>+>->+>+>+>->->+>->->+>+>->+>+>->->->+>+>->->+>->->->->+>->->->->+]~[->+>+>+>+>+>+>->->->+>->+>+>+>+>->+>+>->+>->->->->+>+>->->+>->+>->+>+>->+>+>->->->+>+>->+>+>->->->+>+>->+>+>+>+>->+>+>+>->+>+>+>->+>+>->+>+>+>+>->+>+>+>->->+>->->+>+>->+>+>->->->+>+>->->+>->->->->+>->+>+>+>->->+>+>+>->+>->->->+>+>+>+>->->->->+>+>+>->+>->-]



fyi




also joseph, you need to write a compiler or an instruction set for a virtual machine.
 
mipadi
post Aug 24 2009, 07:33 PM
Post #7


Senior Member
******

Group: Administrator
Posts: 2,648
Joined: Apr 2008
Member No: 639,265



QUOTE(Buttsex @ Aug 24 2009, 08:29 PM) *
fyi


No, I misread the post and thought the location of the file came first, not the other way around.
 
heyo-captain-jac...
post Aug 24 2009, 07:39 PM
Post #8


/人◕‿‿◕人\
*******

Group: Official Member
Posts: 8,283
Joined: Dec 2007
Member No: 602,927



Oh, alright. Makes sense.
 
mipadi
post Aug 24 2009, 10:31 PM
Post #9


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
 
Maccabee
post Aug 24 2009, 10:56 PM
Post #10


Senior Member
*******

Group: Official Designer
Posts: 5,880
Joined: Nov 2007
Member No: 593,382



PHP:

CODE
<?php
Print "Hello, World!";
?>


HTML:

CODE
<html><head><title></title></head><body>Hello, World!</body></html>


java script:

CODE
<script type="text/javascript">
document.write('<b>Hello World</b>');
</script>


Text format:

Hello, World!

mellow.gif


biggrin.gif



Im hardcore. Win?
 
heyo-captain-jac...
post Aug 25 2009, 04:10 PM
Post #11


/人◕‿‿◕人\
*******

Group: Official Member
Posts: 8,283
Joined: Dec 2007
Member No: 602,927



You're softcore, lose.
 
mipadi
post Oct 29 2009, 02:18 PM
Post #12


Senior Member
******

Group: Administrator
Posts: 2,648
Joined: Apr 2008
Member No: 639,265



Boring day at work, wrote a Python version of the Buttfuck VM:

CODE
#!/usr/bin/env python

import os
import sys


class Buttf*ckToken(object):
    TYPES = ("STRING", "LOCATION", "EOF", "ERROR")
    
    def __init__(self, type, line, col, val=None):
        if type not in Buttf*ckToken.TYPES:
            raise ValueError("type must be one of %s" %
                             ", ".join(Buttf*ckToken.TYPES))
        self.type = type
        self.line = line
        self.col = col
        self.val = val
    
    def __str__(self):
        if self.val:
            return "%s(%s)" % (self.type, self.val)
        else:
            return "%s [%d]" % (self.type, self.line)


class Buttf*ckTokenizer(object):
    
    def __init__(self, stream):
        self.stream = stream
        self.line = 0
        self.col = 0
        self.buffer = []
    
    def getc(self):
        if self.buffer:
            ch = self.buffer[0]
            self.buffer = self.buffer[1:]
        else:
            ch = self.stream.read(1)
            self.col += 1
            if not ch:
                ch = '\'
            elif ch == '\t':
                ch = ' '
                self.col += 7
            elif ch == '\n':
                ch = ' '
                self.line += 1
        return ch
    
    def ungetc(self, ch):
        self.buffer.append(ch)
    
    def next(self):
        state = "START"
        buf = ""
        bitpos = 0
        masked = 0
        tkntype = None
        while state != "DONE":
            ch = self.getc()
            if state == "START":
                if ch == '\':
                    state = "DONE"
                    tkn = Buttf*ckToken("EOF", self.line, self.col)
                elif ch == '.':
                    state = "START"
                elif ch == '[':
                    state = "STRING"
                elif ch == '~':
                    state = "TILDE"
                else:
                    state = "ERROR"
                    buf += ch
            elif state == "DATA":
                if ch == '[':
                    state = "DATA"
                elif ch == '>':
                    bitpos += 1
                    if bitpos > 7:
                        buf += chr(masked)
                        bitpos = 0
                        masked = 0
                    bitmask = 2 ** (7 - bitpos)
                elif ch == '+':
                    state = "DATA"
                    masked |= (0xffffffff & bitmask)
                elif ch == '-':
                    state = "DATA"
                    masked |= (0x0 & bitmask)
                elif ch == ']':
                    state = "DONE"
                    buf += chr(masked)
                    tkn = Buttf*ckToken(tkntype, self.line, self.col)
                else:
                    state = "ERROR"
                    buf += ch
            elif state == "TILDE":
                if ch == '[':
                    state = "LOCATION"
                else:
                    state = "ERROR"
                    buf += ch
            elif state == "STRING":
                state = "DATA"
                tkntype = "STRING"
            elif state == "LOCATION":
                state = "DATA"
                tkntype = "LOCATION"
            elif state == "ERROR":
                if ch == '\':
                    state = "DONE"
                    tkn = Buttf*ckToken("ERROR", self.line, self.col)
                else:
                    buf += ch
            else:
                assert False, "Invalid state: " + state
        tkn.val = buf
        return tkn


class Buttf*ckParser(object):
    
    def __init__(self, tokenizer):
        self.tokenizer = tokenizer
        self.path = None
        self.str = None
    
    def parse(self):
        self._parse_string()
        self._parse_location()
        
        perror("Path:   " + self.path)
        perror("String: " + self.str)
        
        self.path = os.path.expanduser(self.path)
        self.path = os.path.realpath(self.path)
        with open(self.path, "w") as fh:
            fh.write(self.str)
        return True
    
    def _parse_string(self):
        tkn = self.tokenizer.next()
        if tkn.type == "STRING":
            self.str = tkn.val
        else:
            perror("Error: Line %d, Col %d" % (tkn.line, tkn.col))
    
    def _parse_location(self):
        tkn = self.tokenizer.next()
        if tkn.type == "LOCATION":
            self.path = tkn.val
        elif tkn.type == "EOF":
            pass
        else:
            perror("Error: Line %d, Col %d" % (tkn.line, tkn.col))


def perror(msg):
    print >>sys.stderr, "buttf*ck: " + msg


def main(argv):
    if len(argv) > 0:
        try:
            stream = open(argv[0])
        except IOError as e:
            perror(str(e))
            return 1
    else:
        stream = sys.stdin
    parser = Buttf*ckParser(Buttf*ckTokenizer(stream))
    if parser.parse():
        stream.close()
        return 0
    else:
        stream.close()
        return 2


if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))


Source: buttuck.py (usual problem with the URL applies)

This post has been edited by mipadi: Oct 29 2009, 11:29 PM
Reason for edit: use bit.ly for the urls
 
tokyo-rose
post Oct 29 2009, 08:24 PM
Post #13


♡♡♡♡♡
********

Group: Head Staff
Posts: 18,173
Joined: Mar 2005
Member No: 108,478



QUOTE(mipadi @ Oct 29 2009, 03:18 PM) *
Source: buttuck.py (usual problem with the URL applies)

Use a URL shortener, like bit.ly?
 
mipadi
post Oct 29 2009, 10:36 PM
Post #14


Senior Member
******

Group: Administrator
Posts: 2,648
Joined: Apr 2008
Member No: 639,265



QUOTE(Cristy @ Oct 29 2009, 09:24 PM) *
Use a URL shortener, like bit.ly?

I thought those were only used to disguise really nasty porn links.
 
Maccabee
post Oct 29 2009, 10:39 PM
Post #15


Senior Member
*******

Group: Official Designer
Posts: 5,880
Joined: Nov 2007
Member No: 593,382



QUOTE(mipadi @ Oct 29 2009, 10:36 PM) *
I thought those were only used to disguise really nasty porn links.

not only that. maybe you should get
https://addons.mozilla.org/en-US/firefox/addon/2207
whats so wrong tinyurl?
 
mipadi
post Oct 29 2009, 11:29 PM
Post #16


Senior Member
******

Group: Administrator
Posts: 2,648
Joined: Apr 2008
Member No: 639,265



Ha!

Well, I used bit.ly to generate better URLs.
 
mipadi
post Nov 8 2009, 01:50 AM
Post #17


Senior Member
******

Group: Administrator
Posts: 2,648
Joined: Apr 2008
Member No: 639,265



Wrote one for Ruby. Thought I'd have more fun with the Ruby version, so I used Treetop to generate a grammar.

Here's the grammar (buttf*ck.tt):

CODE
grammar Buttf*ck
  rule program
    '.[' string ']~[' location ']'
  end
  
  rule string
    bit+
  end
  
  rule location
    bit+
  end
  
  rule bit
    [+-] '>'?
  end
end


And here's the program that uses that grammar to parse a file (bf.rb):

CODE
#!/usr/bin/env ruby

require 'rubygems'
require 'treetop'
require 'buttf*ck'


class String
  def from_buttf*ck
    data = {:bitpos => 0, :masked => 0, :bitmask => 0}
    buf = ''
    each_char do |ch|
      case ch
      when '>'
        data[:bitpos] += 1
        if data[:bitpos] > 7
          buf << data[:masked]
          data[:bitpos] = 0
          data[:masked] = 0
        end
        data[:bitmask] = 2 ** (7 - data[:bitpos])
      when '+'
        data[:masked] |= (0xffffffff & data[:bitmask])
      when '-'
        data[:masked] |= (0x0 & data[:bitmask])
      end
    end
    buf
  end
  
  def to_path
    File.expand_path self
  end
end


if $0 == __FILE__
  if $*.length < 1
    $stderr.puts 'Usage: ruby bf.rb file.bf'
    exit 1
  end
  
  string = nil
  location = nil
  open($*[0], 'r') do |fh|
    nodes = Buttf*ckParser.new.parse fh.read.strip
    string = nodes.string.text_value.from_buttf*ck
    location = nodes.location.text_value.from_buttf*ck
  end
  open(location.to_path, 'w') { |fh| fh.print string }
end


Grammar: buttf*ck.tt
Source: bf.rb
 
superstitious
post Nov 8 2009, 02:38 PM
Post #18


Tick tock, Bill
*******

Group: Administrator
Posts: 8,764
Joined: Dec 2005
Member No: 333,948



I honestly don't know what any of this means, but it sure is funny reading all this code with "buttf*ck" being used throughout. hahaha
 

Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members: