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