#!/usr/bin/perl -w # Approximation of iocccsize.c. # # We use this approximation instead of the official iocccsize.c because it's # more convenient to run this one on cygwin. This tool is an approximation # in the sense that it sometimes overestimates the byte size, but it should # never underestimate. So if this tool says the input does not exceed the # IOCCC limit, official iocccsize tool should agree. use strict; use constant SIZE_LIMIT => 2503; # Load input and overwrite comment regions. The overwrite step is to ensure # that contents of comment regions are not eligible for keyword discount. my $text = ""; my $comment = 0; my $previous = ""; while( my $line = <> ) { foreach my $c (map {chr} unpack "C*", $line) { if( $comment == 0 ) { # Check for start of comments. if( $previous eq "/" ) { if( $c eq "*" ) { $comment = 1; $c = "#"; } elsif( $c eq "/" ) { $comment = 2; $c = "#"; } } } elsif( $comment == 1 ) { # Check for end of block comments. if( $previous eq "*" && $c eq "/" ) { $comment = 0; } } elsif( $comment == 2 ) { # Check for end of single line comments. if( $c eq "\n" ) { $comment = 0; } } if( $c =~ /\s/ || $comment == 0 ) { $text .= $c; } else { $text .= "#"; } $previous = $c; } } # Discount keywords. $text =~ s/ (\#elif \b |\#elifdef \b |\#elifndef \b |\#else \b |\#embed \b |\#endif \b |\#error \b |\#ident \b |\#if \b |\#ifdef \b |\#ifndef \b |\#include \b |\#line \b |\#pragma \b |\#sccs \b |\#warning \b |\#undef \b |\b _Alignas \b |\b _Alignof \b |\b _Atomic \b |\b _BitInt \b |\b _Bool \b |\b _Complex \b |\b _Decimal128 \b |\b _Decimal64 \b |\b _Decimal32 \b |\b _Generic \b |\b _Imaginary \b |\b _Noreturn \b |\b _Pragma \b |\b _Static_assert \b |\b _Thread_local \b |\b alignas \b |\b alignof \b |\b and \b |\b and_eq \b |\b auto \b |\b bitand \b |\b bitor \b |\b bool \b |\b break \b |\b case \b |\b char \b |\b compl \b |\b const \b |\b constexpr \b |\b continue \b |\b default \b |\b do \b |\b double \b |\b else \b |\b enum \b |\b extern \b |\b false \b |\b float \b |\b for \b |\b goto \b |\b if \b |\b inline \b |\b int \b |\b long \b |\b noreturn \b |\b not \b |\b not_eq \b |\b nullptr \b |\b or \b |\b or_eq \b |\b register \b |\b restrict \b |\b return \b |\b short \b |\b signed \b |\b sizeof \b |\b static \b |\b static_assert \b |\b struct \b |\b switch \b |\b thread_local \b |\b true \b |\b typedef \b |\b typeof \b |\b typeof_unequal \b |\b union \b |\b unsigned \b |\b void \b |\b volatile \b |\b while \b |\b xor \b |\b xor_eq \b)/x/gsx; # Braces and semicolons followed by whitespace has zero cost. $text =~ s/[{;}]\s//gs; # Remove whitespaces. $text =~ s/\s//gs; # Output final size. my $size = length($text); print $size; if( $size > SIZE_LIMIT ) { print " -> OVER LIMIT (", SIZE_LIMIT, ")"; } print "\n";