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