]> git.sur5r.net Git - cc65/blob - test/val/cq72.c
Merge branch 'master' into kbrepeat
[cc65] / test / val / cq72.c
1 /*
2   !!DESCRIPTION!! C-Manual Chapter 7.2: Unary Operators
3   !!ORIGIN!!      LCC 4.1 Testsuite
4   !!LICENCE!!     own, freely distributeable for non-profit. read CPYRIGHT.LCC
5 */
6
7 #include "common.h"
8
9 struct defs {
10      int cbits;          /* No. of bits per char           */
11      int ibits;          /*                 int            */
12      int sbits;          /*                 short          */
13      int lbits;          /*                 long           */
14      int ubits;          /*                 unsigned       */
15      int fbits;          /*                 float          */
16      int dbits;          /*                 double         */
17      #ifndef NO_FLOATS
18         float fprec;        /* Smallest number that can be    */
19         float dprec;        /* significantly added to 1.      */
20      #endif
21      int flgs;           /* Print return codes, by section */
22      int flgm;           /* Announce machine dependencies  */
23      int flgd;           /* give explicit diagnostics      */
24      int flgl;           /* Report local return codes.     */
25      int rrc;            /* recent return code             */
26      int crc;            /* Cumulative return code         */
27      char rfs[8];        /* Return from section            */
28 };
29
30      int lbits;          /*                 long           */
31      int ubits;          /*                 unsigned       */
32      int fbits;          /*                 float          */
33      int dbits;          /*                 double         */
34      #ifndef NO_FLOATS
35         float fprec;        /* Smallest number that can be    */
36         float dprec;        /* significantly added to 1.      */
37      #endif
38      int flgs;           /* Print return codes, by section */
39      int flgm;           /* Announce machine dependencies  */
40      int flgd;           /* give explicit diagnostics      */
41      int flgl;           /* Report local return codes.     */
42      int rrc;            /* recent return code             */
43      int crc;            /* Cumulative return code         */
44      char rfs[8];        /* Return from section            */
45
46 #define CQ26_INCLUDED
47 /*
48   section s26, which pokes around at the hardware
49   trying to figure out the characteristics of the machine that
50   it is running on, saves information that is subsequently
51   used by sections s626, s72, and s757. If this program is
52   to be broken up into smallish pieces, say for running on
53   a microcomputer, take care to see that s26 is called before
54   calling any of the latter three sections.
55 */
56
57 /*
58         2.6  Hardware Characteristics
59 */
60
61 #ifndef NO_OLD_FUNC_DECL
62 s26(pd0)
63 struct defs *pd0;
64 {
65 #else
66 s26(struct defs *pd0) {
67 #endif
68    static char qs26[8] = "s26    ";
69    char *ps, *pt;
70    char c0, c1;
71    #ifndef NO_FLOATS
72         float temp, one, delta;
73         double tempd, oned;
74    #endif
75    static char s[] = "%3d bits in %ss.\n";
76    static char s2[] = "%e is the least number that can be added to 1. (%s).\n";
77
78    ps = qs26;
79    pt = pd0->rfs;
80
81    while(*pt++ = *ps++);
82
83           /* Here, we shake the machinery a little to see what falls
84              out.  First, we find out how many bits are in a char.  */
85
86    pd0->cbits = 0;
87    c0 = 0;
88    c1 = 1;
89
90    while(c0 != c1) {
91      c1 = c1<<1;
92      pd0->cbits = pd0->cbits+1;
93    }
94           /* That information lets us determine the size of everything else. */
95
96    pd0->ibits = pd0->cbits * sizeof(int);
97    pd0->sbits = pd0->cbits * sizeof(short);
98    pd0->lbits = pd0->cbits * sizeof(long);
99    pd0->ubits = pd0->cbits * sizeof(unsigned);
100    #ifndef NO_FLOATS
101         pd0->fbits = pd0->cbits * sizeof(float);
102         pd0->dbits = pd0->cbits * sizeof(double);
103    #endif
104
105           /* We have now almost reconstructed the table in section 2.6, the
106              exception being the range of the floating point hardware.
107              Now there are just so many ways to conjure up a floating point
108              representation system that it's damned near impossible to guess
109              what's going on by writing a program to interpret bit patterns.
110              Further, the information isn't all that useful, if we consider
111              the fact that machines that won't handle numbers between 10**30
112              and 10**-30 are very hard to find, and that people playing with
113              numbers outside that range have a lot more to worry about than
114              just the capacity of the characteristic.
115
116              A much more useful measure is the precision, which can be ex-
117              pressed in terms of the smallest number that can be added to
118              1. without loss of significance. We calculate that here, for
119              float and double.                       */
120
121 #ifndef NO_FLOATS
122    one = 1.;
123    delta = 1.;
124    temp = 0.;
125    while(temp != one) {
126      temp = one+delta;
127      delta = delta/2.;
128    }
129    pd0->fprec = delta * 4.;
130    oned = 1.;
131    delta = 1.;
132    tempd = 0.;
133    while(tempd != oned) {
134      tempd = oned+delta;
135      delta = delta/2.;
136    }
137    pd0->dprec = delta * 4.;
138 #endif
139
140           /* Now, if anyone's interested, we publish the results.       */
141
142 #ifndef CQ26_INCLUDED
143    if(pd0->flgm != 0) {
144      printf(s,pd0->cbits,"char");
145      printf(s,pd0->ibits,"int");
146      printf(s,pd0->sbits,"short");
147      printf(s,pd0->lbits,"long");
148      printf(s,pd0->ubits,"unsigned");
149      printf(s,pd0->fbits,"float");
150      printf(s,pd0->dbits,"double");
151      #ifndef NO_FLOATS
152         printf(s2,pd0->fprec,"float");
153         printf(s2,pd0->dprec,"double");
154      #else
155         printf("NO_FLOATS\n");
156      #endif
157    }
158 #endif
159           /* Since we are only exploring and perhaps reporting, but not
160              testing any features, we cannot return an error code.  */
161
162    return 0;
163 }
164
165 #ifndef NO_OLD_FUNC_DECL
166 s72(pd0)          /*  7.2  Unary operators  */
167 struct defs *pd0;
168 {
169 #else
170 int s72(struct defs *pd0){
171 #endif
172    static char s72er[] = "s72,er%d\n";
173    static char qs72[8] = "s72    ";
174    int rc;
175    char *ps, *pt;
176    int k, j, i, lrc;
177    char c;
178    short s;
179    long l;
180    unsigned u;
181
182    #ifndef NO_FLOATS
183         double d;
184         float f;
185    #else
186         signed d;
187         signed f;
188    #endif
189
190    ps = qs72;
191    pt = pd0->rfs;
192    rc = 0;
193    while (*pt++ = *ps++);
194
195         /* The *, denoting indirection, and the &, denoting a
196         pointer, are duals of each other, and ought to behave as
197         such...                                                 */
198
199    k = 2;
200    if(*&*&k != 2){
201      rc = rc+1;
202      printf(s72er,1);
203    }
204
205         /* The unary minus has the conventional meaning.        */
206
207    if(k+(-k) != 0){
208      rc = rc+2;
209      printf(s72er,2);
210    }
211
212         /*  The negation operator (!) has been thoroughly checked out,
213         perhaps more thoroughly than any of the others. The ~ oper-
214         ator gets us a ones complement.                         */
215
216    k = 0;
217    for(j=0;j<pd0->ibits;j++) k = (k<<1)|1;
218    if(~k != 0){
219      rc = rc+4;
220      printf(s72er,4);
221    }
222
223         /*  Now we look at the ++ and -- operators, which can be
224         used in either prefix or suffix form. With side
225         effects they're loaded.                                 */
226
227    k = 5;
228
229    if( ++k != 6 || --k != 5
230     || k++ != 5 || k-- != 6
231     ||   k != 5 ){
232      rc = rc+8;
233      printf(s72er,8);
234    }
235
236         /*  An expression preceded by the parenthesised name of a
237         data type causes conversion of the value of the expression
238         to the named type. This construction is called a cast.
239         Here, we check to see that all of the possible casts and
240         their simple combinations are accepted by the compiler,
241         and that they all produce a correct result for this sample
242         of size one.                                            */
243
244    c = 26;  l = 26;
245    s = 26;  u = 26;
246    i = 26;
247    #ifndef NO_FLOATS
248    f = 26.;
249    d = 26.;
250    #else
251    f = 26;
252    d = 26;
253    #endif
254
255    lrc = 0;
256
257    if( (char)s != 26 || (char)i != 26
258     || (char)l != 26 || (char)u != 26
259     || (char)f != 26 || (char)d != 26 ) lrc = lrc+1;
260
261    if( (short)c != 26 || (short)i != 26
262     || (short)l != 26 || (short)u != 26
263     || (short)f != 26 || (short)d != 26) lrc = lrc+2;
264
265    if( (int)c != 26 || (int)s != 26
266     || (int)l != 26 || (int)u != 26
267     || (int)f != 26 || (int)d != 26 ) lrc = lrc+4;
268
269    if( (long)c != 26 || (long)s != 26
270     || (long)i != 26 || (long)u != 26
271     || (long)f != 26 || (long)d != 26 ) lrc = lrc+8;
272
273    if( (unsigned)c != 26 || (unsigned)s != 26
274     || (unsigned)i != 26 || (unsigned)l != 26
275     || (unsigned)f != 26 || (unsigned)d != 26 ) lrc = lrc+16;
276
277    #ifndef NO_FLOATS
278    if( (float)c != 26. || (float)s != 26.
279     || (float)i != 26. || (float)l != 26.
280     || (float)u != 26. || (float)d != 26. ) lrc = lrc+32;
281
282    if( (double)c != 26. || (double)s != 26.
283     || (double)i != 26. || (double)l != 26.
284     || (double)u != 26. || (double)f != 26. ) lrc = lrc+64;
285    #endif
286
287    if(lrc != 0){
288      rc = rc+16;
289      printf(s72er,16);
290    }
291
292         /*  The sizeof operator has been tested previously.     */
293
294    return rc;
295 }
296
297 /*********************************************************************************************
298  the main loop that launches the sections
299 *********************************************************************************************/
300
301 #ifndef NO_TYPELESS_STRUCT_PTR
302         int section(int j,struct* pd0){
303 #else
304         int section(int j,void* pd0){
305 #endif
306         switch(j){
307                 case 0: return s26(pd0);
308                 case 1: return s72(pd0);
309         }
310 }
311
312 #define cq_sections 2
313
314 /*
315         C REFERENCE MANUAL (main)
316 */
317
318 #ifndef NO_OLD_FUNC_DECL
319 main(n,args)
320 int n;
321 char **args;
322 {
323 #else
324 int main(int n,char **args) {
325 #endif
326
327 int j;
328 static struct defs d0, *pd0;
329         
330    d0.flgs = 1;          /* These flags dictate            */
331    d0.flgm = 1;          /*     the verbosity of           */
332    d0.flgd = 1;          /*         the program.           */
333    d0.flgl = 1;
334
335    pd0 = &d0;
336
337    for (j=0; j<cq_sections; j++) {
338      d0.rrc=section(j,pd0);
339      d0.crc=d0.crc+d0.rrc;
340      if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc);
341    }
342
343    if(d0.crc == 0) printf("\nNo errors detected.\n");
344    else printf("\nFailed.\n");
345
346    return d0.crc;
347 }