177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* #!/usr/local/bin/otcc */ 277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* 377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * Sample OTCC C example. You can uncomment the first line and install 477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * otcc in /usr/local/bin to make otcc scripts ! 577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao */ 677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* Any preprocessor directive except #define are ignored. We put this 877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao include so that a standard C compiler can compile this code too. */ 977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#include <stdio.h> 1077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 1177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* defines are handled, but macro arguments cannot be given. No 1277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao recursive defines are tolerated */ 1377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DEFAULT_BASE 10 1477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 1577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* 1677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * Only old style K&R prototypes are parsed. Only int arguments are 1777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * allowed (implicit types). 1877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * 1977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * By benchmarking the execution time of this function (for example 2077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * for fib(35)), you'll notice that OTCC is quite fast because it 2177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * generates native i386 machine code. 2277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao */ 2377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaofib(n) 2477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao{ 2577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao if (n <= 2) 2677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao return 1; 2777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao else 2877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao return fib(n-1) + fib(n-2); 2977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao} 3077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 3177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* Identifiers are parsed the same way as C: begins with letter or 3277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao '_', and then letters, '_' or digits */ 3377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaofact(n) 3477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao{ 3577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* local variables can be declared. Only 'int' type is supported */ 3677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao int i, r; 3777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao r = 1; 3877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* 'while' and 'for' loops are supported */ 3977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao for(i=2;i<=n;i++) 4077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao r = r * i; 4177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao return r; 4277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao} 4377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 4477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* Well, we could use printf, but it would be too easy */ 4577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaoprint_num(n, b) 4677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao{ 4777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao int tab, p, c; 4877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* Numbers can be entered in decimal, hexadecimal ('0x' prefix) and 4977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao octal ('0' prefix) */ 5077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* more complex programs use malloc */ 5177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao tab = malloc(0x100); 5277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao p = tab; 5377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao while (1) { 5477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao c = n % b; 5577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* Character constants can be used */ 5677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao if (c >= 10) 5777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao c = c + 'a' - 10; 5877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao else 5977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao c = c + '0'; 6077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao *(char *)p = c; 6177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao p++; 6277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao n = n / b; 6377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* 'break' is supported */ 6477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao if (n == 0) 6577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao break; 6677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao } 6777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao while (p != tab) { 6877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao p--; 6977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao printf("%c", *(char *)p); 7077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao } 7177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao free(tab); 7277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao} 7377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 7477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* 'main' takes standard 'argc' and 'argv' parameters */ 7577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaomain(argc, argv) 7677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao{ 7777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* no local name space is supported, but local variables ARE 7877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao supported. As long as you do not use a globally defined 7977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao variable name as local variable (which is a bad habbit), you 8077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao won't have any problem */ 8177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao int s, n, f, base; 8277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 8377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* && and || operator have the same semantics as C (left to right 8477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao evaluation and early exit) */ 8577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao if (argc != 2 && argc != 3) { 8677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* '*' operator is supported with explicit casting to 'int *', 8777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 'char *' or 'int (*)()' (function pointer). Of course, 'int' 8877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao are supposed to be used as pointers too. */ 8977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao s = *(int *)argv; 9077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao help(s); 9177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao return 1; 9277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao } 9377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* Any libc function can be used because OTCC uses dynamic linking */ 9477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao n = atoi(*(int *)(argv + 4)); 9577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao base = DEFAULT_BASE; 9677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao if (argc >= 3) { 9777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao base = atoi(*(int *)(argv + 8)); 9877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao if (base < 2 || base > 36) { 9977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* external variables can be used too (here: 'stderr') */ 10077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao fprintf(stderr, "Invalid base\n"); 10177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao return 1; 10277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao } 10377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao } 10477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao printf("fib(%d) = ", n); 10577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao print_num(fib(n), base); 10677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao printf("\n"); 10777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 10877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao printf("fact(%d) = ", n); 10977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao if (n > 12) { 11077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao printf("Overflow"); 11177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao } else { 11277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* why not using a function pointer ? */ 11377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao f = &fact; 11477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao print_num((*(int (*)())f)(n), base); 11577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao } 11677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao printf("\n"); 11777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao return 0; 11877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao} 11977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 12077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* functions can be used before being defined */ 12177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaohelp(name) 12277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao{ 12377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao printf("usage: %s n [base]\n", name); 12477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao printf("Compute fib(n) and fact(n) and output the result in base 'base'\n"); 12577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao} 12677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 127