]> git.sur5r.net Git - cc65/blob - test/val/cq4.c
All regression-tests subdirectories are cleaned before the first test starts, so...
[cc65] / test / val / cq4.c
1 /*
2   !!DESCRIPTION!! C-Manual Chapter 4: what's in a name?
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 int extvar;
166
167 #ifdef NO_IMPLICIT_FUNC_PROTOTYPES
168 int s4(struct defs *pd0);
169 int svtest(int n);
170 zero();
171 testev();
172 setev();
173 #endif
174
175 #ifndef NO_OLD_FUNC_DECL
176 s4(pd0)                    /* 4. What's in a name?             */
177 struct defs *pd0;
178 {
179 #else
180 int s4(struct defs *pd0) {
181 #endif
182    static char s4er[] = "s4,er%d\n";
183    static char qs4[8] = "s4     ";
184    char *ps, *pt;
185    int j, rc;
186
187    short sint;             /* short integer, for size test      */
188    int pint;               /* plain                             */
189    long lint;              /* long                              */
190    unsigned target;
191    unsigned int mask;
192
193    rc = 0;
194    ps = qs4;
195    pt = pd0->rfs;
196
197    while(*pt++ = *ps++);
198
199 /*   There are four declarable storage classes: automatic,
200 static, external, and register. Automatic variables have
201 been dealt with extensively thus far, and will not be specif-
202 ically treated in this section. Register variables are treated
203 in section s81.
204
205      Static variables are local to a block, but retain their
206 values upon reentry to a block, even after control has left
207 the block.                                                     */
208
209    for (j=0; j<3; j++)
210      if(svtest(j) != zero()){
211        rc = 1;
212        if(pd0->flgd != 0) printf(s4er,1);
213      }
214    ;
215
216 /*   External variables exist and retain their values throughout
217 the execution of the entire program, and may be used for comm-
218 unication between functions, even separately compiled functions.
219                                                                 */
220
221    setev();
222    if(testev() != 0){
223      rc=rc+2;
224      if(pd0->flgd != 0) printf(s4er,2);
225    }
226 /*
227      Characters have been tested elsewhere (in s243).
228
229      Up to three sizes of integer, declared short int, int, and
230 long int, are available. Longer integers provide no less storage
231 than shorter ones, but implementation may make either short
232 integers, or long integers, or both, equivalent to plain
233 integers.
234                                                                 */
235
236    if(sizeof lint < sizeof pint || sizeof pint < sizeof sint){
237      rc = rc+4;
238      if(pd0->flgd != 0) printf(s4er,4);
239    }
240
241 /*   Unsigned integers, declared unsigned, obey the laws of
242 arithmetic modulo 2**n, where n is the number of bits in the
243 implementation                                                  */
244
245    target = ~0U;
246    mask = 1;
247    printf("sizeof target: %08x pd0->cbits: %08x\n", sizeof target, pd0->cbits);
248    printf("mask: %08x target: %08x\n", mask, target);
249
250    for(j=0; j<(sizeof target)*pd0->cbits; j++){
251      mask = mask&target;
252      target = target>>1;
253      printf("mask: %08x target: %08x\n", mask, target);
254    }
255
256    if(mask != 1 || target != 0){
257      rc = rc+8;
258      if(pd0->flgd != 0) printf(s4er,8);
259    }
260
261    return rc;
262 }
263
264 #ifndef NO_OLD_FUNC_DECL
265 svtest(n)
266 int n;
267 {
268 #else
269 int svtest(int n) {
270 #endif
271
272    static k;
273    int rc;
274    switch (n) {
275      case 0: k = 1978;
276              rc = 0;
277              break;
278
279      case 1: if(k != 1978) rc = 1;
280              else{
281               k = 1929;
282               rc = 0;
283              }
284              break;
285
286      case 2: if(k != 1929) rc = 1;
287              else rc = 0;
288              break;
289    }
290    return rc;
291 }
292 zero(){                 /* Returns a value of zero, possibly */
293    static k;            /* with side effects, as it's called */
294    int rc;              /* alternately with svtest, above,   */
295    k = 2;               /* and has the same internal storage */
296    rc = 0;              /* requirements.                     */
297    return rc;
298 }
299 testev(){
300    if(extvar != 1066) return 1;
301    else return 0;
302 }
303
304 /* Sets an external variable. Used  */
305 /* by s4, and should be compiled    */
306 /* separately from s4.              */
307
308 setev(){
309 #ifndef NO_SLOPPY_EXTERN
310    extern int extvar;
311 #endif
312    extvar = 1066;
313 }
314
315 /*********************************************************************************************
316  the main loop that launches the sections
317 *********************************************************************************************/
318
319 #ifndef NO_TYPELESS_STRUCT_PTR
320         int section(int j,struct* pd0){
321 #else
322         int section(int j,void* pd0){
323 #endif
324         switch(j){
325                 case 0: return s26(pd0);
326                 case 1: return s4(pd0);
327         }
328 }
329
330 #define cq_sections 2
331
332 /*
333         C REFERENCE MANUAL (main)
334 */
335
336 #ifndef NO_OLD_FUNC_DECL
337 main(n,args)
338 int n;
339 char **args;
340 {
341 #else
342 int main(int n,char **args) {
343 #endif
344
345 int j;
346 static struct defs d0, *pd0;
347         
348    d0.flgs = 1;          /* These flags dictate            */
349    d0.flgm = 1;          /*     the verbosity of           */
350    d0.flgd = 1;          /*         the program.           */
351    d0.flgl = 1;
352
353    pd0 = &d0;
354
355    for (j=0; j<cq_sections; j++) {
356      d0.rrc=section(j,pd0);
357      d0.crc=d0.crc+d0.rrc;
358      if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc);
359    }
360
361    if(d0.crc == 0) printf("\nNo errors detected.\n");
362    else printf("\nFailed.\n");
363
364    return d0.crc;
365 }