Files correlati : Commento : Aggiunto il preprocessore c++ mcpp per sostituire il compilatore nella compilazione delle maschere.
		
			
				
	
	
		
			958 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			958 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  *      n_std.c
 | |
|  *
 | |
|  * 1998/08      made public                                     kmatsui
 | |
|  * 2002/08      revised not to conflict with C99 Standard       kmatsui
 | |
|  * 2004/10      added a few testcases for macro expansion       kmatsui
 | |
|  *
 | |
|  *   Samples to test Standard C preprocessing.
 | |
|  *   This is a strictly-comforming program.
 | |
|  *   Any Standard-comforming translator must translate successfully this
 | |
|  * program.  The generated execution program must be executed with the message
 | |
|  * <End of "n_std.c"> on stdout and no other messages on stderr.
 | |
|  *   A translator must process also #error directive properly, which is not
 | |
|  * included here because the directive might cause translator to terminate.
 | |
|  */
 | |
| 
 | |
| 
 | |
| #include    "defs.h"
 | |
| 
 | |
| #define ZERO_TOKEN
 | |
| #define TWO_ARGS        a,b
 | |
| #define MACRO_0         0
 | |
| #define MACRO_1         1
 | |
| #define sub( x, y)      (x - y)
 | |
| #define str( a)         # a
 | |
| #define xstr( a)        str( a)
 | |
| #define glue( a, b)     a ## b
 | |
| #define xglue( a, b)    glue( a, b)
 | |
| 
 | |
| void    n_1( void);
 | |
| void    n_2( void);
 | |
| void    n_3( void);
 | |
| void    n_4( void);
 | |
| void    n_5( void);
 | |
| void    n_6( void);
 | |
| void    n_7( void);
 | |
| void    n_9( void);
 | |
| void    n_10( void);
 | |
| void    n_11( void);
 | |
| void    n_12( void);
 | |
| void    n_13( void);
 | |
| void    n_13_5( void);
 | |
| void    n_13_7( void);
 | |
| void    n_13_8( void);
 | |
| void    n_13_13( void);
 | |
| void    n_15( void);
 | |
| void    n_18( void);
 | |
| void    n_19( void);
 | |
| void    n_20( void);
 | |
| void    n_21( void);
 | |
| void    n_22( void);
 | |
| void    n_23( void);
 | |
| void    n_24( void);
 | |
| void    n_25( void);
 | |
| void    n_26( void);
 | |
| void    n_27( void);
 | |
| void    n_28( void);
 | |
| void    n_29( void);
 | |
| void    n_30( void);
 | |
| void    n_32( void);
 | |
| void    n_37( void);
 | |
| 
 | |
| int main( void)
 | |
| {
 | |
|     n_1();
 | |
|     n_2();
 | |
|     n_3();
 | |
|     n_4();
 | |
|     n_5();
 | |
|     n_6();
 | |
|     n_7();
 | |
|     n_9();
 | |
|     n_10();
 | |
|     n_11();
 | |
|     n_12();
 | |
|     n_13();
 | |
|     n_13_5();
 | |
|     n_13_7();
 | |
|     n_13_8();
 | |
|     n_13_13();
 | |
|     n_15();
 | |
|     n_18();
 | |
|     n_19();
 | |
|     n_20();
 | |
|     n_21();
 | |
|     n_22();
 | |
|     n_23();
 | |
|     n_24();
 | |
|     n_25();
 | |
|     n_26();
 | |
|     n_27();
 | |
|     n_28();
 | |
|     n_29();
 | |
|     n_30();
 | |
|     n_32();
 | |
|     n_37();
 | |
|     puts( "<End of \"n_std.c\">");
 | |
|     return  0;
 | |
| }
 | |
| 
 | |
| char    quasi_trigraph[] = { '?', '?', ' ', '?', '?', '?', ' '
 | |
|             , '?', '?', '%', ' ', '?', '?', '^', ' ', '?', '#', '\0' };
 | |
| 
 | |
| void    n_1( void)
 | |
| /*      Conversion of trigraph sequences.   */
 | |
| {
 | |
|     int     ab = 1, cd = 2;
 | |
| 
 | |
| /* 1.1: The following 9 sequences are valid trigraph sequences. */
 | |
|     assert( strcmp( "??( ??) ??/??/ ??' ??< ??> ??! ??- ??="
 | |
|             ,"[ ] \\ ^ { } | ~ #") == 0);
 | |
| 
 | |
| /* 1.2: In directive line.  */
 | |
| ??= define  OR( a, b)   a ??! b
 | |
|     assert( OR( ab, cd) == 3);
 | |
| 
 | |
| /* 1.3: Any sequence other than above 9 is not a trigraph sequence. */
 | |
|     assert( strcmp( "?? ??? ??% ??^ ???=", quasi_trigraph) == 0);
 | |
| }
 | |
| 
 | |
| void    n_2( void)
 | |
| /*      Line splicing by <backslash><newline> sequence. */
 | |
