our $Ident	= qr{
			[A-Za-z_][A-Za-z\d_]*
			(?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)*
		}x;
our $Member	= qr{->$Ident|\.$Ident|\[[^]]*\]};
our $Lval	= qr{$Ident(?:$Member)*};

our $Int_type	= qr{(?i)llu|ull|ll|lu|ul|l|u};
our $Binary	= qr{(?i)0b[01]+$Int_type?};
our $Hex	= qr{(?i)0x[0-9a-f]+$Int_type?};
our $Int	= qr{[0-9]+$Int_type?};
our $Octal	= qr{0[0-7]+$Int_type?};
our $String	= qr{"[^"]+"};
our $Float_hex	= qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?};
our $Float_dec	= qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?};
our $Float_int	= qr{(?i)[0-9]+e-?[0-9]+[fl]?};
our $Float	= qr{$Float_hex|$Float_dec|$Float_int};
our $Constant	= qr{$Float|$Binary|$Octal|$Hex|$Int};

our $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/;
our $LvalOrFunc	= qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*};
our $FuncArg = qr{($LvalOrFunc|$Constant|$String)};

local $/;
while (<>) {
    my $content = $_;

    ## counted length of string

    # strncmp(arg, string, counted length of string) == 0
    pos($content) = 0;
    while ($content =~ /\bstrncmp\s*\(\s*($LvalOrFunc)\s*,\s*($String)\s*,\s*($Int)\s*\)\s*==\s*0\b/g) {
	my $arg1 = $1;
	my $string = $5;
	my $len = $6;
	if (length($string) - 2 == $len) {
	    $content =~ s/\bstrncmp\s*\(\s*\Q$arg1\E,\s*\Q$string\E\s*,\s*$len\s*\)\s*==\s*0\b/str_has_prefix($arg1, $string)/;
	}
    }

    # strncmp(arg, string, counted length of string) != 0
    pos($content) = 0;
    while ($content =~ /\bstrncmp\s*\(\s*($LvalOrFunc)\s*,\s*($String)\s*,\s*($Int)\s*\)\s*!=\s*0\b/g) {
	my $arg1 = $1;
	my $string = $5;
	my $len = $6;
	if (length($string) - 2 == $len) {
	    $content =~ s/\bstrncmp\s*\(\s*\Q$arg1\E,\s*\Q$string\E\s*,\s*$len\s*\)\s*!=\s*0\b/!str_has_prefix($arg1, $string)/;
	}
    }

    # !strncmp(arg, string, counted length of string)
    pos($content) = 0;
    while ($content =~ /\!\s*strncmp\s*\(\s*($LvalOrFunc)\s*,\s*($String)\s*,\s*(\d+)\s*\)/g) {
	my $arg1 = $1;
	my $string = $5;
	my $len = $6;
	if (length($string) - 2 == $len) {
	    $content =~ s/\!\s*strncmp\s*\(\s*\Q$arg1\E\s*,\s*\Q$string\E\s*,\s*$len\s*\)/str_has_prefix($arg1, $string)/;
	}
    }

    # strncmp(arg, string, counted length of string)
    pos($content) = 0;
    while ($content =~ /\bstrncmp\s*\(\s*($LvalOrFunc)\s*,\s*($String)\s*,\s*(\d+)\s*\)/g) {
	my $arg1 = $1;
	my $string = $5;
	my $len = $6;
	if (length($string) - 2 == $len) {
	    $content =~ s/\bstrncmp\s*\(\s*\Q$arg1\E\s*,\s*\Q$string\E\s*,\s*$len\s*\)/!str_has_prefix($arg1, $string)/;
	}
    }

    ## Reversed string/arg counted length of string uses

    # strncmp(string, arg, counted length of string) == 0
    pos($content) = 0;
    while ($content =~ /\bstrncmp\s*\(\s*($String)\s*,\s*($LvalOrFunc)\s*,\s*($Int)\s*\)\s*==\s*0\b/g) {
	my $string = $1;
	my $arg1 = $2;
	my $len = $6;
	if (length($string) - 2 == $len) {
	    $content =~ s/\bstrncmp\s*\(\s*\Q$string\E\s*,\s*\Q$arg1\E\s*,\s*$len\s*\)\s*==\s*0\b/str_has_prefix($arg1, $string)/;
	}
    }

    # strncmp(string, arg, counted length of string) != 0
    pos($content) = 0;
    while ($content =~ /\bstrncmp\s*\(\s*($String)\s*,\s*($LvalOrFunc)\s*,\s*($Int)\s*\)\s*!=\s*0\b/g) {
	my $string = $1;
	my $arg1 = $2;
	my $len = $6;
	if (length($string) - 2 == $len) {
	    $content =~ s/\bstrncmp\s*\(\s*\Q$string\E\s*,\s*\Q$arg1\E,\s*$len\s*\)\s*!=\s*0\b/!str_has_prefix($arg1, $string)/;
	}
    }

    # !strncmp(string, arg, counted length of string)
    pos($content) = 0;
    while ($content =~ /\!\s*strncmp\s*\(\s*($String)\s*,\s*($LvalOrFunc)\s*,\s*(\d+)\s*\)/g) {
	my $string = $1;
	my $arg1 = $2;
	my $len = $6;
	if (length($string) - 2 == $len) {
	    $content =~ s/\!\s*strncmp\s*\(\s*\Q$string\E\s*,\s*\Q$arg1\E\s*,\s*$len\s*\)/str_has_prefix($arg1, $string)/;
	}
    }

    # strncmp(string, arg, counted length of string)
    pos($content) = 0;
    while ($content =~ /\bstrncmp\s*\(\s*($String)\s*,\s*($LvalOrFunc)\s*,\s*(\d+)\s*\)/g) {
	my $string = $1;
	my $arg1 = $2;
	my $len = $6;
	if (length($string) - 2 == $len) {
	    $content =~ s/\bstrncmp\s*\(\s*\Q$string\E\s*,\s*\Q$arg1\E\s*,\s*$len\s*\)/!str_has_prefix($arg1, $string)/;
	}
    }

    ## strlen uses

    # strncmp(arg, string, strlen(string)) == 0
    pos($content) = 0;
    while ($content =~ /\bstrncmp\s*\(\s*($LvalOrFunc)\s*,\s*($String)\s*,\s*strlen\s*\(\s*($String)\s*\)\s*==\s*0\b/g) {
	my $arg1 = $1;
	my $string = $5;
	my $sizeof_string = $6;
	if ($string == $sizeof_string) {
	    $content =~ s/\bstrncmp\s*\(\s*\Q$arg1\E\s*,\s*\Q$string\E\s*,\s*strlen\s*\(\s*\Q$sizeof_string\E\s*\)\s*==\s*0\b/str_has_prefix($arg1, $string)/;
	}
    }

    # !strncmp(arg, string, strlen(string))
    pos($content) = 0;
    while ($content =~ /\!\s*strncmp\s*\(\s*($LvalOrFunc)\s*,\s*($String)\s*,\s*strlen\s*\(\s*($String)\s*\)\s*\)/g) {
	my $arg1 = $1;
	my $string = $5;
	my $sizeof_string = $6;
	if ($string == $sizeof_string) {
	    $content =~ s/\!\s*strncmp\s*\(\s*\Q$arg1\E,\s*\Q$string\E\s*,\s*strlen\s*\(\s*\Q$sizeof_string\E\s*\)\s*\)/str_has_prefix($arg1, $string)/;
	}
    }


    ## reversed strlen uses

    # strncmp(string, arg, strlen(string)) == 0
    pos($content) = 0;
    while ($content =~ /\bstrncmp\s*\(\s*($String)\s*,\s*($LvalOrFunc)\s*,\s*strlen\s*\(\s*($String)\s*\)\s*==\s*0\b/g) {
	my $string = $1;
	my $arg1 = $2;
	my $sizeof_string = $6;
	if ($string == $sizeof_string) {
	    $content =~ s/\bstrncmp\s*\(\s*\Q$string\E\s*,\s*\Q$arg1\E\s*,\s*strlen\s*\(\s*\Q$sizeof_string\E\s*\)\s*==\s*0\b/str_has_prefix($arg1, $string)/;
	}
    }

    # !strncmp(string, arg, strlen(string))
    pos($content) = 0;
    while ($content =~ /\!\s*strncmp\s*\(\s*($String)\s*,\s*($LvalOrFunc)\s*,\s*strlen\s*\(\s*($String)\s*\)\s*\)/g) {
	my $string = $1;
	my $arg1 = $2;
	my $sizeof_string = $6;
	if ($string == $sizeof_string) {
	    $content =~ s/\!\s*strncmp\s*\(\s*\Q$string\E\s*,\s*\Q$arg1\E,\s*strlen\s*\(\s*\Q$sizeof_string\E\s*\)\s*\)/str_has_prefix($arg1, $string)/;
	}
    }


    ## 'sizeof(string) - 1' uses

    # strncmp(arg, string, sizeof(string) - 1) == 0
    pos($content) = 0;
    while ($content =~ /\bstrncmp\s*\(\s*($LvalOrFunc)\s*,\s*($String)\s*,\s*sizeof\s*\(\s*($String)\s*\)\s*\-\s*1\s*\)\s*==\s*0\b/g) {
	my $arg1 = $1;
	my $string = $5;
	my $sizeof_string = $6;
	if ($string == $sizeof_string) {
	    $content =~ s/\bstrncmp\s*\(\s*\Q$arg1\E\s*,\s*\Q$string\E\s*,\s*sizeof\s*\(\s*\Q$sizeof_string\E\s*\)\s*\-\s*1\s*\)\s*==\s*0\b/str_has_prefix($arg1, $string)/;
	}
    }

    # !strncmp(arg, string, sizeof(string) - 1)
    pos($content) = 0;
    while ($content =~ /\!\s*strncmp\s*\(\s*($LvalOrFunc)\s*,\s*($String)\s*,\s*sizeof\s*\(\s*($String)\s*\)\s*-\s*1\s*\)/g) {
	my $arg1 = $1;
	my $string = $5;
	my $sizeof_string = $6;
	if ($string == $sizeof_string) {
	    $content =~ s/\!\s*strncmp\s*\(\s*\Q$arg1\E,\s*\Q$string\E\s*,\s*sizeof\s*\(\s*\Q$sizeof_string\E\s*\)\s*\-\s*1\s*\)/str_has_prefix($arg1, $string)/;
	}
    }

    print $content;
}
