⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cq.c

📁 3D 游戏界的大牛人 John Carmack 终于放出了 Q3 的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
   struct defs {
     int cbits;          /* No. of bits per char           */
     int ibits;          /*                 int            */
     int sbits;          /*                 short          */
     int lbits;          /*                 long           */
     int ubits;          /*                 unsigned       */
     int fbits;          /*                 float          */
     int dbits;          /*                 double         */
     float fprec;        /* Smallest number that can be    */
     float dprec;        /* significantly added to 1.      */
     int flgs;           /* Print return codes, by section */
     int flgm;           /* Announce machine dependencies  */
     int flgd;           /* give explicit diagnostics      */
     int flgl;           /* Report local return codes.     */
     int rrc;            /* recent return code             */
     int crc;            /* Cumulative return code         */
     char rfs[8];        /* Return from section            */
   };
main(n,args)               /* C REFERENCE MANUAL         */
int n;
char **args;
{

/*   This program performs a series of tests on a C compiler,
based on information in the

             C REFERENCE MANUAL

which appears as Appendix A to the book "The C Programming
Language" by Brian W. Kernighan and Dennis M. Ritchie
(Prentice-Hall, 1978, $10.95). This Appendix is hereafter
referred to as "the Manual".

     The rules followed in writing this program are:

     1. The entire program is written in legal C, according
     to the Manual. It should compile with no error messages,
     although some warning messages may be produced by some
     compilers. Failure to compile should be interpreted as
     a compiler error.

     2. The program is clean, in that it does not make use
     of any features of the operating system on which it runs,
     with the sole exceptions of the printf() function, and an
     internal "options" routine, which is easily excised.

     3. No global variables are used, except for the spec-
     ific purpose of testing the global variable facility.

     The program is divided into modules having names of the
form snnn... These modules correspond to those sections of the
Manual, as identified by boldface type headings, in which
there is something to test. For example, s241() corresponds
to section 2.4.1 of the Manual (Integer constants) and tests
the facilities described therein. The module numbering
scheme is ambiguous, especially when it names modules
referring to more than one section; module s7813, for ex-
ample, deals with sections 7.8 through 7.13. Nonetheless,
it is surprisingly easy to find a section in the Manual
corresponding to a section of code, and vice versa.

     Note also that there seem to be "holes" in the program,
at least from the point of view that there exist sections in the
Manual for which there is no corresponding code. Such holes
arise from three causes: (a) there is nothing in that partic-
ular section to test, (b) everything in that section is tested
elsewhere, and (c) it was deemed advisable not to check cer-
tain features like preprocessor or listing control features.

     Modules are called by a main program main(). The mod-
ules that are called, and the sequence in which they are 
called, are determined by two lists in main(), in which the
module names appear. The first list (an extern statement)
declares the module names to be external. The second (a stat-
ic int statement) names the modules and defines the sequence
in which they are called. There is no need for these lists
to be in the same order, but it is probably a good idea to keep
them that way in the interest of clarity. Since there are no
cross-linkages between modules, new modules may be added,
or old ones deleted, simply by editing the lists, with one
exception: section s26, which pokes around at the hardware
trying to figure out the characteristics of the machine that
it is running on, saves information that is subsequently
used by sections s626, s72, and s757. If this program is
to be broken up into smallish pieces, say for running on
a microcomputer, take care to see that s26 is called before
calling any of the latter three sections.  The size
of the lists, i.e., the number of modules to be called, is
not explicitly specified as a program parameter, but is
determined dynamically using the sizeof operator.

     Communication between the main program and the modules
takes place in two ways. In all cases, a pointer to a structure
is passed to the called module. The structure contains flags
that will determine the type of information to be published
by the module, and fields that may be written in by the
module. The former include "flgm" and "flgd", which, if set
to a nonzero value, specify that machine dependencies are to
be announced or that error messages are to be printed, re-
spectively. The called module's name, and the hardware char-
acteristics probed in s26() comprise the latter.


     Also, in all cases, a return code is returned by the called
module. A return code of zero indicates that all has gone well;
nonzero indicates otherwise. Since more than one type of error
may be detected by a module, the return code is a composite
of error indicators, which, individually, are given as numbers
that are powers of two. Thus, a return code of 10 indicates
that two specific errors, 8 and 2, were detected. Whether or
not the codes returned by the modules are printed by the main
program is determined by setting "flgs" to 1 (resp. 0).

     The entire logic of the main program is contained in the
half-dozen or so lines at the end. The somewhat cryptic 
statement:

           d0.rrc = (*sec[j])(pd0);

in the for loop calls the modules. The rest of the code is
reasonably straightforward.

     Finally, in each of the modules, there is the following
prologue:

           snnn(pd0)
           struct defs *pd0;
           {
              static char snnner[] = "snnn,er%d\n";
              static char qsnnn[8] = "snnn   ";
              char *ps, *pt;
              int rc;

              rc = 0;
              ps = qsnnn;
              pt = pd0->rfs;
              while(*pt++ = *ps++);

used for housekeeping, handshaking and module initialization.

                                                           */
   extern
     s22(),
     s241(),
     s243(),
     s244(),
     s25(),
     s26(),
     s4(),
     s61(),
     s626(),
     s71(),
     s72(),
     s757(),
     s7813(),
     s714(),
     s715(),
     s81(),
     s84(),
     s85(),
     s86(),
     s88(),
     s9()
   ;

   int j;
   static int (*sec[])() = {
     s22,
     s241,
     s243,
     s244,
     s25,
     s26,
     s4,
     s61,
     s626,
     s71,
     s72,
     s757,
     s7813,
     s714,
     s715,
     s81,
     s84,
     s85,
     s86,
     s88,
     s9
   };

   static struct defs d0, *pd0;
    
     d0.flgs = 1;          /* These flags dictate            */
     d0.flgm = 1;          /*     the verbosity of           */
     d0.flgd = 1;          /*         the program.           */
     d0.flgl = 1;

   pd0 = &d0;

   for (j=0; j<sizeof(sec) / sizeof(sec[0]); j++) {
     d0.rrc = (*sec[j])(pd0);
     d0.crc = d0.crc+d0.rrc;
     if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc);
   }
  
   if(d0.crc == 0) printf("\nNo errors detected.\n");
   else printf("\nFailed.\n");
   return 0;
}
s22(pd0)                 /* 2.2 Identifiers (Names)      */
struct defs *pd0;
{
   int a234, a;
   int _, _234, A, rc;

