• R/O
  • SSH
  • HTTPS

iutest: Commit


Commit MetaInfo

Revision1201 (tree)
Time2016-10-12 10:35:42
Authorsrz_zumix

Log Message

update compile error checker

git@afc91852902ef57d16fbdc7a91760e45b849469c
https://github.com/srz-zumix/iutest/commit/afc91852902ef57d16fbdc7a91760e45b849469c


support --command option

git@c1aa8bce246ec76eda8f3ed8e811a446c9fb9882


update .gitignore

git@bac1b721c097170f95d067239af1b2e3b288b694


update compiler error checker

git@33ced2b97503156ecd307015de9d7006fe073fa0

Change Summary

Incremental Difference

--- trunk/test/.gitignore (revision 1200)
+++ trunk/test/.gitignore (revision 1201)
@@ -2,4 +2,4 @@
22 *.png
33 *.css
44 benchmark/benchmark_n*.cpp
5-
5+cpplint/cpplint.py
--- trunk/test/Makefile (revision 1200)
+++ trunk/test/Makefile (revision 1201)
@@ -79,5 +79,5 @@
7979
8080 $(COMPILEERROR_TARGETS) : $(SRCS) $(IUTEST_HEADERS) Makefile
8181 # -$(CXX) $(IUTEST_INCLUDE) $(CXXFLAGS) /Fe$@ $@.cpp $(LDFLAGS)
82- $(CXX) $(IUTEST_INCLUDE) $(CXXFLAGS) /Fe$@ $@.cpp $(LDFLAGS) | python ../tools/python/iutest_compile_error_test.py -c $(CXX)
82+ $(CXX) $(IUTEST_INCLUDE) $(CXXFLAGS) /Fe$@ $@.cpp $(LDFLAGS) | python ../tools/python/iutest_compile_error_test.py -c $(CXX) --verbose
8383
--- trunk/tools/python/iutest_compile_error_test.py (revision 1200)
+++ trunk/tools/python/iutest_compile_error_test.py (revision 1201)
@@ -1,415 +1,433 @@
1-#!/usr/bin/env python
2-# -*- coding: utf-8 -*-
3-#
4-# iutest_compiler_error_test.py
5-#
6-# Copyright (C) 2015-2016, Takazumi Shirayanagi
7-# This software is released under the new BSD License,
8-# see LICENSE
9-#
10-
11-import os
12-import sys
13-import argparse
14-import re
15-
16-from argparse import ArgumentParser
17-
18-
19-class ErrorMessage:
20- file = ""
21- line = 0
22- type = ""
23- message = ""
24- parent = None
25- child = None
26- checked = False
27-
28- def set_type(self, str):
29- s = str.strip()
30- if s in {"error", u"エラー"}:
31- self.type = "error"
32- elif s in {"note", u"備考"}:
33- self.type = "note"
34- elif s in {"warning", u"警告"}:
35- self.type = "warning"
36- if s in {"error", "エラー"}:
37- self.type = "error"
38- elif s in {"note", "備考"}:
39- self.type = "note"
40- elif s in {"warning", "警告"}:
41- self.type = "warning"
42- else:
43- self.type = s
44-
45- def is_error(self):
46- if self.type == "error":
47- return True
48- return False
49-
50- def is_note(self):
51- if self.type == "note":
52- return True
53- return False
54-
55- def is_type_none(self):
56- if not self.type:
57- return True
58- return False
59-
60- def is_warning(self):
61- if self.type == "warning":
62- return True
63- return False
64-
65- def has_error(self):
66- if self.type == "error":
67- return True
68- elif self.parent and self.parent.has_error_parent():
69- return True
70- elif self.child and self.child.has_error_child():
71- return True
72- return False
73-
74- def has_error_parent(self):
75- if self.type == "error":
76- return True
77- elif self.parent:
78- return self.parent.has_error_parent()
79- return False
80-
81- def has_error_child(self):
82- if self.type == "error":
83- return True
84- elif self.child:
85- return self.child.has_error_child()
86- return False
87-
88- def is_checked(self):
89- if self.checked:
90- return True
91- elif self.parent:
92- return self.parent.is_checked()
93- return False
94-
95- def is_tail(self):
96- if self.child:
97- return False
98- return True
99-
100- def get_error(self):
101- if self.type == "error":
102- return self
103- if self.parent:
104- e = self.parent.get_error_parent()
105- if e:
106- return e
107- if self.child:
108- e = self.child.get_error_child()
109- if e:
110- return e
111- return None
112-
113- def get_error_parent(self):
114- if self.type == "error":
115- return self
116- elif self.parent:
117- return self.parent.get_error_parent()
118- return None
119-
120- def get_error_child(self):
121- if self.type == "error":
122- return self
123- elif self.child:
124- return self.child.get_error_child()
125- return None
126-
127-format_gcc = True
128-color_prompt = False
129-
130-
131-# command line option
132-def parse_command_line():
133- parser = ArgumentParser()
134- parser.add_argument(
135- '-v',
136- '--version',
137- action='version',
138- version=u'%(prog)s version 0.3'
139- )
140- parser.add_argument(
141- '-c',
142- '--compiler',
143- help='set compiler.',
144- default='gcc'
145- )
146- parser.add_argument(
147- '--verbose',
148- action='store_true',
149- help='print input message.'
150- )
151- parser.add_argument(
152- '--debug',
153- action='store_true',
154- help='debug.'
155- )
156- if sys.version_info[0] >= 3:
157- parser.add_argument(
158- '-i',
159- '--infile',
160- type=argparse.FileType('r', encoding='UTF-8'),
161- help='compiler stdout.',
162- default=sys.stdin
163- )
164- else:
165- parser.add_argument(
166- '-i',
167- '--infile',
168- type=argparse.FileType('r'),
169- help='compiler stdout.',
170- default=sys.stdin
171- )
172-
173- options = parser.parse_args()
174- return options
175-
176-
177-def parse_gcc_clang(options, f, r_expansion, note_is_child):
178- re_fatal = re.compile(r'(\S+)\s*:\s*fatal\s*error\s*.*')
179- re_file = re.compile(r'(\S+):(\d+):(\d+)\s*:(.*)')
180- re_infile = re.compile(r'In file included from (\S+):(\d+):(\d+)(.*)')
181- re_message = re.compile(r'.*:\d+:\d+: (\S*): (.*)')
182- re_expansion = re.compile(r_expansion)
183- re_declaration = re.compile(r'.*declaration of\s*(.*)')
184- msg_list = []
185- msg = None
186- prev = None
187- for line in f:
188- if options.verbose:
189- print(line)
190- if re_fatal.match(line):
191- raise Exception(line)
192-
193- m = re_file.match(line)
194- if not m:
195- m = re_infile.match(line)
196-
197- if m:
198- if msg:
199- msg_list.append(msg)
200- prev = msg
201- msg = ErrorMessage()
202- msg.file = m.group(1)
203- msg.line = int(m.group(2))
204- msg.type = ""
205- n = re_message.match(line)
206- if n:
207- msg.set_type(n.group(1))
208- msg.message += n.group(2)
209- else:
210- msg.set_type('')
211- msg.message += m.group(4)
212-
213- is_child = note_is_child and msg.is_note()
214- is_type_none = prev and prev.is_type_none()
215- is_declaration = False
216- n = re_declaration.match(line)
217- if n and prev and prev.message.find(n.group(1)) != -1:
218- is_declaration = True
219-
220- if prev:
221- if is_child or is_type_none or is_declaration or re_expansion.search(msg.message):
222- prev.child = msg
223- msg.parent = prev
224- else:
225- if msg:
226- msg.message += '\n'
227- msg.message += line
228- msg_list.append(msg)
229- return msg_list
230-
231-
232-def parse_gcc(options, f):
233- return parse_gcc_clang(options, f, r'in expansion of macro', False)
234-
235-
236-def parse_clang(options, f):
237- return parse_gcc_clang(options, f, r'expanded from ', True)
238-
239-
240-def parse_vc(options, f):
241- re_fatal = re.compile(r'(\S+)\s*:\s*fatal\s*error\s*.*')
242- re_file = re.compile(r'(\s*)(\S+)\((\d+)\)\s*:\s*(.*)')
243- re_message = re.compile(r'.*\(\d+\)\s*: (\S*) (\S*: .*)')
244- msg_list = []
245- msg = None
246- prev = None
247- for line in f:
248- if options.verbose:
249- print(line)
250- if re_fatal.match(line):
251- raise Exception(line)
252-
253- m = re_file.match(line)
254- if m:
255- if msg:
256- msg_list.append(msg)
257- prev = msg
258- msg = ErrorMessage()
259- msg.file = m.group(2)
260- msg.line = int(m.group(3))
261- msg.type = ""
262- n = re_message.match(line)
263- if n:
264- msg.set_type(n.group(1))
265- msg.message += n.group(2)
266- else:
267- msg.set_type('')
268- msg.message += m.group(4)
269-
270- if m.group(1) and prev:
271- prev.child = msg
272- msg.parent = prev
273- else:
274- if msg:
275- msg.message += '\n'
276- msg.message += line
277- msg_list.append(msg)
278- return msg_list
279-
280-
281-def dump_msg(m):
282- if format_gcc:
283- if m.is_type_none():
284- print("%s:%d: %s" % (m.file, m.line, m.message))
285- else:
286- print("%s:%d: %s: %s" % (m.file, m.line, m.type, m.message))
287- else:
288- if m.parent:
289- print("\t%s(%d): %s %s" % (m.file, m.line, m.type, m.message))
290- else:
291- print("%s(%d): %s %s" % (m.file, m.line, m.type, m.message))
292-
293-
294-def dump_msgs(m):
295- if m.parent:
296- dump_msgs(m.parent)
297- dump_msg(m)
298-
299-
300-def dump_list(l):
301- for m in l:
302- if not m.parent:
303- print('------------------------------')
304- dump_msg(m)
305- if not m.child:
306- print('------------------------------')
307-
308- return True
309-
310-
311-def test_result(result, msg, e):
312- OKGREEN = '\033[32m'
313-# WARNING = '\033[33m'
314- FAIL = '\033[31m'
315- ENDC = '\033[0m'
316-
317- if e:
318- msg += ': ' + e.file + ': ' + str(e.line)
319-
320- if result:
321- if color_prompt:
322- print(OKGREEN + '[OK] ' + ENDC + msg)
323- else:
324- print('[OK] ' + msg)
325- else:
326- if color_prompt:
327- print(FAIL + '[NG] ' + ENDC + msg)
328- else:
329- print('[NG] ' + msg)
330-
331-
332-def iutest(l):
333- result = True
334- re_iutest = re.compile(r'IUTEST_TEST_COMPILEERROR\( (.*) \)')
335- re_m = None
336- check = None
337- for msg in l:
338- if not msg:
339- continue
340-
341- mm = re_iutest.search(msg.message)
342- if mm:
343- if msg.parent:
344- continue
345- if check and not check.checked:
346- dump_msg(check)
347- dump_msg(msg)
348- test_result(False, re_m.group(0), check)
349- check = None
350- result = False
351- else:
352- check = msg
353- re_m = mm
354- elif msg.has_error():
355- #print('%s - %d' % (msg.file, msg.line))
356- if check and msg.file in check.file and msg.line == check.line + 1:
357- actual = msg.get_error()
358- expect = re_m.group(1).strip('"')
359- #print(actual.message)
360- if not expect or actual.message.find(expect) != -1:
361- check.checked = True
362- msg.checked = True
363- test_result(True, re_m.group(0), check)
364- elif msg.is_tail() and not msg.is_checked():
365- dump_msgs(msg)
366- result = False
367- elif msg.is_warning():
368- dump_msg(msg)
369-
370- if check and not check.checked:
371- test_result(False, re_m.group(0), check)
372- result = False
373- return result
374-
375-
376-def parse_output(options):
377- global format_gcc
378- l = None
379- if not options.infile:
380- raise Exception("infile null")
381- #print(options.infile.encoding)
382- f = options.infile
383- #f = codecs.getreader('utf-8')(options.infile)
384-
385- if any(options.compiler.find(s) != -1 for s in ('clang', 'clang++')):
386- l = parse_clang(options, f)
387- elif any(options.compiler.find(s) != -1 for s in ('gcc', 'g++')):
388- l = parse_gcc(options, f)
389- elif options.compiler == 'cl':
390- format_gcc = False
391- l = parse_vc(options, f)
392- else:
393- raise Exception("sorry, %s compiler is not supported", (options.compiler))
394-
395- if options.debug:
396- dump_list(l)
397- return iutest(l)
398-
399-
400-def setup():
401- global color_prompt
402- term = os.environ.get('TERM')
403- if term:
404- if any(term.find(s) for s in ('xterm', 'screen', 'rxvt', 'linux', 'cygwin')):
405- color_prompt = True
406-
407-
408-def main():
409- options = parse_command_line()
410- setup()
411- if not parse_output(options):
412- sys.exit(1)
413-
414-if __name__ == '__main__':
415- main()
1+#!/usr/bin/env python
2+# -*- coding: utf-8 -*-
3+#
4+# iutest_compiler_error_test.py
5+#
6+# Copyright (C) 2015-2016, Takazumi Shirayanagi
7+# This software is released under the new BSD License,
8+# see LICENSE
9+#
10+
11+import os
12+import sys
13+import argparse
14+import re
15+
16+from argparse import ArgumentParser
17+from subprocess import Popen, PIPE, STDOUT
18+
19+
20+class ErrorMessage:
21+ file = ""
22+ line = 0
23+ type = ""
24+ message = ""
25+ parent = None
26+ child = None
27+ checked = False
28+
29+ def set_type(self, str):
30+ s = str.strip()
31+ if s in {"error", u"エラー"}:
32+ self.type = "error"
33+ elif s in {"note", u"備考"}:
34+ self.type = "note"
35+ elif s in {"warning", u"警告"}:
36+ self.type = "warning"
37+ if s in {"error", "エラー"}:
38+ self.type = "error"
39+ elif s in {"note", "備考"}:
40+ self.type = "note"
41+ elif s in {"warning", "警告"}:
42+ self.type = "warning"
43+ else:
44+ self.type = s
45+
46+ def is_error(self):
47+ if self.type == "error":
48+ return True
49+ return False
50+
51+ def is_note(self):
52+ if self.type == "note":
53+ return True
54+ return False
55+
56+ def is_iutest(self):
57+ if self.is_note() and self.message.find("IUTEST_TEST_COMPILEERROR") != -1:
58+ return True
59+ return False
60+
61+ def is_type_none(self):
62+ if not self.type:
63+ return True
64+ return False
65+
66+ def is_warning(self):
67+ if self.type == "warning":
68+ return True
69+ return False
70+
71+ def has_error(self):
72+ if self.type == "error":
73+ return True
74+ elif self.parent and self.parent.has_error_parent():
75+ return True
76+ elif self.child and self.child.has_error_child():
77+ return True
78+ return False
79+
80+ def has_error_parent(self):
81+ if self.type == "error":
82+ return True
83+ elif self.parent:
84+ return self.parent.has_error_parent()
85+ return False
86+
87+ def has_error_child(self):
88+ if self.type == "error":
89+ return True
90+ elif self.child:
91+ return self.child.has_error_child()
92+ return False
93+
94+ def is_checked(self):
95+ if self.checked:
96+ return True
97+ elif self.parent:
98+ return self.parent.is_checked()
99+ return False
100+
101+ def is_tail(self):
102+ if self.child:
103+ return False
104+ return True
105+
106+ def get_error(self):
107+ if self.type == "error":
108+ return self
109+ if self.parent:
110+ e = self.parent.get_error_parent()
111+ if e:
112+ return e
113+ if self.child:
114+ e = self.child.get_error_child()
115+ if e:
116+ return e
117+ return None
118+
119+ def get_error_parent(self):
120+ if self.type == "error":
121+ return self
122+ elif self.parent:
123+ return self.parent.get_error_parent()
124+ return None
125+
126+ def get_error_child(self):
127+ if self.type == "error":
128+ return self
129+ elif self.child:
130+ return self.child.get_error_child()
131+ return None
132+
133+format_gcc = True
134+color_prompt = False
135+
136+
137+# command line option
138+def parse_command_line():
139+ parser = ArgumentParser()
140+ parser.add_argument(
141+ '-v',
142+ '--version',
143+ action='version',
144+ version=u'%(prog)s version 0.3'
145+ )
146+ parser.add_argument(
147+ '-c',
148+ '--compiler',
149+ help='set compiler.',
150+ default='gcc'
151+ )
152+ parser.add_argument(
153+ '--verbose',
154+ action='store_true',
155+ help='print input message.'
156+ )
157+ parser.add_argument(
158+ '--debug',
159+ action='store_true',
160+ help='debug.'
161+ )
162+ parser.add_argument(
163+ '--command',
164+ help='execute command.',
165+ default=None
166+ )
167+ if sys.version_info[0] >= 3:
168+ parser.add_argument(
169+ '-i',
170+ '--infile',
171+ type=argparse.FileType('r', encoding='UTF-8'),
172+ help='compiler stdout.',
173+ default=sys.stdin
174+ )
175+ else:
176+ parser.add_argument(
177+ '-i',
178+ '--infile',
179+ type=argparse.FileType('r'),
180+ help='compiler stdout.',
181+ default=sys.stdin
182+ )
183+
184+ options = parser.parse_args()
185+ return options
186+
187+
188+def parse_gcc_clang(options, f, r_expansion, note_is_child):
189+ re_fatal = re.compile(r'(\S+)\s*:\s*fatal\s*error\s*.*')
190+ re_file = re.compile(r'(\S+):(\d+):(\d+)\s*:(.*)')
191+ re_infile = re.compile(r'In file included from (\S+):(\d+):(\d+)(.*)')
192+ re_message = re.compile(r'.*:\d+:\d+: (\S*): (.*)')
193+ re_expansion = re.compile(r_expansion)
194+ re_declaration = re.compile(r'.*declaration of\s*(.*)')
195+ msg_list = []
196+ msg = None
197+ prev = None
198+ for line in f:
199+ if options.verbose:
200+ print(line)
201+ if re_fatal.match(line):
202+ raise Exception(line)
203+
204+ m = re_file.match(line)
205+ if not m:
206+ m = re_infile.match(line)
207+
208+ if m:
209+ if msg:
210+ msg_list.append(msg)
211+ prev = msg
212+ msg = ErrorMessage()
213+ msg.file = m.group(1)
214+ msg.line = int(m.group(2))
215+ msg.type = ""
216+ n = re_message.match(line)
217+ if n:
218+ msg.set_type(n.group(1))
219+ msg.message += n.group(2)
220+ else:
221+ msg.set_type('')
222+ msg.message += m.group(4)
223+
224+ is_child = note_is_child and msg.is_note()
225+ is_type_none = prev and prev.is_type_none()
226+ is_declaration = False
227+ n = re_declaration.match(line)
228+ if n and prev and prev.message.find(n.group(1)) != -1:
229+ is_declaration = True
230+
231+ if prev:
232+ if is_child or is_type_none or is_declaration or re_expansion.search(msg.message):
233+ prev.child = msg
234+ msg.parent = prev
235+ else:
236+ if msg:
237+ msg.message += '\n'
238+ msg.message += line
239+ msg_list.append(msg)
240+ return msg_list
241+
242+
243+def parse_gcc(options, f):
244+ return parse_gcc_clang(options, f, r'in expansion of macro', False)
245+
246+
247+def parse_clang(options, f):
248+ return parse_gcc_clang(options, f, r'expanded from ', True)
249+
250+
251+def parse_vc(options, f):
252+ re_fatal = re.compile(r'(\S+)\s*:\s*fatal\s*error\s*.*')
253+ re_file = re.compile(r'(\s*)(\S+)\((\d+)\)\s*:\s*(.*)')
254+ re_message = re.compile(r'.*\(\d+\)\s*: (\S*)\s*(\S*: .*)')
255+ msg_list = []
256+ msg = None
257+ prev = None
258+ for line in f:
259+ if options.verbose:
260+ print(line)
261+ if re_fatal.match(line):
262+ raise Exception(line)
263+
264+ m = re_file.match(line)
265+ if m:
266+ if msg:
267+ msg_list.append(msg)
268+ prev = msg
269+ msg = ErrorMessage()
270+ msg.file = m.group(2)
271+ msg.line = int(m.group(3))
272+ msg.type = ""
273+ n = re_message.match(line)
274+ if n:
275+ msg.set_type(n.group(1))
276+ msg.message += n.group(2)
277+ else:
278+ msg.set_type('')
279+ msg.message += m.group(4)
280+
281+ child_note = m.group(1) or (msg.is_note() and not msg.is_iutest())
282+ if (m.group(1) or child_note) and prev:
283+ prev.child = msg
284+ msg.parent = prev
285+ else:
286+ if msg:
287+ msg.message += '\n'
288+ msg.message += line
289+ msg_list.append(msg)
290+ return msg_list
291+
292+
293+def dump_msg(m):
294+ if format_gcc:
295+ if m.is_type_none():
296+ print("%s:%d: %s" % (m.file, m.line, m.message))
297+ else:
298+ print("%s:%d: %s: %s" % (m.file, m.line, m.type, m.message))
299+ else:
300+ if m.parent:
301+ print("\t%s(%d): %s %s" % (m.file, m.line, m.type, m.message))
302+ else:
303+ print("%s(%d): %s %s" % (m.file, m.line, m.type, m.message))
304+
305+
306+def dump_msgs(m):
307+ if m.parent:
308+ dump_msgs(m.parent)
309+ dump_msg(m)
310+
311+
312+def dump_list(l):
313+ for m in l:
314+ if not m.parent:
315+ print('------------------------------')
316+ dump_msg(m)
317+ if not m.child:
318+ print('------------------------------')
319+
320+ return True
321+
322+
323+def test_result(result, msg, e):
324+ OKGREEN = '\033[32m'
325+# WARNING = '\033[33m'
326+ FAIL = '\033[31m'
327+ ENDC = '\033[0m'
328+
329+ if e:
330+ msg += ': ' + e.file + ': ' + str(e.line)
331+
332+ if result:
333+ if color_prompt:
334+ print(OKGREEN + '[OK] ' + ENDC + msg)
335+ else:
336+ print('[OK] ' + msg)
337+ else:
338+ if color_prompt:
339+ print(FAIL + '[NG] ' + ENDC + msg)
340+ else:
341+ print('[NG] ' + msg)
342+
343+
344+def iutest(l):
345+ result = True
346+ re_iutest = re.compile(r'IUTEST_TEST_COMPILEERROR\( (.*) \)')
347+ re_m = None
348+ check = None
349+ for msg in l:
350+ if not msg:
351+ continue
352+
353+ mm = re_iutest.search(msg.message)
354+ if mm:
355+ if msg.parent:
356+ continue
357+ if check and not check.checked:
358+ dump_msg(check)
359+ dump_msg(msg)
360+ test_result(False, re_m.group(0), check)
361+ result = False
362+ check = msg
363+ re_m = mm
364+ elif msg.has_error():
365+ #print('%s - %d' % (msg.file, msg.line))
366+ if check and msg.file in check.file and msg.line == check.line + 1:
367+ actual = msg.get_error()
368+ expect = re_m.group(1).strip('"')
369+ #print(actual.message)
370+ if not expect or actual.message.find(expect) != -1:
371+ check.checked = True
372+ msg.checked = True
373+ test_result(True, re_m.group(0), check)
374+ elif msg.is_tail() and not msg.is_checked():
375+ dump_msgs(msg)
376+ result = False
377+ elif msg.is_warning():
378+ dump_msg(msg)
379+
380+ if check and not check.checked:
381+ test_result(False, re_m.group(0), check)
382+ result = False
383+ return result
384+
385+
386+def parse_output(options):
387+ global format_gcc
388+ l = None
389+ if options.command:
390+ args = re.split('\s+', options.command)
391+ for i in range(len(args)):
392+ args[i] = os.path.expandvars(args[i])
393+ p = Popen(args, stdout=PIPE, stderr=STDOUT)
394+ p.wait()
395+ out, err = p.communicate()
396+ f = out.splitlines()
397+ else:
398+ if not options.infile:
399+ raise Exception("infile null")
400+ #print(options.infile.encoding)
401+ f = options.infile
402+ #f = codecs.getreader('utf-8')(options.infile)
403+
404+ if any(options.compiler.find(s) != -1 for s in ('clang', 'clang++')):
405+ l = parse_clang(options, f)
406+ elif any(options.compiler.find(s) != -1 for s in ('gcc', 'g++')):
407+ l = parse_gcc(options, f)
408+ elif options.compiler == 'cl':
409+ format_gcc = False
410+ l = parse_vc(options, f)
411+ else:
412+ raise Exception("sorry, %s compiler is not supported", (options.compiler))
413+
414+ if options.debug:
415+ dump_list(l)
416+ return iutest(l)
417+
418+
419+def setup():
420+ global color_prompt
421+ term = os.environ.get('TERM')
422+ if term:
423+ if any(term.find(s) for s in ('xterm', 'screen', 'rxvt', 'linux', 'cygwin')):
424+ color_prompt = True
425+
426+def main():
427+ options = parse_command_line()
428+ setup()
429+ if not parse_output(options):
430+ sys.exit(1)
431+
432+if __name__ == '__main__':
433+ main()
Show on old repository browser