Skip to content

Commit 7eb55b2

Browse files
authored
Merge pull request #12 from djeada/strip_cpp_comments
add strip_cpp_comments.sh
2 parents cfa7902 + 3d34b48 commit 7eb55b2

File tree

1 file changed

+159
-0
lines changed

1 file changed

+159
-0
lines changed

src/strip_cpp_comments.sh

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
#!/usr/bin/env bash
2+
#
3+
# strip_comments.sh — Remove C / C++ comments from files *in place* (pure Bash)
4+
#
5+
# Usage:
6+
# strip_comments.sh [-r REGEX] [file1 file2 …]
7+
#
8+
# -r | --regex REGEX Extended-regexp that candidate filenames must match.
9+
# If you omit every file argument, the script looks in
10+
# the current directory and processes *all* regular files
11+
# that match REGEX.
12+
#
13+
# Default REGEX : \.([ch](pp|xx|c)?|cc|hh|hpp)$ # .c .h .cpp .cc .cxx .hpp …
14+
#
15+
# Exit codes:
16+
# 0 OK
17+
# 1 bad usage / no files found
18+
# 2 cannot read / write file
19+
#
20+
21+
set -euo pipefail
22+
IFS=$'\n\t'
23+
24+
##############################################################################
25+
# CONFIG
26+
##############################################################################
27+
DEFAULT_RE='\.([ch](pp|xx|c)?|cc|hh|hpp)$' # .c .h .cpp .cc .cxx .hpp …
28+
29+
##############################################################################
30+
# FUNCTION: strip_file (unchanged)
31+
##############################################################################
32+
strip_file() {
33+
local file=$1
34+
local tmp
35+
tmp=$(mktemp "${TMPDIR:-/tmp}/scrub.XXXXXX") || {
36+
echo "Error: cannot create temp file" >&2; return 2; }
37+
38+
# State variables
39+
local in_block=0 in_line=0 in_str=0 in_char=0 escape=0
40+
local prev='' c=''
41+
42+
# FD 3 → tmp
43+
exec 3> "$tmp"
44+
45+
while IFS= read -r -N1 c || [[ -n $c ]]; do
46+
# ---------- end of line comment ----------
47+
if (( in_line )); then
48+
if [[ $c == $'\n' ]]; then
49+
in_line=0
50+
printf '\n' >&3
51+
fi
52+
continue
53+
fi
54+
55+
# ---------- end of block comment ----------
56+
if (( in_block )); then
57+
if [[ $prev == '*' && $c == '/' ]]; then
58+
in_block=0
59+
prev=''
60+
else
61+
prev=$c
62+
fi
63+
continue
64+
fi
65+
66+
# ---------- inside string ----------
67+
if (( in_str )); then
68+
printf '%s' "$c" >&3
69+
if (( escape )); then
70+
escape=0
71+
elif [[ $c == "\\" ]]; then
72+
escape=1
73+
elif [[ $c == '"' ]]; then
74+
in_str=0
75+
fi
76+
continue
77+
fi
78+
79+
# ---------- inside character ----------
80+
if (( in_char )); then
81+
printf '%s' "$c" >&3
82+
if (( escape )); then
83+
escape=0
84+
elif [[ $c == "\\" ]]; then
85+
escape=1
86+
elif [[ $c == "'" ]]; then
87+
in_char=0
88+
fi
89+
continue
90+
fi
91+
92+
# ---------- neutral ----------
93+
if [[ -z $prev ]]; then
94+
case $c in
95+
/) prev='/' ;; # might start comment
96+
'"') in_str=1 ; printf '%s' "$c" >&3 ;;
97+
"'") in_char=1; printf '%s' "$c" >&3 ;;
98+
*) printf '%s' "$c" >&3 ;;
99+
esac
100+
else
101+
case $c in
102+
/) in_line=1 ; prev='' ;; # "//"
103+
\*) in_block=1; prev='' ;; # "/*"
104+
*) printf '/%s' "$c" >&3; prev='' ;;
105+
esac
106+
fi
107+
done < "$file"
108+
109+
[[ -n $prev ]] && printf '%s' "$prev" >&3 # lone '/'
110+
111+
chmod --reference="$file" "$tmp"
112+
mv "$tmp" "$file"
113+
}
114+
115+
##############################################################################
116+
# FUNCTION: main (argument logic updated)
117+
##############################################################################
118+
main() {
119+
local regex=$DEFAULT_RE
120+
local positional=()
121+
122+
# ------ parse args ------
123+
while [[ $# -gt 0 ]]; do
124+
case $1 in
125+
-r|--regex)
126+
shift
127+
[[ $# -eq 0 ]] && { echo "Error: -r needs ARG" >&2; exit 1; }
128+
regex=$1
129+
;;
130+
-*)
131+
echo "Unknown option: $1" >&2; exit 1 ;;
132+
*)
133+
positional+=("$1")
134+
;;
135+
esac
136+
shift
137+
done
138+
139+
# ------ auto-discover files if none listed ------
140+
if (( ${#positional[@]} == 0 )); then
141+
for f in *; do
142+
[[ -f $f && $f =~ $regex ]] && positional+=("$f")
143+
done
144+
fi
145+
146+
(( ${#positional[@]} )) || { echo "Error: no files match '$regex'" >&2; exit 1; }
147+
148+
# ------ process ------
149+
for f in "${positional[@]}"; do
150+
[[ $f =~ $regex ]] || { echo "Skip: $f (no match)" >&2; continue; }
151+
[[ -r $f && -w $f ]] || { echo "Error: cannot read/write $f" >&2; exit 2; }
152+
echo "Stripping comments from $f ..."
153+
strip_file "$f" || exit $?
154+
done
155+
156+
echo "Done."
157+
}
158+
159+
main "$@"

0 commit comments

Comments
 (0)