File: convert_comment.py

package info (click to toggle)
plplot 5.10.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 26,280 kB
  • ctags: 13,512
  • sloc: ansic: 83,001; xml: 27,081; ada: 18,878; cpp: 15,966; tcl: 11,651; python: 7,075; f90: 7,058; ml: 6,974; java: 6,665; perl: 5,029; sh: 2,210; makefile: 199; lisp: 75; sed: 25; fortran: 7
file content (206 lines) | stat: -rwxr-xr-x 8,814 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#!/usr/bin/env python

# Programme to convert all single-line or multi-line "/* ... */"
# comments to "//" form in C or C++ code.  Input source code file is
# stdin, output file is stdout.
import sys
import re
# Restore default signal handling for SIGPIPE as suggested by
# http://www.velocityreviews.com/forums/t332662-ioerror-errno-32-broken-pipe.html
# so that stdout can be sent (unix-only) to a pipelined process that terminates
# early such as cmp.
import signal
signal.signal(signal.SIGPIPE, signal.SIG_DFL)

ifsingleline = True
previous_continue = False

for line in sys.stdin.readlines():
    start_comment = line.find("/*")
    # FIXME?: the simple rules below to ignore all special strings
    # in a line where the first instance is quoted obviously
    # need generalization.  However, second instances
    # of special strings are unlikely in practice so we will go with
    # this simple rule until it is proved something more is required.
    # Ignore all "/*" instances on a line where the first one is
    # quoted.
    if start_comment >=0 and re.search(r'^[^"]*("[^"]*"[^"]*)*"[^"]*/\*[^"]*"', line):
        start_comment = -1

    start_special = line.find("//*")
    # FIXME?
    # Ignore all "//*" instances on a line where the first one is
    # quoted.
    if start_special >= 0 and re.search(r'^[^"]*("[^"]*"[^"]*)*"[^"]*//\*[^"]*"', line):
        start_special = -1

    # if start_special corresponds to start_comment, then ignore start_comment
    # to deal with issue of recursive changes to an original line of the
    # form "/******..."
    if start_special >= 0 and start_special == start_comment -1:
        start_comment = -1

    end_comment = line.find("*/")
    # FIXME?
    # Ignore all "*/" instances on a line where the first one is
    # quoted.
    if end_comment >= 0 and re.search(r'^[^"]*("[^"]*"[^"]*)*"[^"]*\*/[^"]*"', line):
        end_comment = -1

    start_special = line.find("//")
    # FIXME?
    # Ignore all "//" instances on a line where the first one is
    # quoted.
    if start_special >= 0 and re.search(r'^[^"]*("[^"]*"[^"]*)*"[^"]*//[^"]*"', line):
        start_special = -1
    # If unquoted // before /* and not in the middle of a comment block,
    # then ignore both /* and */ beyond //.
    if ifsingleline and start_special >= 0 and start_special <= start_comment -1:
        start_comment = -1
        end_comment = -1

    # Note trailing "\n" has not (yet) been removed from line so
    # that the next to last character is at position len(line) - 3.
    if end_comment >=0 and end_comment !=  len(line) - 3:
        if ifsingleline and start_comment >=0:
            # Skip most further processing for a line with embedded
            # comments outside of multiline blocks of comments.
            start_comment = -1
            end_comment = -1
        else:
            sys.stderr.write(line)
            raise RuntimeError, "Cannot interpret trailing character(s) after */ for this line"

    # Note trailing "\n" has not (yet) been removed from line so
    # that the next to last character is at position len(line) - 3.
    # print "start_comment = ", start_comment
    # print "end_comment = ", end_comment
    # print "start_special = ", start_special
    if ifsingleline:
        if start_comment >=0 and start_comment < end_comment and end_comment == len(line) - 3:
            # Single-line comment case.
            # Strip trailing "\n" (Unix line endings, only) since that might
            # cause trouble with stripping trailing white space below.
            # This trailing "\n" will be added back at the end of this block.
            line = re.sub(r'^(.*)\n$', "\\1", line)
            # Convert single-line comment.
            # \1 corresponds to zero or more leading characters before "/*".
            # \3 corresponds to zero or more characters between "/*" and
            # "*/".
            # N.B. preserves indentation.
            line = re.sub(r'^(.*)(/\*)(.*)\*/$', "\\1//\\3", line)
            # strip trailing white space (if any).
            line = line.rstrip()
            # Add back (Unix-only) line ending.
            line = line + "\n"

        elif end_comment >=0:
            sys.stderr.write(line)
            raise RuntimeError, "Trailing */ for a line which is not a comment"

        elif start_comment >=0:
            # Convert first line of multiline comment.
            # N.B. preserves indentation.
            line = line.replace("/*", "//", 1)
            ifsingleline = False


    else:
        # Case where dealing with multi-line comment.
        if start_comment >=0:
            sys.stderr.write(line)
            raise RuntimeError, "/* in the middle of a comment block"

        # strip trailing "\n" (Unix line endings, only) since that might
        # cause trouble with stripping trailing white space below.
        # This trailing "\n" will be added back at the end of this block.
        line = re.sub(r'^(.*)\n$', "\\1", line)
        if end_comment < 0:
            # Convert multiline comment line that is not start line
            # or end line of that comment.  
            # Replace " *" after zero or more blanks (the standard form
            # produced by uncrustify) if it is there by "//".
            # N.B. preserves indentation.
            if re.search(r'^( *) \*', line):
                line = re.sub(r'^( *) \*', "\\1//", line)
            else:
                # If standard indented form not found....
                line = "//" + line


        else:
            # Convert last line of multiline comment.
            # Try converting vacuous form (initial blanks + " */")
            # to initial blanks (if any) + "//".
            # This consumes the blank in " */" that is customary as
            # the last line of a multi-line block.
            # N.B. preserves indentation.
            # \1 contains the initial blanks
            if re.search(r'^( *) \*/$', line):
                line = re.sub(r'^( *) \*/$', "\\1//", line)

            # Try converting non-vacuous standard form produced by
            # uncrustify (initial blanks + " *" + any string + "*/")
            # to initial blanks + "//" + any string.
            # N.B. preserves indentation.
            # \1 contains the initial blanks
            # \2 contains the "any" string preceding "*/".
            elif re.search(r'^( *) \*(.*)\*/$', line):
                line = re.sub(r'^( *) \*(.*)\*/$', "\\1//\\2", line)

            # If all previous conversion attempts failed....
            # N.B. Does not preserve indentation.
            else:
                line = re.sub(r'^(.*)\*/$', "//\\1", line)

            # strip trailing white space (if any).
            line = line.rstrip()
            ifsingleline = True

        # Add back (Unix-only) line ending.
        line = line + "\n"

    # If previous comment continuation exists, check whether it is 
    # valid, i.e., whether it is followed by another line consisting
    # zero or more blanks followed by a comment.
    if previous_continue:
        if re.search(r'^ *//', line):
            previous_continue = False
        else:
            sys.stderr.write(line_old)
            sys.stderr.write(line)
            raise RuntimeError, "Comment continuation not allowed unless next line is a comment"
    # End with some special processing for all lines which previously
    # or now include "//".
    start_special = line.find("//")
    if start_special >= 0:
        # Special transforms to get rid of left-over "\*" and "*\"
        # forms which have historically been used to frame
        # multi-block comments by some PLplot developers.
        # Replace leading "// \*" ==> "//"
        line = re.sub(r'^// \\\*(.*)$', "//\\1", line)
        # Remove "*\" from end of comment lines
        line = re.sub(r'^//(.*)\*\\$', "//\\1", line)
        # Convert long "horizontal line" comment forms to standard form.
        line = re.sub(r'^// *[-*=/+_\\# ]{50,200}$', "//--------------------------------------------------------------------------", line)
        # Look for trailing continuation after comment lines and
        # complain if you find any.
        start_special = line.rfind("\\")
        # Note line has trailing "\n" so that the last character
        # is at position len(line) - 2.
        if start_special >=0 and start_special == len(line) -2:
            # Strings are immutable so this is a copy not a reference.
            line_old = line
            previous_continue = True

    sys.stdout.write(line)

if not ifsingleline:
    sys.stderr.write(line)
    raise RuntimeError, "Last line of file leaves unterminated comment block."

if previous_continue:
    sys.stderr.write(line_old)
    raise RuntimeError, "Last line of file is a continued comment."

sys.exit()