dep-curl/.github/scripts/c-comments
2026-08-07 11:25:15 +02:00

191 lines
4.6 KiB
Perl
Executable file

#!/usr/bin/env perl
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
# Output all the C comments and double-quoted strings in the given source
# files. All other contents should be blanked out. Output the text at the same
# horizontal position as in the original file.
#
# Ignores strings for the preprocessor.
#
## States
#
# 0 - default, initial state
# 1 - there was a slash
# 2 - quoted string
# 3 - // comment
# 4 - /* comment
# 5 - asterisk found within a /* comment
# 6 - #include line
# 7 - backslash in a string
# 8 - backslash in plain code
# 9 - single quote in plain code
#
## Flags
#
# 1 - include preprocessor line, ignore strings
sub scanline {
my ($col, $state, $flags, $l) = @_;
my $line;
if($state == 3) {
# // ended on the prev line, go back to init
$state = 0;
}
if(($state == 0) && ($l =~ /^ *\# *include/)) {
# preprocessor include line
$flags |= 1;
}
else {
# not preprocessor
$flags &= ~1;
}
my @c = split(//, $l);
# state machine this line
for my $c (@c) {
if($state == 1) {
# we had a slash
if($c eq "/") {
# // confirmed, the rest of the line is a comment
$line .= "//";
$state = 3;
}
elsif($c eq "*") {
# /* confirmed
$state = 4;
$line .= "/*";
}
else {
# back to normal
$line .= " ";
$state = 0;
}
}
elsif($state == 2) {
# a string
if($c eq "\\") {
$line .= "\\";
$state = 7;
}
elsif($c eq "\"") {
# end of the string
$line .= "\"";
$state = 0;
}
else {
$line .= $c;
}
}
elsif($state == 3) {
# a // comment
$line .= $c;
}
elsif($state == 4) {
# an ongoing /* comment
if($c eq "*") {
# could a comment close
$state = 5;
}
else {
$line .= $c;
}
}
elsif($state == 5) {
if($c eq "/") {
# a /* */ comment ended here */
$line .= "*/";
$state = 0;
}
else {
# the /* comment continues
$line .= "*$c";
$state = 4;
}
}
elsif($state == 7) {
# the prev was a backslash in a string
$line .= $c;
# switch back to normal string
$state = 2;
}
elsif($state == 8) {
# the prev was a backslash in code
if($c eq "\n") {
$line .= $c;
}
else {
#$line .= " ";
}
# switch back to plain code
$state = 0;
}
elsif($state == 9) {
# the prev was a single quote in code
if($c eq "\n") {
$line .= $c;
# switch back to plain code
$state = 0;
}
elsif($c eq "\\") {
# a backslash followed the quote
$line .= " ";
$state = 8;
}
else {
# switch back to plain code
$state = 0;
}
}
else {
if($c eq "\\") {
# got a backslash
$line .= " ";
$state = 8
}
elsif($c eq "\'") {
# got a single quote
$line .= " ";
$state = 9
}
if($c eq "/") {
$state = 1; # got a slash
}
elsif(($c eq "\"") && !($flags & 1)) {
# start of a string, not within a preprocessor line
$line .= "\"";
$state = 2;
}
elsif($c eq "\n") {
$line .= "\n";
}
else {
$line .= " ";
}
}
}
# strip trailing space
$line =~ s/( +)\n/\n/;
return $state, $flags, $line;
}
sub strip {
my ($f) = @_;
my $state = 0;
my $flags = 0;
open(F, "<$f") || die "can't open $f";
while(<F>) {
my $l = $_;
($state, $flags, $line) = scanline(0, $state, $flags, $l);
print "$line";
}
close(F);
}
for my $f (@ARGV) {
strip($f);
}