/* 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. 8025is 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." );