| {
 | |
|     int     ab = 1, cd = 2, ef = 3, abcde = 5;
 | |
| 
 | |
| /* 2.1: In a #define directive line, between the parameter list and the
 | |
|         replacement text.   */
 | |
| #define FUNC( a, b, c)  \
 | |
|         a + b + c
 | |
|     assert( FUNC( ab, cd, ef) == 6);
 | |
| 
 | |
| /* 2.2: In a #define directive line, among the parameter list and among the
 | |
|         replacement text.   */
 | |
| #undef  FUNC
 | |
| #define FUNC( a, b  \
 | |
|     , c)            \
 | |
|     a + b           \
 | |
|     + c
 | |
|     assert (FUNC( ab, cd, ef) == 6);
 | |
| 
 | |
| /* 2.3: In a string literal.    */
 | |
|     assert (strcmp( "abc\
 | |
| de", "abcde") == 0);
 | |
| 
 | |
| /* 2.4: <backslash><newline> in midst of an identifier. */
 | |
|     assert( abc\
 | |
| de == 5);
 | |
| 
 | |
| /* 2.5: <backslash><newline> by trigraph.   */
 | |
|     assert( abc??/
 | |
| de == 5);
 | |
| }
 | |
| 
 | |
| void    n_3( void)
 | |
| /*      Handling of comment.    */
 | |
| {
 | |
|     int     abcd = 4;
 | |
| 
 | |
| /* 3.1: A comment is converted to one space.    */
 | |
|     assert( strcmp( str( abc/* comment */de), "abc de") == 0);
 | |
| 
 | |
| /* 3.2: // is not a comment of C.   */
 | |
| /*    assert( strcmp( str( //), "//") == 0);    */
 | |
| 
 | |
| /* 3.3: Comment is parsed prior to the parsing of preprocessing directive.  */
 | |
| #if     0
 | |
|     "nonsence"; /*
 | |
| #else
 | |
|     still in
 | |
|     comment     */
 | |
| #else
 | |
| #define MACRO_abcd  /*
 | |
|     in comment
 | |
|     */  abcd
 | |
| #endif
 | |
|     assert( MACRO_abcd == 4);
 | |
| }
 | |
| 
 | |
| void    n_4( void)
 | |
| /* Special tokens.  */
 | |
| {
 | |
| /* 4.1: Digraph spellings in directive line.    */
 | |
| %: define  stringize( a)    %: a
 | |
| 
 | |
|     assert( strcmp( stringize( abc), "abc") == 0);
 | |
| 
 | |
| /* 4.2: Digraph spellings are retained in stringization.    */
 | |
|     assert( strcmp( stringize( <:), "<" ":") == 0);
 | |
| }
 | |
| 
 | |
| void    n_5( void)
 | |
| /*      Spaces or tabs are allowed at any place in pp-directive line,
 | |
|         including between the top of a pp-directive line and '#', and between
 | |
|         the '#' and the directive. */
 | |
| {
 | |
|     int     abcde = 5;
 | |
| /*  |**|[TAB]# |**|[TAB]define |**| MACRO_abcde[TAB]|**| abcde |**| */
 | |
| /**/    # /**/  define /**/ MACRO_abcde /**/ abcde /**/
 | |
|     assert( MACRO_abcde == 5);
 | |
| }
 | |
| 
 | |
| /* 6.1: Header-name quoted by " and " as well as by < and > can include
 | |
|         standard headers.   */
 | |
| /* Note: Standard headers can be included any times.    */
 | |
| #include    "ctype.h"
 | |
| #include    <ctype.h>
 | |
| 
 | |
| void    n_6( void)
 | |
| /*      #include directive. */
 | |
| {
 | |
|     int     abc = 3;
 | |
| 
 | |
|     assert( isalpha( 'a'));
 | |
| 
 | |
| /* 6.2: Macro is allowed in #include line.  */
 | |
| #define HEADER  "header.h"
 | |
| #include    HEADER
 | |
|     assert( MACRO_abc == 3);
 | |
| 
 | |
| /* 6.3: With macro nonsence but legal.  */
 | |
| #undef  MACRO_abc
 | |
| #include    ZERO_TOKEN HEADER ZERO_TOKEN
 | |
|     assert( MACRO_abc == 3);
 | |
| }
 | |
| 
 | |
| void    n_7( void)
 | |
| /*      #line directive.    */
 | |
| {
 | |
| /* 7.1: Line number and filename.   */
 | |
| #line   1234    "cpp"
 | |
|     assert( __LINE__ == 1234);
 | |
|     assert( strcmp( __FILE__, "cpp") == 0);
 | |
| 
 | |
| /* 7.2: Filename argument is optional.  */
 | |
| #line   2345
 | |
|     assert( __LINE__ == 2345);
 | |
|     assert( strcmp( __FILE__, "cpp") == 0);
 | |
| 
 | |
| /* 7.3: Argument with macro.    */
 | |
| #define LINE_AND_FILENAME   1234 "n_7.c"
 | |
| #line   LINE_AND_FILENAME
 | |
|     assert( __LINE__ == 1234);
 | |
|     assert( strcmp( __FILE__, "n_7.c") == 0);
 | |
| }
 | |
| 
 | |
| /* Restore to correct line number and filename. */
 | |
| #line   248 "n_std.c"
 | |
| 
 | |
| void    n_9( void)
 | |
| /*      #pragma directive.  */
 | |
| {
 | |
| /* 9.1: Any #pragma directive should be processed or ignored, should not
 | |
|         be diagnosed as an error.   */
 | |
| #pragma once
 | |
| #pragma who knows ?
 | |
| }
 | |
| 
 | |
| void    n_10( void)
 | |
| /*      #if, #elif, #else and #endif pp-directive.  */
 | |
| {
 | |
| /* 10.1:    */
 | |
| /* Note: an undefined identifier in #if expression is replaced to 0.    */
 | |
| #if     a
 | |
|     assert( a);
 | |
| #elif   MACRO_0
 | |
|     assert( MACRO_0);
 | |
| #elif   MACRO_1         /* Valid block  */
 | |
|     assert( MACRO_1);
 | |
| #else
 | |
|     assert( 0);
 | |
| #endif
 | |
| 
 | |
| /* 10.2:    Comments must be processed even if in skipped #if block.    */
 | |
| /* At least tokenization of string literal and character constant is necessary
 | |
|         to process comments, e.g. /* is not a comment mark in string literal.
 | |
|  */
 | |
| #ifdef  UNDEFINED
 | |
|     /* Comment  */
 | |
|     "in literal /* is not a comment"
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void    n_11( void)
 | |
| /*      Operator "defined" in #if or #elif directive.   */
 | |
| {
 | |
|     int     abc = 1, a = 0;
 | |
| 
 | |
| /* 11.1:    */
 | |
| #undef  MACRO_abc
 | |
| #define MACRO_abc   abc
 | |
| #if     defined a
 | |
|     assert( a);
 | |
| #else
 | |
|     assert( MACRO_abc);
 | |
| #endif
 | |
| #if     defined (MACRO_abc)
 | |
|     assert( MACRO_abc);
 | |
| #else
 | |
|     assert( a);
 | |
| #endif
 | |
| 
 | |
| /* 11.2:    "defined" is an unary operator whose result is 1 or 0.  */
 | |
| #if     defined MACRO_0 * 3 != 3
 | |
|     fputs( "Bad handling of defined operator.\n", stderr);
 | |
| #endif
 | |
| #if     (!defined ZERO_TOKEN != 0) || (-defined ZERO_TOKEN != -1)
 | |
|     fputs( "Bad grouping of defined, -, ! in #if expression.\n", stderr);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| #include    <limits.h>
 | |
| 
 | |
| void    n_12( void)
 | |
| /*      Integer preprocessing number token and type of #if expression.  */
 | |
| {
 | |
| /* 12.1:    */
 | |
| #if     LONG_MAX <= LONG_MIN
 | |
|     fputs( "Bad evaluation of long.\n", stderr);
 | |
| #endif
 | |
| #if     LONG_MAX <= 1073741823  /* 0x3FFFFFFF   */
 | |
|     fputs( "Bad evaluation of long.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* 12.2:    */
 | |
| #if     ULONG_MAX / 2 < LONG_MAX
 | |
|     fputs( "Bad evaluation of unsigned long.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* 12.3:    Octal number.   */
 | |
| #if     0177777 != 65535
 | |
|     fputs( "Bad evaluation of octal number.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* 12.4:    Hexadecimal number. */
 | |
| #if     0Xffff != 65535 || 0XFfFf != 65535
 | |
|     fputs( "Bad evaluation of hexadecimal number.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* 12.5:    Suffix 'L' or 'l'.  */
 | |
| #if     0L != 0 || 0l != 0
 | |
|     fputs( "Bad evaluation of 'L' suffix.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* 12.6:    Suffix 'U' or 'u'.  */
 | |
| #if     1U != 1 || 1u != 1
 | |
|     fputs( "Bad evaluation of 'U' suffix.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* 12.7:    Negative integer.   */
 | |
| #if     0 <= -1
 | |
|     fputs( "Bad evaluation of negative number.\n", stderr);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void    n_13( void)
 | |
| /*      evaluation of #if expressions.  */
 | |
| /* Valid operators are (precedence in this order) :
 | |
|     defined, (unary)+, (unary)-, ~, !,
 | |
|     *, /, %,
 | |
|     +, -,
 | |
|     <<, >>,
 | |
|     <, >, <=, >=,
 | |
|     ==, !=,
 | |
|     &,
 | |
|     ^,
 | |
|     |,
 | |
|     &&,
 | |
|     ||,
 | |
|     ? :
 | |
|  */
 | |
| {
 | |
| /* 13.1:    Bit shift.  */
 | |
| #if     1 << 2 != 4 || 8 >> 1 != 4
 | |
|     fputs( "Bad arithmetic of <<, >> operators.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* 13.2:    Bitwise operators.  */
 | |
| #if     (3 ^ 5) != 6 || (3 | 5) != 7 || (3 & 5) != 1
 | |
|     fputs( "Bad arithmetic of ^, |, & operators.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* 13.3:    Result of ||, && operators is either of 1 or 0. */
 | |
| #if     (2 || 3) != 1 || (2 && 3) != 1 || (0 || 4) != 1 || (0 && 5) != 0
 | |
|     fputs( "Bad arithmetic of ||, && operators.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* 13.4:    ?, : operator.  */
 | |
| #if     (0 ? 1 : 2) != 2
 | |
|     fputs( "Bad arithmetic of ?: operator.\n", stderr);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void    n_13_5( void)
 | |
| /*      Arithmetic conversion in #if expressions.   */
 | |
| {
 | |
| /* 13.5:    The usual arithmetic conversion is not performed on bit shift.  */
 | |
| #if     -1 << 3U > 0
 | |
|     fputs( "Bad conversion of bit shift operands.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* 13.6:    Usual arithmetic conversions.   */
 | |
| #if     -1 <= 0U        /* -1 is converted to unsigned long.    */
 | |
|     fputs( "Bad arithmetic conversion.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| #if     -1 * 1U <= 0
 | |
|     fputs( "Bad arithmetic conversion.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* Second and third operands of conditional operator are converted to the
 | |
|         same type, thus -1 is converted to unsigned long.    */
 | |
| #if     (1 ? -1 : 0U) <= 0
 | |
|     fputs( "Bad arithmetic conversion.\n", stderr);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void    n_13_7( void)
 | |
| /*      Short-circuit evaluation of #if expression. */
 | |
| {
 | |
| /* 13.7:    10/0 or 10/MACRO_0 are never evaluated, "divide by zero" error
 | |
|         cannot occur.   */
 | |
| 
 | |
| #if     0 && 10 / 0
 | |
| #endif
 | |
| #if     not_defined && 10 / not_defined
 | |
| #endif
 | |
| #if     MACRO_0 && 10 / MACRO_0 > 1
 | |
| #endif
 | |
| #if     MACRO_0 ? 10 / MACRO_0 : 0
 | |
| #endif
 | |
| #if     MACRO_0 == 0 || 10 / MACRO_0 > 1        /* Valid block  */
 | |
| #else
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void    n_13_8( void)
 | |
| /*      Grouping of sub-expressions in #if expression.  */
 | |
| {
 | |
| /* 13.8:    Unary operators are grouped from right to left. */
 | |
| #if     (- -1 != 1) || (!!9 != 1) || (-!+!9 != -1) || (~~1 != 1)
 | |
|     fputs( "Bad grouping of -, +, !, ~ in #if expression.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* 13.9:    ?: operators are grouped from right to left.    */
 | |
| #if     (1 ? 2 ? 3 ? 3 : 2 : 1 : 0) != 3
 | |
|     fputs( "Bad grouping of ? : in #if expression.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* 13.10:   Other operators are grouped from left to right. */
 | |
| #if     (15 >> 2 >> 1 != 1) || (3 << 2 << 1 != 24)
 | |
|     fputs( "Bad grouping of >>, << in #if expression.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* 13.11:   Test of precedence. */
 | |
| #if     3*10/2 >> !0*2 >> !+!-9 != 1
 | |
|     fputs( "Bad grouping of -, +, !, *, /, >> in #if expression.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* 13.12:   Overall test.  Grouped as:
 | |
|         ((((((+1 - -1 - ~~1 - -!0) & 6) | ((8 % 9) ^ (-2 * -2))) >> 1) == 7)
 | |
|         ? 7 : 0) != 7
 | |
|     evaluated to FALSE.
 | |
|  */
 | |
| #if     (((+1- -1-~~1- -!0&6|8%9^-2*-2)>>1)==7?7:0)!=7
 | |
|     fputs( "Bad arithmetic of #if expression.\n", stderr);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void    n_13_13( void)
 | |
| /*      #if expression with macros. */
 | |
| {
 | |
| #define and             &&
 | |
| #define or              ||
 | |
| #define not_eq          !=
 | |
| #define bitor           |
 | |
| 
 | |
| /* 13.13:   With macros expanding to operators. */
 | |
| #if     (1 bitor 2) == 3 and 4 not_eq 5 or 0
 | |
|     /* #if (1 | 2) == 3 && 4 != 5 || 0  */
 | |
| #else
 | |
|     fputs(
 | |
|     "Bad evaluation of macros expanding to operators in #if expression.\n"
 | |
|         , stderr);
 | |
| #endif
 | |
| 
 | |
| /* 13.14:   With macros expanding to 0 token, nonsence but legal.   */
 | |
| #if     ZERO_TOKEN MACRO_1 ZERO_TOKEN > ZERO_TOKEN MACRO_0 ZERO_TOKEN
 | |
|     /* #if 1 > 0    */
 | |
| #else
 | |
|     fputs(
 | |
|     "Bad evaluation of macros expanding to 0 token in #if expression.\n"
 | |
|         , stderr);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void    n_15( void)
 | |
| /*      #ifdef, #ifndef directives. */
 | |
| {
 | |
| 
 | |
| /* 15.1:    #ifdef directive.   */
 | |
| #ifdef  MACRO_1         /* Valid block  */
 | |
|     assert( MACRO_1);
 | |
| #else
 | |
|     assert( MACRO_0);
 | |
| #endif
 | |
| 
 | |
| /* 15.2:    #ifndef directive.  */
 | |
| #ifndef MACRO_1
 | |
|     assert( MACRO_0);
 | |
| #else               /* Valid block  */
 | |
|     assert( MACRO_1);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void    n_18( void)
 | |
| /*      #define directive.  */
 | |
| /* Excerpts from ISO C 6.8.3 "Examples".    */
 | |
| #define OBJ_LIKE        (1-1)
 | |
| #define FTN_LIKE(a)     ( a )
 | |
| {
 | |
|     int     c = 3;
 | |
| 
 | |
| /* 18.1:    Definition of an object-like macro. */
 | |
|     assert( OBJ_LIKE == 0);
 | |
| #ifndef ZERO_TOKEN
 | |
|     fputs( "Can't define macro to 0-token.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* 18.2:    Definition of a function-like macro.    */
 | |
|     assert( FTN_LIKE( c) == 3);
 | |
| 
 | |
| /* 18.3:    Spelling in string identical to parameter is not a parameter.   */
 | |
| #define STR( n1, n2)    "n1:n2"
 | |
|     assert( strcmp( STR( 1, 2), "n1:n2") == 0);
 | |
| }
 | |
| 
 | |
| void    n_19( void)
 | |
| /*      Valid re-definitions of macros. */
 | |
| {
 | |
|     int     c = 1;
 | |
| 
 | |
| /* 19.1:    */
 | |
| #define OBJ_LIKE    /* white space */  (1-1) /* other */
 | |
| 
 | |
| /* 19.2:    */
 | |
| #define FTN_LIKE( a     )(  /* note the white space */  \
 | |
|                         a  /* other stuff on this line
 | |
|                            */ )
 | |
|     assert( FTN_LIKE( c) == 1);
 | |
| }
 | |
| 
 | |
| void    n_20( void)
 | |
| /*      Macro lexically identical to keyword. */
 | |
| {
 | |
| /* 20.1:    */
 | |
| #define float   double
 | |
|     float   fl;
 | |
|     assert( sizeof fl == sizeof (double));
 | |
| }
 | |
| 
 | |
| void    n_21( void)
 | |
| /*      Tokenization (No preprocessing tokens are merged implicitly).   */
 | |
| {
 | |
|     int     a = 1, x = 2, y = -3;
 | |
| 
 | |
| /* 21.1:    */
 | |
| #define MINUS   -
 | |
|     assert( -MINUS-a == -1);
 | |
| 
 | |
| /* 21.2:    */
 | |
| #undef  sub
 | |
| #define sub( a, b)  a-b     /* '(a)-(b)' is better  */
 | |
| #define Y   -y              /* '(-y)' is better     */
 | |
| /*  x- -y   */
 | |
|     assert( sub( x, Y) == -1);
 | |
| }
 | |
| 
 | |
| void    n_22( void)
 | |
| /*      Tokenization of preprocessing number.   */
 | |
| {
 | |
| #define EXP         1
 | |
| 
 | |
| /* 22.1:    12E+EXP is a preprocessing number, EXP is not expanded. */
 | |
|     assert( strcmp( xstr( 12E+EXP), "12E+EXP") == 0);
 | |
| 
 | |
| /* 22.2:    .2e-EXP is also a preprocessing number. */
 | |
|     assert( strcmp( xstr( .2e-EXP), ".2e-EXP") == 0);
 | |
| 
 | |
| /* 22.3:    + or - is allowed only following E or e, 12+EXP is not a
 | |
|         preprocessing number.   */
 | |
|     assert( strcmp( xstr( 12+EXP), "12+1") == 0);
 | |
| }
 | |
| 
 | |
| void    n_23( void)
 | |
| /*      ## operator in macro definition.    */
 | |
| {
 | |
|     int     xy = 1;
 | |
| 
 | |
| /* 23.1:    */
 | |
|     assert( glue( x, y) == 1);
 | |
| 
 | |
| /* 23.2:    Generate a preprocessing number.    */
 | |
| #undef  EXP
 | |
| #define EXP     2
 | |
|     assert( xglue( .12e+, EXP) == 12.0);
 | |
| }
 | |
| 
 | |
| void    n_24( void)
 | |
| /*      # operator in macro definition. */
 | |
| {
 | |
| /* 24.1:    */
 | |
|     assert( strcmp( str( a+b), "a+b") == 0);
 | |
| 
 | |
| /* 24.2:    White spaces between tokens of operand are converted to one space.
 | |
|  */
 | |
|     assert( strcmp( str(    ab  /* comment */   +
 | |
|         cd  ), "ab + cd") == 0);
 | |
| 
 | |
| /* 24.3:    \ is inserted before \ and " in or surrounding literals and no
 | |
|         other character is inserted to anywhere.    */
 | |
|     assert( strcmp( str( '"' + "' \""), "'\"' + \"' \\\"\"") == 0);
 | |
| 
 | |
| /* 24.4:    Line splicing by <backslash><newline> is done prior to token
 | |
|         parsing.   */
 | |
|     assert( strcmp( str( "ab\
 | |
| c"), "\"abc\"") == 0);
 | |
| 
 | |
| /* 24.5:    Token separator inserted by macro expansion should be removed.
 | |
|         (Meanwhile, tokens should not be merged.  See 21.2.)    */
 | |
| #define f(a)        a
 | |
|     assert( strcmp( xstr( x-f(y)), "x-y") == 0);
 | |
| }
 | |
| 
 | |
| void    n_25( void)
 | |
| /*      Macro arguments are pre-expanded (unless the argument is an
 | |
|         operand of # or ## operator) separately, that is, are macro-replaced
 | |
|         completely prior to rescanning. */
 | |
| {
 | |
|     int     a = 1, b = 2, abc = 3, MACRO_0MACRO_1 = 2;
 | |
| 
 | |
| #undef sub
 | |
| #define sub( x, y)      (x - y)
 | |
| 
 | |
| /* 25.1:    "TWO_ARGS" is read as one argument to "sub", then expanded to
 | |
|         "a,b", then "x" is substituted by "a,b".    */
 | |
|     assert( sub( TWO_ARGS, 1) == 1);
 | |
| 
 | |
| /* 25.2:    An argument pre-expanded to 0-token.    */
 | |
|     assert( sub( ZERO_TOKEN, a) == -1);
 | |
| 
 | |
| /* 25.3:    "glue( a, b)" is pre-expanded.  */
 | |
|     assert( xglue( glue( a, b), c) == 3);
 | |
| 
 | |
| /* 25.4:    Operands of ## operator are not pre-expanded.   */
 | |
|     assert( glue( MACRO_0, MACRO_1) == 2);
 | |
| 
 | |
| /* 25.5:    Operand of # operator is not pre-expanded.  */
 | |
|     assert( strcmp( str( ZERO_TOKEN), "ZERO_TOKEN") == 0);
 | |
| }
 | |
| 
 | |
| #undef  f
 | |
| 
 | |
| #ifdef  void
 | |
| int     f( a)
 | |
|     int     a;
 | |
| {
 | |
|     return  a;
 | |
| }
 | |
| 
 | |
| int     g( a)
 | |
|     int     a;
 | |
| {
 | |
|     return  a * 2;
 | |
| }
 | |
| #else
 | |
| int     f( int a)
 | |
| {
 | |
|     return  a;
 | |
| }
 | |
| 
 | |
| int     g( int a)
 | |
| {
 | |
|     return  a * 2;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| void    n_26( void)
 | |
| /*      The name once replaced is not furthur replaced. */
 | |
| {
 | |
|     int     x = 1;
 | |
|     int     AB = 1;
 | |
|     int     Z[1];
 | |
|     Z[0] = 1;
 | |
| 
 | |
| /* 26.1:    Directly recursive macro definition.    */
 | |
| /*  Z[0];   */
 | |
| #define Z   Z[0]
 | |
|     assert( Z == 1);
 | |
| 
 | |
| /* 26.2:    Intermediately recursive macro definition.  */
 | |
| /*  AB; */
 | |
| #define AB  BA
 | |
| #define BA  AB
 | |
|     assert( AB == 1);
 | |
| 
 | |
| /* 26.3:    Directly recursive function-like macro definition.  */
 | |
| /*  x + f(x);   */
 | |
| #define f(a)    a + f(a)
 | |
|     assert( f( x) == 2);
 | |
| 
 | |
| /* 26.4:    Intermediately recursive function-like macro definition.    */
 | |
| /*  x + x + g( x);  */
 | |
| #define g(a)    a + h( a)
 | |
| #define h(a)    a + g( a)
 | |
|     assert( g( x) == 4);
 | |
| 
 | |
| /* 26.5:    Rescanning encounters the non-replaced macro name.  */
 | |
| /*  Z[0] + f( Z[0]);    */
 | |
|     assert( f( Z) == 2);
 | |
| }
 | |
| 
 | |
| void    n_27( void)
 | |
| /*      Rescanning of a macro raplace any macro call in the replacement
 | |
|         text after substitution of parameters by pre-expanded-arguments.  This
 | |
|         re-examination may involve the succeding sequences from the source
 | |
|         file (what a queer thing!). */
 | |
| {
 | |
|     int     a = 1, b = 2, c, m = 1, n = 2;
 | |
| 
 | |
| /* 27.1:    Cascaded use of object-like macros. */
 | |
| #define NEST8   NEST7 + 8
 | |
| #define NEST7   NEST6 + 7
 | |
| #define NEST6   NEST5 + 6
 | |
| #define NEST5   NEST4 + 5
 | |
| #define NEST4   NEST3 + 4
 | |
| #define NEST3   NEST2 + 3
 | |
| #define NEST2   NEST1 + 2
 | |
| #define NEST1   1
 | |
|     assert( NEST8 == 36);
 | |
| 
 | |
| /* 27.2:    Cascaded use of function-like macros.   */
 | |
| #define FUNC4( a, b)    FUNC3( a, b) + NEST4
 | |
| #define FUNC3( a, b)    FUNC2( a, b) + NEST3
 | |
| #define FUNC2( a, b)    FUNC1( a, b) + NEST2
 | |
| #define FUNC1( a, b)    (a) + (b)
 | |
|     assert( FUNC4( NEST1, NEST2) == 23);
 | |
| 
 | |
| /* 27.3:    An identifier generated by ## operator is subject to expansion. */
 | |
|     assert( glue( MACRO_, 1) == 1);
 | |
| 
 | |
| #define head            sub(
 | |
| #define math( op, a, b) op( (a), (b))
 | |
| 
 | |
| /* 27.4:    'sub' as an argument of math() is not pre-expanded, since '(' is
 | |
|         missing.    */
 | |
|     assert( math( sub, a, b) == -1);
 | |
| 
 | |
| /* 27.5:    Queer thing.    */
 | |
|     c = head a,b );
 | |
|     assert( c == -1);
 | |
| 
 | |
| /* 27.6:    Recursive macro (the 2nd 'm' is expanded to 'n' since it is in
 | |
|         source file).   */
 | |
| #define m       n
 | |
| #define n( a)   a 
 | |
|     assert( m( m) == 2);
 | |
| }
 | |
| 
 | |
| void    n_28( void)
 | |
| /*      __FILE__, __LINE__, __DATE__, __TIME__, __STDC__ and
 | |
|         __STDC_VERSION are predefined.  */
 | |
| {
 | |
|     char *  date = __DATE__;
 | |
| 
 | |
| /* 28.1:    */
 | |
|     assert( strcmp( __FILE__, "n_std.c") == 0);
 | |
| 
 | |
| /* 28.2:    */
 | |
|     assert( __LINE__ == 779);
 | |
| 
 | |
| /* 28.3:    */
 | |
|     assert( strlen( __DATE__) == 11);
 | |
|     assert( date[ 4] != '0');
 | |
| 
 | |
| /* 28.4:    */
 | |
|     assert( strlen( __TIME__) == 8);
 | |
| 
 | |
| /* 28.5:    */
 | |
|     assert( __STDC__);
 | |
| 
 | |
| /* 28.6:    */
 | |
|     assert( __STDC_VERSION__ >= 199409L);
 | |
| 
 | |
| /* 28.7:    */
 | |
| #include    "line.h"
 | |
| }
 | |
| 
 | |
| void    n_29( void)
 | |
| /*      #undef directive.   */
 | |
| {
 | |
|     int     DEFINED = 1;
 | |
| 
 | |
| /* 29.1:    Undefined macro is not a macro. */
 | |
| #define DEFINED
 | |
| #undef  DEFINED
 | |
|     assert( DEFINED == 1);
 | |
| 
 | |
| /* 29.2:    Undefining undefined name is not an error.  */
 | |
| #undef  UNDEFINED
 | |
| }
 | |
| 
 | |
| void    n_30( void)
 | |
| /*      Macro calls.    */
 | |
| /*  Note:   Comma separate the arguments of function-like macro call,
 | |
|         but comma between matching inner parenthesis doesn't.  This feature
 | |
|         is tested on so many places in this suite especially on *.c samples
 | |
|         which use assert() macro, that no separete item to test this feature
 | |
|         is provided.    */
 | |
| {
 | |
| #undef  FUNC
 | |
| #define FUNC( a, b, c)      a + b + c
 | |
| 
 | |
|     int     a = 1, b = 2, c = 3;
 | |
| 
 | |
| /* 30.1:    A macro may cross lines.    */
 | |
|     assert
 | |
|     (
 | |
|         FUNC
 | |
|         (
 | |
|             a,
 | |
|             b,
 | |
|             c
 | |
|         )
 | |
|         == 6
 | |
|     );
 | |
| }
 | |
| 
 | |
| void    n_32( void)
 | |
| /*      Escape sequence in character constant in #if expression.    */
 | |
| {
 | |
| /* 32.1:    Character octal escape sequence.    */
 | |
| #if     '\123' != 83
 | |
|     fputs( "Bad evaluation of octal escape sequence.\n", stderr);
 | |
| #endif
 | |
| 
 | |
| /* 32.2:    Character hexadecimal escape sequence.  */
 | |
| #if     '\x1b' != '\033'
 | |
|     fputs( "Bad evaluation of hexadecimal escape sequence.\n", stderr);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void    n_37( void)
 | |
| /* Translation limits.  */
 | |
| {
 | |
| #define     MACRO_8     8
 | |
| 
 | |
| /* 37.1:    Number of parameters in macro: at least 31. */
 | |
| #define glue31(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E)   \
 | |
|     a##b##c##d##e##f##g##h##i##j##k##l##m##n##o##p##q##r##s##t##u##v##w##x##y##z##A##B##C##D##E
 | |
| 
 | |
|     int     ABCDEFGHIJKLMNOPQRSTUVWXYZabcde = 31;
 | |
|     int     ABCDEFGHIJKLMNOPQRSTUVWXYZabcd_ = 30;
 | |
|     int     nest = 0;
 | |
| 
 | |
| /* 37.2:    Number of arguments in macro call: at least 31. */
 | |
|     assert(
 | |
|         glue31( A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R
 | |
|             , S, T, U, V, W, X, Y, Z, a, b, c, d, e)
 | |
|         == 31);
 | |
| 
 | |
| /* 37.3:    Significant initial characters in an internal identifier or a
 | |
|         macro name: at least 31.  */
 | |
|     assert( ABCDEFGHIJKLMNOPQRSTUVWXYZabcd_ == 30);
 | |
| 
 | |
| /* 37.4:    Nested conditional inclusion: at least 8 levels.    */
 | |
|     nest = 0;
 | |
| #ifdef  A
 | |
| #else
 | |
| #   ifdef   B
 | |
| #   else
 | |
| #       ifdef   C
 | |
| #       else
 | |
| #           ifdef   D
 | |
| #           else
 | |
| #               ifdef   E
 | |
| #               else
 | |
| #                   ifdef   F
 | |
| #                   else
 | |
| #                       ifdef   G
 | |
| #                       else
 | |
| #                           ifdef   H
 | |
| #                           else
 | |
|                                 nest = 8;
 | |
| #                           endif
 | |
| #                       endif
 | |
| #                   endif
 | |
| #               endif
 | |
| #           endif
 | |
| #       endif
 | |
| #   endif
 | |
| #endif
 | |
|     assert( nest == 8);
 | |
| 
 | |
| /* 37.5:    Nested source file inclusion: at least 8 levels.    */
 | |
|     nest = 0;
 | |
| #include    "nest1.h"
 | |
|     assert( nest == 8);
 | |
| 
 | |
| /* 37.6:    Parenthesized expression: at least 32 levels.   */
 | |
| #if     0 + (1 - (2 + (3 - (4 + (5 - (6 + (7 - (8 + (9 - (10 + (11 - (12 +  \
 | |
|         (13 - (14 + (15 - (16 + (17 - (18 + (19 - (20 + (21 - (22 + (23 -   \
 | |
|         (24 + (25 - (26 + (27 - (28 + (29 - (30 + (31 - (32 + 0))))))))))   \
 | |
|         )))))))))))))))))))))) == 0
 | |
|     nest = 32;
 | |
| #endif
 | |
|     assert( nest == 32);
 | |
| 
 | |
| /* 37.7:    Characters in a string (after concatenation): at least 509. */
 | |
|     {
 | |
|         char *  extremely_long_string =
 | |
| "123456789012345678901234567890123456789012345678901234567890123456789\
 | |
| 0123456789012345678901234567890123456789012345678901234567890123456789\
 | |
| 0123456789012345678901234567890123456789012345678901234567890123456789\
 | |
| 0123456789012345678901234567890123456789012345678901234567890123456789\
 | |
| 0123456789012345678901234567890123456789012345678901234567890123456789\
 | |
| 0123456789012345678901234567890123456789012345678901234567890123456789\
 | |
| 0123456789012345678901234567890123456789012345678901234567890123456789\
 | |
| 012345678901234567"
 | |
|         ;
 | |
|         assert( strlen( extremely_long_string) == 507);
 | |
|     }
 | |
| 
 | |
| /* 37.8:    Characters in a logical source line: at least 509.  */
 | |
|     {
 | |
|     int a123456789012345678901234567890 = 123450;   \
 | |
|     int b123456789012345678901234567890 = 123451;   \
 | |
|     int c123456789012345678901234567890 = 123452;   \
 | |
|     int d123456789012345678901234567890 = 123453;   \
 | |
|     int e123456789012345678901234567890 = 123454;   \
 | |
|     int f123456789012345678901234567890 = 123455;   \
 | |
|     int A123456789012345678901234567890 = 123456;   \
 | |
|     int B123456789012345678901234567890 = 123457;   \
 | |
|     int C123456789012345678901234567890 = 123458;   \
 | |
|     int D1234567890123456789012 = 123459;
 | |
|         assert( a123456789012345678901234567890 == 123450
 | |
|             && D1234567890123456789012 == 123459);
 | |
|     }
 | |
| 
 | |
| /* 37.9:    Macro definitions: at least 1024.   */
 | |
| #undef  AB
 | |
| #undef  BA
 | |
| #undef  OR
 | |
| 
 | |
| #include    "m1024.h"
 | |
|     assert( ZX);
 | |
| }
 | |
| 
 |