   static char s22er[] = "s22,er%d\n";
   static char qs22[8] = "s22    ";

   char *ps, *pt;
                         /* Initialize                      */

   rc = 0;
   ps = qs22;
   pt = pd0 -> rfs;
   while (*pt++ = *ps++);

     /* An identifier is a sequence of letters and digits;
        the first character must be a letter. The under-
        score _ counts as a letter.                        */

   a=1;
   _=2;
   _234=3;
   a234=4;
   if(a+_+_234+a234 != 10) {
     rc = rc+1;
     if(pd0->flgd != 0) printf(s22er,1);
   }

   /* Upper and lower case letters are different.     */

   A = 2;
   if (A == a) {
     rc = rc+4;
     if (pd0->flgd != 0) printf(s22er,4);
   }

   return(rc);
}
s241(pd0)                   /* 2.4.1 Integer constants
                               2.4.2 Explicit long constants  */
struct defs *pd0;
{
   long pow2();
   static char s241er[] = "s241,er%d\n";
   static char qs241[8] = "s241   ";
   char *ps, *pt;
   int rc, j, lrc;
   static long g[39] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                        0,6,0,8,0,12,0,16,0,18,0,20,0,24,
                        0,28,0,30,0,32,0,36};
   long d[39], o[39], x[39];

   rc = 0;
   lrc = 0;
   ps = qs241;
   pt = pd0 -> rfs;
   while (*pt++ = *ps++);

     /* An integer constant consisting of a sequence of digits is
        taken to be octal if it begins with 0 (digit zero), decimal
        otherwise.                                            */

   if (   8 !=  010
     ||  16 !=  020
     ||  24 !=  030
     ||  32 !=  040
     ||  40 !=  050
     ||  48 !=  060
     ||  56 !=  070
     ||  64 != 0100
     ||  72 != 0110
     ||  80 != 0120
     ||   9 != 0011
     ||  17 != 0021
     ||  25 != 0031
     ||  33 != 0041
     ||  41 != 0051
     ||  49 != 0061
     ||  57 != 0071
     ||  65 != 0101
     ||  73 != 0111
     ||  81 != 0121 ){

     rc = rc+1;
     if( pd0->flgd != 0 ) printf(s241er,1);
   }

     /* A sequence of digits preceded by 0x or 0X (digit zero)
        is taken to be a hexadecimal integer. The hexadecimal
        digits include a or A through f or F with values 10
        through 15.     */

   if ( 0x00abcdef != 0xabcdef
     || 0xabcdef != 0Xabcdef || 0Xabcdef != 0XAbcdef
     || 0XAbcdef != 0XABcdef || 0XABcdef != 0XABCdef
     || 0XABCdef != 0XABCDef || 0XABCDef != 0XABCDEf
     || 0XABCDEf != 0XABCDEF || 0xABCDEF != 11259375 ){

     rc = rc+2;
     if( pd0->flgd != 0 ) printf(s241er,2);
   }

     /* A decimal constant whose value exceeds the largest signed
        machine integer is taken to be long; an octal or hex con-
        stant which exceeds the largest unsigned machine integer
        is likewise taken to be long.     */

   if ( sizeof 010000000000 != sizeof(long)      /* 2**30 */
     || sizeof 1073741824   != sizeof(long)      /* ditto */
     || sizeof 0x40000000   != sizeof(long) ){   /*   "   */

     rc = rc+4;
     if( pd0->flgd != 0 ) printf(s241er,4);
   }

     /* A decimal, octal, or hexadecimal constant immediately followed
        by l (letter ell) or L is a long constant.    */

   if ( sizeof   67l != sizeof(long)
     || sizeof   67L != sizeof(long)
     || sizeof  067l != sizeof(long)
     || sizeof  067L != sizeof(long)
     || sizeof 0X67l != sizeof(long)
     || sizeof 0x67L != sizeof(long) ){

     rc = rc+8;
     if( pd0 -> flgd != 0 ) printf(s241er,8);
   }

     /* Finally, we test to see that decimal (d), octal (o),
        and hexadecimal (x) constants representing the same values
        agree among themselves, and with computed values, at spec-
        ified points over an appropriate range. The points select-
        ed here are those with the greatest potential for caus-
        ing trouble, i.e., zero, 1-16, and values of 2**n and
        2**n - 1 where n is some multiple of 4 or 6. Unfortunately,
        just what happens when a value is too big to fit in a
        long is undefined; however, it would be nice if what
        happened were at least consistent...      */

   for ( j=0; j<17; j++ ) g[j] = j;
   for ( j=18; j<39; ) {
     g[j] = pow2(g[j]);
     g[j-1] = g[j] - 1;
     j = j+2;
   }

   d[0] = 0;                o[0] = 00;               x[0] = 0x0;
   d[1] = 1;                o[1] = 01;               x[1] = 0x1;
   d[2] = 2;                o[2] = 02;               x[2] = 0x2;
   d[3] = 3;                o[3] = 03;               x[3] = 0x3;
   d[4] = 4;                o[4] = 04;               x[4] = 0x4;
   d[5] = 5;                o[5] = 05;               x[5] = 0x5;
   d[6] = 6;                o[6] = 06;               x[6] = 0x6;
   d[7] = 7;                o[7] = 07;               x[7] = 0x7;
   d[8] = 8;                o[8] = 010;              x[8] = 0x8;
   d[9] = 9;                o[9] = 011;              x[9] = 0x9;
   d[10] = 10;              o[10] = 012;             x[10] = 0xa;
   d[11] = 11;              o[11] = 013;             x[11] = 0xb;
   d[12] = 12;              o[12] = 014;             x[12] = 0xc;
   d[13] = 13;              o[13] = 015;             x[13] = 0xd;
   d[14] = 14;              o[14] = 016;             x[14] = 0xe;
   d[15] = 15;              o[15] = 017;             x[15] = 0xf;
   d[16] = 16;              o[16] = 020;             x[16] = 0x10;
   d[17] = 63;              o[17] = 077;             x[17] = 0x3f;
   d[18] = 64;              o[18] = 0100;            x[18] = 0x40;
   d[19] = 255;             o[19] = 0377;            x[19] = 0xff;
   d[20] = 256;             o[20] = 0400;            x[20] = 0x100;
   d[21] = 4095;            o[21] = 07777;           x[21] = 0xfff;
   d[22] = 4096;            o[22] = 010000;          x[22] = 0x1000;
   d[23] = 65535;           o[23] = 0177777;         x[23] = 0xffff;
   d[24] = 65536;           o[24] = 0200000;         x[24] = 0x10000;
   d[25] = 262143;          o[25] = 0777777;         x[25] = 0x3ffff;
   d[26] = 262144;          o[26] = 01000000;        x[26] = 0x40000;
   d[27] = 1048575;         o[27] = 03777777;        x[27] = 0xfffff;
   d[28] = 1048576;         o[28] = 04000000;        x[28] = 0x100000;
   d[29] = 16777215;        o[29] = 077777777;       x[29] = 0xffffff;
   d[30] = 16777216;        o[30] = 0100000000;      x[30] = 0x1000000;
   d[31] = 268435455;       o[31] = 01777777777;     x[31] = 0xfffffff;
   d[32] = 268435456;       o[32] = 02000000000;     x[32] = 0x10000000;
   d[33] = 1073741823;      o[33] = 07777777777;     x[33] = 0x3fffffff;
   d[34] = 1073741824;      o[34] = 010000000000;    x[34] = 0x40000000;
   d[35] = 4294967295;      o[35] = 037777777777;    x[35] = 0xffffffff;
   d[36] = 4294967296;      o[36] = 040000000000;    x[36] = 0x100000000;
   d[37] = 68719476735;     o[37] = 0777777777777;   x[37] = 0xfffffffff;
   d[38] = 68719476736;     o[38] = 01000000000000;  x[38] = 0x1000000000;

   /* WHEW! */

   for (j=0; j<39; j++){
     if ( g[j] != d[j]
       || d[j] != o[j]
       || o[j] != x[j]) {

       if( pd0 -> flgm != 0 ) {
/*       printf(s241er,16);          save in case opinions change...     */
         printf("Decimal and octal/hex constants sometimes give\n");
         printf("   different results when assigned to longs.\n");
       }
/*     lrc = 1;   save...   */
     }
   }

   if (lrc != 0) rc =16;

   return rc;
}

