]> git.sur5r.net Git - cc65/blob - test/ref/otccex.c
atari5200: fix COLOR defines' names
[cc65] / test / ref / otccex.c
1 /*
2   !!DESCRIPTION!! OTCC Example (simple K&R Style)
3   !!ORIGIN!!      OTCC
4   !!LICENCE!!     GPL (?), read COPYING.GPL
5 */
6
7 #include "common.h"
8
9 /*
10  * Sample OTCC C example. You can uncomment the first line and install
11  * otcc in /usr/local/bin to make otcc scripts !  
12  */
13
14 /* Any preprocessor directive except #define are ignored. We put this
15    include so that a standard C compiler can compile this code too. */
16 #include <stdio.h>
17 #include <limits.h>
18
19 /* defines are handled, but macro arguments cannot be given. No
20    recursive defines are tolerated */
21 #define DEFAULT_BASE 10
22
23 #ifdef NO_IMPLICIT_FUNC_PROTOTYPES
24 help(char *name);
25 #endif
26
27 /*
28  * Only old style K&R prototypes are parsed. Only int arguments are
29  * allowed (implicit types).
30  * 
31  * By benchmarking the execution time of this function (for example
32  * for fib(35)), you'll notice that OTCC is quite fast because it
33  * generates native i386 machine code.  
34  */
35 fib(n)
36 {
37     printf("[fib(%d)]", n);
38     if (n <= 2)
39         return 1;
40     else
41         return fib(n-1) + fib(n-2);
42 }
43
44 /* Identifiers are parsed the same way as C: begins with letter or
45    '_', and then letters, '_' or digits */
46 long fact(n)
47 {
48     /* local variables can be declared. Only 'int' type is supported */
49     int i;
50     long r;
51     r = 1;
52     /* 'while' and 'for' loops are supported */
53     for(i=2;i<=n;i++)
54         r = r * i;
55     return r;
56 }
57
58 /* Well, we could use printf, but it would be too easy */
59 print_num(long n,int b)
60 {
61     int tab, p, c;
62     /* Numbers can be entered in decimal, hexadecimal ('0x' prefix) and
63        octal ('0' prefix) */
64     /* more complex programs use malloc */
65     tab = malloc(0x100); 
66     p = tab;
67     while (1) {
68         c = n % b;
69         /* Character constants can be used */
70         if (c >= 10)
71             c = c + 'a' - 10;
72         else
73             c = c + '0';
74         *(char *)p = c;
75         p++;
76         n = n / b;
77         /* 'break' is supported */
78         if (n == 0)
79             break;
80     }
81     while (p != tab) {
82         p--;
83         printf("%c", *(char *)p);
84     }
85     free(tab);
86 }
87
88 /* 'main' takes standard 'argc' and 'argv' parameters */
89 mymain(int argc,char **argv)
90 {
91     /* no local name space is supported, but local variables ARE
92        supported. As long as you do not use a globally defined
93        variable name as local variable (which is a bad habbit), you
94        won't have any problem */
95     int s, n, f, base;
96     
97     
98     /* && and || operator have the same semantics as C (left to right
99        evaluation and early exit) */
100     if (argc != 2 && argc != 3) {
101         /* '*' operator is supported with explicit casting to 'int *',
102            'char *' or 'int (*)()' (function pointer). Of course, 'int'
103            are supposed to be used as pointers too. */
104         s = *(int *)argv;
105         help(s);
106         return 1;
107     }
108     /* Any libc function can be used because OTCC uses dynamic linking */
109     n = atoi(argv[1]);
110     base = DEFAULT_BASE;
111     if (argc >= 3) {
112         base = atoi(argv[2]);
113         if (base < 2 || base > 36) {
114             /* external variables can be used too (here: 'stderr') */
115             fprintf(stdout, "Invalid base\n");
116             return 1;
117         }
118     }
119     printf("fib(%d) =\n", n);
120     print_num(fib(n), base);
121     printf("\n");
122
123     printf("fact(%d) = ", n);
124     if (n > 12) {
125         printf("Overflow");
126     } else {
127         /* why not using a function pointer ? */
128         f = &fact;
129         print_num((*(long (*)(int))f)(n), base);
130     }
131     printf("\n");
132     return 0;
133 }
134
135 /* functions can be used before being defined */
136 help(char *name)
137 {
138     printf("usage: %s n [base]\n", name);
139     printf("Compute fib(n) and fact(n) and output the result in base 'base'\n");
140 }
141
142 int main(void)
143 {
144     char *argv[3];
145     argv[0]="";
146     argv[1]="10"; /* n */
147     argv[2]="8"; /* base */
148     mymain(3, argv);
149     return 0;
150 }