/*	ansi.cc
	Copyright (c) 1992-96 by Abraxas Software. All rights reserved.
==============================================================================
	Purpose:	Checks for compatibility with ANSI C standards.
	Author:		Loren Cobb.
	Revision:	12 October 1994.
	Format:		Monospaced font with 4 spaces/tab.
==============================================================================

Abstract:

	These CodeCheck rules check for compatibility with the ANSI C
	Standard. These rules are not comprehensive, but they do check
	for a great many of the troublesome areas of ANSI compliance.
	
	These rules are applied to all headers that are included in double
	quotes, e.g. #include "project.h". For proper use of these rules, be
	sure to include system headers in angle brackets: #include <ctypes.h.

	DOS and OS/2 only: do not use the -K1 or -K0 options with these rules,
	as this will prevent CodeCheck from parsing (and detecting) non-ANSI
	keywords such as near, far, huge, pascal, etc.

Warning Codes:

8001	Rule file ansi.cc should not be run with option -K1 or -K2.
8002	Octal digits 8 and 9 are illegal in ANSI C.
8003	The long float type is illegal in ANSI C.
8004	ANSI C files must end with a newline character.
8005	String literal too long for ANSI C.
8006	ANSI C does not expand macros inside strings.
8007	ANSI C will recode the trigraph in this string.
8008	Too many parameters in this macro.
8009	This comment will not paste tokens in ANSI C.
8010	Header file nesting is too deep.
8011	This preprocessor usage is not allowed in ANSI C.
8012	ANSI C does not permit sizeof in directives.
8013	ANSI C does not parse tokens that follow a preprocessor directive.
8014	Not an ANSI preprocessor directive.
8015	This declaration is not valid.
8016	Only 31 chars are significant.
8017	Use double instead of long float.
8018	ANSI C requires 3 dots (...) here.
8019	Return type for this function should be specified.
8020	An explicit type is required in ANSI C declarations.
8021	Local static function declarations are not allowed in ANSI C.
8022	Zero-length arrays are illegal in ANSI C.
8023	This function has no prototype.
8024	Too many macros for some ANSI compilers.
8025	 is not an ANSI type specifier.
8026	For Apple "extended" type use ANSI "long double".
8027	Non-ANSI type modifier (pascal, cdecl, near, far, huge,
			interrupt, export, loadds, saveregs, based, or fastcall).
8028	Non-ANSI placement of const or volatile.
8029	Non-ANSI function type specifier (inline, virtual, pure, pascal,
			cdecl, interrupt, loadds, saveregs, fastcall, or export).
8030	Nested comments are not allowed in ANSI C.
8031	The preceding label is not attached to a statement.
8032	Array  must be declared extern.
8033	Binary constants are not permitted in ANSI C.
8034	: Prefix  is reserved by ANSI.
8035	ANSI C does not use va_dcl.
8036	Macro va_start has two arguments in ANSI C.
8037	Replace header 
with
. 8038 Replace function with . 8039 Replacement of preprocessor commands is not allowed in ANSI C. 8040 Empty initializers are not allowed in ANSI C. ============================================================================== */ #include <check.cch #define REPLACE_HDR(hdr1,hdr2) if ( strcmp(header_name(),hdr1) == 0 ) \ warn( 8037, "Replace header " hdr1 " with " hdr2 "."); #define REPLACE_FCN(fname,gname) if ( strcmp(op_function(),fname) == 0 ) \ warn( 8038, "Replace " fname " with " gname "."); int ch, // Character that follows a prefix. k, // counter for dcl_level(k) non_ANSI_mod, // Non-ANSI type modifier flags varargs_included; // True if <varargs.h was included. if ( prj_begin ) { /* Flags for non-ANSI type and pointer modifiers: */ non_ANSI_mod = ~(CONST_FLAG + VOLATILE_FLAG); /* Make sure that extended keywords are allowed on DOS machines: */ #ifdef __MSDOS__ if ( option('K') <3 ) { warn( 8001, "Rule file ansi.cc should not be run with -K1 or -K2." ); } #endif } if ( lex_big_octal ) warn( 8002, "Octal digits 8 and 9 are illegal in ANSI C." ); if ( lex_long_float ) warn( 8003, "The long float type is illegal in ANSI C." ); if ( lex_nl_eof ) warn( 8004, "ANSI C files must end with a newline character." ); if ( lex_str_length > 509 ) warn( 8005, "String literal too long for ANSI C." ); if ( lex_str_macro ) warn( 8006, "ANSI C does not expand macros inside strings." ); if ( lex_str_trigraph ) warn( 8007, "ANSI C will recode the trigraph in this string." ); if ( pp_arg_count 31 ) warn( 8008, "Too many parameters in this macro." ); if ( pp_comment ) warn( 8009, "This comment will not paste tokens in ANSI C." ); if ( pp_if_depth 8 ) warn( 8010, "Header file nesting is too deep." ); if ( pp_not_ansi ) warn( 8011, "This preprocessor usage is not allowed in ANSI C." ); if ( pp_sizeof ) warn( 8012, "ANSI C does not permit sizeof in directives." ); if ( pp_trailer ) warn( 8013, "ANSI C does not parse tokens that follow a preprocessor directive." ); if ( pp_unknown ) warn( 8014, "Not an ANSI preprocessor directive." ); if ( dcl_empty ) if ( ! dcl_tag_def ) warn( 8015, "This declaration is not valid." ); if ( dcl_ident_length 31 ) warn( 8016, "Only 31 chars are significant." ); if ( dcl_long_float ) warn( 8017, "Use double instead of long float." ); if ( dcl_need_3dots ) warn( 8018, "ANSI C requires 3 dots (...) here." ); if ( dcl_no_specifier ) { if ( dcl_function ) warn( 8019, "Return type for function %s should be specified.", dcl_name() ); else warn( 8020, "An explicit type for %s is required in ANSI C.", dcl_name() ); } if ( dcl_static ) if ( dcl_local && dcl_function ) warn( 8021, "Local static function declarations are not allowed in ANSI C." ); if ( dcl_zero_array ) warn( 8022, "Zero-length arrays are illegal in ANSI C." ); if ( idn_no_prototype ) warn( 8023, "Function %s has no prototype.", idn_name() ); if ( mod_macros 1024 ) warn( 8024, "Too many macros for some ANSI compilers."); if ( dcl_base == EXTRA_INT_TYPE ) if ( lin_header != SYS_HEADER ) warn( 8025, "non-ANSI integer type." ); if ( dcl_base == EXTRA_UINT_TYPE ) if ( lin_header != SYS_HEADER ) warn( 8025, "non-ANSI unsigned type." ); if ( dcl_base == EXTRA_FLOAT_TYPE ) if ( lin_header != SYS_HEADER ) warn( 8025, "non-ANSI float type." ); if ( dcl_base == EXTRA_PTR_TYPE ) if ( lin_header != SYS_HEADER ) warn( 8025, "non-ANSI pointer type." ); if ( dcl_storage_flags & GLOBAL_SC ) if ( lin_header != SYS_HEADER ) warn( 8025, "VAX globaldef and globalref are not ANSI type specifiers." ); if ( keyword("comp") ) if ( lin_header != SYS_HEADER ) warn( 8025, "Apple comp is not an ANSI type specifier." ); if ( keyword("extended") ) if ( lin_header != SYS_HEADER ) warn( 8026, "For Apple \"extended\" type use ANSI \"long double\"." ); if ( dcl_variable || dcl_function ) if ( lin_header != SYS_HEADER ) { k = 0; while ( k <= dcl_levels ) if ( dcl_level_flags(k++) & non_ANSI_mod ) warn( 8027, "Non-ANSI type modifier." ); } if ( dcl_cv_modifier ) if ( lin_header != SYS_HEADER ) warn( 8028, "Non-ANSI placement of const or volatile." ); if ( dcl_function_flags ) warn( 8029, "Non-ANSI function type specifier." ); if ( lin_nested_comment ) { warn( 8030, "Nested comments are not allowed in ANSI C." ); // If you want CodeCheck to assume that nested comments are okay as // soon as it finds the first such comment, then enable these 2 lines: /* if ( option('N') == 0 ) // Assume that the rest of this file set_option( 'N', 1 ); // will contain nested comments too. */ } // Although many modern compilers allow labels that are not attached // to any statement, e.g. at the end of a block, this is not allowed // by the ANSI standard. if ( stm_bad_label ) warn( 8031, "The preceding label is not attached to a statement." ); // Detects local arrays that have no explicit dimension. Some // pre-ANSI compilers consider such arrays to be implicitly // external (i.e. the identifier has file scope and external // linkage). This interpretation is not allowed in ANSI C. if ( dcl_level(0) == ARRAY ) if ( dcl_local && (dcl_array_size == -1) && (! dcl_parameter) ) if ( (! dcl_extern) && (! dcl_initializer) ) warn( 8032, "Array %s must be declared extern.", dcl_name() ); // Detect Zortech binary constants (e.g. 0b10101001): if ( lex_radix == 2 ) if ( lin_header != SYS_HEADER ) warn( 8033, "Binary constants are not permitted in ANSI C." ); // Check each external identifier for reserved prefixes: if ( (dcl_global && ! dcl_static) || pp_macro ) if ( lin_header != SYS_HEADER ) { if ( prefix("E") ) { ch = root()[0]; if ( isdigit(ch) || isupper(ch) ) warn( 8034, "%s: prefix E is reserved by ANSI.", dcl_name() ); } if ( prefix("is") ) { ch = root()[0]; if ( islower(ch) ) warn( 8034, "%s: prefix \"is\" is reserved by ANSI.", dcl_name() ); } else if ( prefix("to") ) { ch = root()[0]; if ( islower(ch) ) warn( 8034, "%s: prefix to is reserved by ANSI.", dcl_name() ); } else if ( prefix("LC_") ) { ch = root()[0]; if ( isupper(ch) ) warn( 8034, "%s: prefix LC_ is reserved by ANSI.", dcl_name() ); } else if ( prefix("SIG") ) { ch = root()[0]; if ( isupper(ch) || (ch == '_') ) warn( 8034, "%s: prefix SIG is reserved by ANSI.", dcl_name() ); } else if ( prefix("mem") ) { ch = root()[0]; if ( islower(ch) ) warn( 8034, "%s: prefix mem is reserved by ANSI.", dcl_name() ); } else if ( prefix("str") ) { ch = root()[0]; if ( islower(ch) ) warn( 8034, "%s: prefix str is reserved by ANSI.", dcl_name() ); } else if ( prefix("wcs") ) { ch = root()[0]; if ( islower(ch) ) warn( 8034, "%s: prefix wcs is reserved by ANSI.", dcl_name() ); } } if ( macro("va_dcl") ) warn( 8035, "ANSI C does not use va_dcl." ); if ( macro("va_start") ) if ( varargs_included ) warn( 8036, "Macro va_start has two arguments in ANSI C." ); if ( header_name() ) { if ( strcmp(header_name(),"varargs.h") == 0 ) { warn( 8037, "Replace <varargs.h with <stdargs.h." ); varargs_included = 1; } else REPLACE_HDR( "memory.h", "string.h" ) else REPLACE_HDR( "sys/times.h", "time.h" ) } if ( op_call ) { REPLACE_FCN( "cfree", "free" ) else REPLACE_FCN( "bcmp", "strcmp" ) else REPLACE_FCN( "bzero", "memset" ) else REPLACE_FCN( "strpos", "strchr" ) else REPLACE_FCN( "strrpos", "strrchr" ) else REPLACE_FCN( "mktemp", "tmpnam" ) } if ( pp_sub_keyword ) warn( 8039, "Replacement of preprocessor commands is not allowed in ANSI C." ); if ( exp_empty_initializer ) warn( 8040, "Empty initializers are not allowed in ANSI C." );