long pow2(n)        /* Calculate 2**n by multiplying, not shifting  */
long n;
{
   long s;
   s = 1;
   while(n--) s = s*2;
   return s;
}
s243(pd0)                   /*  2.4.3 Character constants  */
struct defs *pd0;
{
   static char s243er[] = "s243,er%d\n";
   static char qs243[8] = "s243   ";
   char *ps, *pt;
   int rc;
   char chars[256];

   rc = 0;
   ps = qs243;
   pt = pd0->rfs;
   while(*pt++ = *ps++);

     /* One of the problems that arises when testing character constants
        is that of definition: What, exactly, is the character set?
        In order to guarantee a certain amount of machine independence,
        the character set we will use here is the set of characters writ-
        able as escape sequences in C, plus those characters used in writ-
        ing C programs, i.e.,

        letters:
                   ABCDEFGHIJKLMNOPQRSTUVWXYZ      26
                   abcdefghijklmnopqrstuvwxyz      26
        numbers:
                   0123456789                      10
        special characters:
                   ~!"#%&()_=-^|{}[]+;*:<>,.?/     27
        extra special characters:
                   newline           \n       
                   horizontal tab    \t
                   backspace         \b
                   carriage return   \r
                   form feed         \f
                   backslash         \\
                   single quote      \'             7
        blank & NUL                                 2
                                                  ---
                                                   98

        Any specific implementation of C may of course support additional
        characters.                                       */

