121a15a2416b4b138bf509186106525944e78ad08Jack Palevich/* #!/usr/local/bin/otcc */
221a15a2416b4b138bf509186106525944e78ad08Jack Palevich/*
321a15a2416b4b138bf509186106525944e78ad08Jack Palevich * Sample OTCC C example. You can uncomment the first line and install
421a15a2416b4b138bf509186106525944e78ad08Jack Palevich * otcc in /usr/local/bin to make otcc scripts !
521a15a2416b4b138bf509186106525944e78ad08Jack Palevich */
621a15a2416b4b138bf509186106525944e78ad08Jack Palevich
721a15a2416b4b138bf509186106525944e78ad08Jack Palevich/* Any preprocessor directive except #define are ignored. We put this
821a15a2416b4b138bf509186106525944e78ad08Jack Palevich   include so that a standard C compiler can compile this code too. */
921a15a2416b4b138bf509186106525944e78ad08Jack Palevich#include <stdio.h>
1021a15a2416b4b138bf509186106525944e78ad08Jack Palevich
1121a15a2416b4b138bf509186106525944e78ad08Jack Palevich/* defines are handled, but macro arguments cannot be given. No
1221a15a2416b4b138bf509186106525944e78ad08Jack Palevich   recursive defines are tolerated */
1321a15a2416b4b138bf509186106525944e78ad08Jack Palevich#define DEFAULT_BASE 10
1421a15a2416b4b138bf509186106525944e78ad08Jack Palevich
1521a15a2416b4b138bf509186106525944e78ad08Jack Palevich/*
1621a15a2416b4b138bf509186106525944e78ad08Jack Palevich * Only old style K&R prototypes are parsed. Only int arguments are
1721a15a2416b4b138bf509186106525944e78ad08Jack Palevich * allowed (implicit types).
1821a15a2416b4b138bf509186106525944e78ad08Jack Palevich *
1921a15a2416b4b138bf509186106525944e78ad08Jack Palevich * By benchmarking the execution time of this function (for example
2021a15a2416b4b138bf509186106525944e78ad08Jack Palevich * for fib(35)), you'll notice that OTCC is quite fast because it
2121a15a2416b4b138bf509186106525944e78ad08Jack Palevich * generates native i386 machine code.
2221a15a2416b4b138bf509186106525944e78ad08Jack Palevich */
2321a15a2416b4b138bf509186106525944e78ad08Jack Palevichfib(n)
2421a15a2416b4b138bf509186106525944e78ad08Jack Palevich{
2521a15a2416b4b138bf509186106525944e78ad08Jack Palevich    if (n <= 2)
2621a15a2416b4b138bf509186106525944e78ad08Jack Palevich        return 1;
2721a15a2416b4b138bf509186106525944e78ad08Jack Palevich    else
2821a15a2416b4b138bf509186106525944e78ad08Jack Palevich        return fib(n-1) + fib(n-2);
2921a15a2416b4b138bf509186106525944e78ad08Jack Palevich}
3021a15a2416b4b138bf509186106525944e78ad08Jack Palevich
3121a15a2416b4b138bf509186106525944e78ad08Jack Palevich/* Identifiers are parsed the same way as C: begins with letter or
3221a15a2416b4b138bf509186106525944e78ad08Jack Palevich   '_', and then letters, '_' or digits */
3321a15a2416b4b138bf509186106525944e78ad08Jack Palevichfact(n)
3421a15a2416b4b138bf509186106525944e78ad08Jack Palevich{
3521a15a2416b4b138bf509186106525944e78ad08Jack Palevich    /* local variables can be declared. Only 'int' type is supported */
3621a15a2416b4b138bf509186106525944e78ad08Jack Palevich    int i, r;
3721a15a2416b4b138bf509186106525944e78ad08Jack Palevich    r = 1;
3821a15a2416b4b138bf509186106525944e78ad08Jack Palevich    /* 'while' and 'for' loops are supported */
3921a15a2416b4b138bf509186106525944e78ad08Jack Palevich    for(i=2;i<=n;i++)
4021a15a2416b4b138bf509186106525944e78ad08Jack Palevich        r = r * i;
4121a15a2416b4b138bf509186106525944e78ad08Jack Palevich    return r;
4221a15a2416b4b138bf509186106525944e78ad08Jack Palevich}
4321a15a2416b4b138bf509186106525944e78ad08Jack Palevich
4421a15a2416b4b138bf509186106525944e78ad08Jack Palevich/* Well, we could use printf, but it would be too easy */
4521a15a2416b4b138bf509186106525944e78ad08Jack Palevichprint_num(n, b)
4621a15a2416b4b138bf509186106525944e78ad08Jack Palevich{
4721a15a2416b4b138bf509186106525944e78ad08Jack Palevich    int tab, p, c;
4821a15a2416b4b138bf509186106525944e78ad08Jack Palevich    /* Numbers can be entered in decimal, hexadecimal ('0x' prefix) and
4921a15a2416b4b138bf509186106525944e78ad08Jack Palevich       octal ('0' prefix) */
5021a15a2416b4b138bf509186106525944e78ad08Jack Palevich    /* more complex programs use malloc */
5121a15a2416b4b138bf509186106525944e78ad08Jack Palevich    tab = malloc(0x100);
5221a15a2416b4b138bf509186106525944e78ad08Jack Palevich    p = tab;
5321a15a2416b4b138bf509186106525944e78ad08Jack Palevich    while (1) {
5421a15a2416b4b138bf509186106525944e78ad08Jack Palevich        c = n % b;
5521a15a2416b4b138bf509186106525944e78ad08Jack Palevich        /* Character constants can be used */
5621a15a2416b4b138bf509186106525944e78ad08Jack Palevich        if (c >= 10)
5721a15a2416b4b138bf509186106525944e78ad08Jack Palevich            c = c + 'a' - 10;
5821a15a2416b4b138bf509186106525944e78ad08Jack Palevich        else
5921a15a2416b4b138bf509186106525944e78ad08Jack Palevich            c = c + '0';
6021a15a2416b4b138bf509186106525944e78ad08Jack Palevich        *(char *)p = c;
6121a15a2416b4b138bf509186106525944e78ad08Jack Palevich        p++;
6221a15a2416b4b138bf509186106525944e78ad08Jack Palevich        n = n / b;
6321a15a2416b4b138bf509186106525944e78ad08Jack Palevich        /* 'break' is supported */
6421a15a2416b4b138bf509186106525944e78ad08Jack Palevich        if (n == 0)
6521a15a2416b4b138bf509186106525944e78ad08Jack Palevich            break;
6621a15a2416b4b138bf509186106525944e78ad08Jack Palevich    }
6721a15a2416b4b138bf509186106525944e78ad08Jack Palevich    while (p != tab) {
6821a15a2416b4b138bf509186106525944e78ad08Jack Palevich        p--;
6921a15a2416b4b138bf509186106525944e78ad08Jack Palevich        printf("%c", *(char *)p);
7021a15a2416b4b138bf509186106525944e78ad08Jack Palevich    }
7121a15a2416b4b138bf509186106525944e78ad08Jack Palevich    free(tab);
7221a15a2416b4b138bf509186106525944e78ad08Jack Palevich}
7321a15a2416b4b138bf509186106525944e78ad08Jack Palevich
7421a15a2416b4b138bf509186106525944e78ad08Jack Palevich/* 'main' takes standard 'argc' and 'argv' parameters */
7521a15a2416b4b138bf509186106525944e78ad08Jack Palevichmain(argc, argv)
7621a15a2416b4b138bf509186106525944e78ad08Jack Palevich{
7721a15a2416b4b138bf509186106525944e78ad08Jack Palevich    /* no local name space is supported, but local variables ARE
7821a15a2416b4b138bf509186106525944e78ad08Jack Palevich       supported. As long as you do not use a globally defined
7921a15a2416b4b138bf509186106525944e78ad08Jack Palevich       variable name as local variable (which is a bad habbit), you
8021a15a2416b4b138bf509186106525944e78ad08Jack Palevich       won't have any problem */
8121a15a2416b4b138bf509186106525944e78ad08Jack Palevich    int s, n, f, base;
8221a15a2416b4b138bf509186106525944e78ad08Jack Palevich
8321a15a2416b4b138bf509186106525944e78ad08Jack Palevich    /* && and || operator have the same semantics as C (left to right
8421a15a2416b4b138bf509186106525944e78ad08Jack Palevich       evaluation and early exit) */
8521a15a2416b4b138bf509186106525944e78ad08Jack Palevich    if (argc != 2 && argc != 3) {
8621a15a2416b4b138bf509186106525944e78ad08Jack Palevich        /* '*' operator is supported with explicit casting to 'int *',
8721a15a2416b4b138bf509186106525944e78ad08Jack Palevich           'char *' or 'int (*)()' (function pointer). Of course, 'int'
8821a15a2416b4b138bf509186106525944e78ad08Jack Palevich           are supposed to be used as pointers too. */
8921a15a2416b4b138bf509186106525944e78ad08Jack Palevich        s = *(int *)argv;
9021a15a2416b4b138bf509186106525944e78ad08Jack Palevich        help(s);
9121a15a2416b4b138bf509186106525944e78ad08Jack Palevich        return 1;
9221a15a2416b4b138bf509186106525944e78ad08Jack Palevich    }
9321a15a2416b4b138bf509186106525944e78ad08Jack Palevich    /* Any libc function can be used because OTCC uses dynamic linking */
9421a15a2416b4b138bf509186106525944e78ad08Jack Palevich    n = atoi(*(int *)(argv + 4));
9521a15a2416b4b138bf509186106525944e78ad08Jack Palevich    base = DEFAULT_BASE;
9621a15a2416b4b138bf509186106525944e78ad08Jack Palevich    if (argc >= 3) {
9721a15a2416b4b138bf509186106525944e78ad08Jack Palevich        base = atoi(*(int *)(argv + 8));
9821a15a2416b4b138bf509186106525944e78ad08Jack Palevich        if (base < 2 || base > 36) {
9921a15a2416b4b138bf509186106525944e78ad08Jack Palevich            /* external variables can be used too (here: 'stderr') */
10021a15a2416b4b138bf509186106525944e78ad08Jack Palevich            fprintf(stderr, "Invalid base\n");
10121a15a2416b4b138bf509186106525944e78ad08Jack Palevich            return 1;
10221a15a2416b4b138bf509186106525944e78ad08Jack Palevich        }
10321a15a2416b4b138bf509186106525944e78ad08Jack Palevich    }
10421a15a2416b4b138bf509186106525944e78ad08Jack Palevich    printf("fib(%d) = ", n);
10521a15a2416b4b138bf509186106525944e78ad08Jack Palevich    print_num(fib(n), base);
10621a15a2416b4b138bf509186106525944e78ad08Jack Palevich    printf("\n");
10721a15a2416b4b138bf509186106525944e78ad08Jack Palevich
10821a15a2416b4b138bf509186106525944e78ad08Jack Palevich    printf("fact(%d) = ", n);
10921a15a2416b4b138bf509186106525944e78ad08Jack Palevich    if (n > 12) {
11021a15a2416b4b138bf509186106525944e78ad08Jack Palevich        printf("Overflow");
11121a15a2416b4b138bf509186106525944e78ad08Jack Palevich    } else {
11221a15a2416b4b138bf509186106525944e78ad08Jack Palevich        /* why not using a function pointer ? */
11321a15a2416b4b138bf509186106525944e78ad08Jack Palevich        f = &fact;
11421a15a2416b4b138bf509186106525944e78ad08Jack Palevich        print_num((*(int (*)())f)(n), base);
11521a15a2416b4b138bf509186106525944e78ad08Jack Palevich    }
11621a15a2416b4b138bf509186106525944e78ad08Jack Palevich    printf("\n");
11721a15a2416b4b138bf509186106525944e78ad08Jack Palevich    return 0;
11821a15a2416b4b138bf509186106525944e78ad08Jack Palevich}
11921a15a2416b4b138bf509186106525944e78ad08Jack Palevich
12021a15a2416b4b138bf509186106525944e78ad08Jack Palevich/* functions can be used before being defined */
12121a15a2416b4b138bf509186106525944e78ad08Jack Palevichhelp(name)
12221a15a2416b4b138bf509186106525944e78ad08Jack Palevich{
12321a15a2416b4b138bf509186106525944e78ad08Jack Palevich    printf("usage: %s n [base]\n", name);
12421a15a2416b4b138bf509186106525944e78ad08Jack Palevich    printf("Compute fib(n) and fact(n) and output the result in base 'base'\n");
12521a15a2416b4b138bf509186106525944e78ad08Jack Palevich}
12621a15a2416b4b138bf509186106525944e78ad08Jack Palevich
127