        /* Since the value of a character constant is the numerical value
           of the character in the machine's character set, there should
           be a one-to-one correspondence between characters and values. */

   zerofill(chars);

   chars['a'] = 1;   chars['A'] = 1;   chars['~'] = 1;   chars['0'] = 1;
   chars['b'] = 1;   chars['B'] = 1;   chars['!'] = 1;   chars['1'] = 1;
   chars['c'] = 1;   chars['C'] = 1;   chars['"'] = 1;   chars['2'] = 1;
   chars['d'] = 1;   chars['D'] = 1;   chars['#'] = 1;   chars['3'] = 1;
   chars['e'] = 1;   chars['E'] = 1;   chars['%'] = 1;   chars['4'] = 1;
   chars['f'] = 1;   chars['F'] = 1;   chars['&'] = 1;   chars['5'] = 1;
   chars['g'] = 1;   chars['G'] = 1;   chars['('] = 1;   chars['6'] = 1;
   chars['h'] = 1;   chars['H'] = 1;   chars[')'] = 1;   chars['7'] = 1;
   chars['i'] = 1;   chars['I'] = 1;   chars['_'] = 1;   chars['8'] = 1;
   chars['j'] = 1;   chars['J'] = 1;   chars['='] = 1;   chars['9'] = 1;
   chars['k'] = 1;   chars['K'] = 1;   chars['-'] = 1;
   chars['l'] = 1;   chars['L'] = 1;   chars['^'] = 1;
   chars['m'] = 1;   chars['M'] = 1;   chars['|'] = 1;   chars['\n'] = 1;
   chars['n'] = 1;   chars['N'] = 1;                     chars['\t'] = 1;
   chars['o'] = 1;   chars['O'] = 1;   chars['{'] = 1;   chars['\b'] = 1;
   chars['p'] = 1;   chars['P'] = 1;   chars['}'] = 1;   chars['\r'] = 1;
   chars['q'] = 1;   chars['Q'] = 1;   chars['['] = 1;   chars['\f'] = 1;
   chars['r'] = 1;   chars['R'] = 1;   chars[']'] = 1;
   chars['s'] = 1;   chars['S'] = 1;   chars['+'] = 1;   chars['\\'] = 1;
   chars['t'] = 1;   chars['T'] = 1;   chars[';'] = 1;   chars['\''] = 1;
   chars['u'] = 1;   chars['U'] = 1;   chars['*'] = 1;  
   chars['v'] = 1;   chars['V'] = 1;   chars[':'] = 1;   chars['\0'] = 1;
   chars['w'] = 1;   chars['W'] = 1;   chars['<'] = 1;   chars[' '] = 1;
   chars['x'] = 1;   chars['X'] = 1;   chars['>'] = 1;
   chars['y'] = 1;   chars['Y'] = 1;   chars[','] = 1;
   chars['z'] = 1;   chars['Z'] = 1;   chars['.'] = 1;
                                       chars['?'] = 1;
                                       chars['/'] = 1;

   if(sumof(chars) != 98){
     rc = rc+1;
     if(pd0->flgd != 0) printf(s243er,1);
   }

   /* Finally, the escape \ddd consists of the backslash followed
      by 1, 2, or 3 octal digits which are taken to specify  the
      desired character.                           */

   if( '\0'    !=   0 || '\01'   !=   1 || '\02'   !=   2
    || '\03'   !=   3 || '\04'   !=   4 || '\05'   !=   5
    || '\06'   !=   6 || '\07'   !=   7 || '\10'   !=   8
    || '\17'   !=  15 || '\20'   !=  16 || '\77'   !=  63
    || '\100'  !=  64 || '\177'  != 127                 ){
   
     rc = rc+8;
     if(pd0->flgd != 0) printf(s243er,8);
   }

   return rc;
}
zerofill(x)
char *x;
{
   int j;

   for (j=0; j<256; j++) *x++ = 0;
}
sumof(x)
char *x;
{
   char *p;
   int total, j;

   p = x;
   total = 0;

   for(j=0; j<256; j++) total = total+ *p++;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -