Passed
Push — master ( 69834d...cf8455 )
by srz
06:40 queued 12s
created

iuwandbox.listup_options()   D

Complexity

Conditions 12

Size

Total Lines 26
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 24
nop 1
dl 0
loc 26
rs 4.8
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like iuwandbox.listup_options() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
#!/usr/bin/env python
2
#
3
# iuwandbox.py
4
#
5
# Copyright (C) 2014-2018, Takazumi Shirayanagi
6
# This software is released under the new BSD License,
7
# see LICENSE
8
#
9
10
import os
11
import sys
12
import re
13
import codecs
14
import argparse
15
16
from time import sleep
17
from argparse import ArgumentParser
18
from wandbox import Wandbox
19
from requests.exceptions import HTTPError
20
from requests.exceptions import ConnectionError
21
22
IUTEST_FUSED_SRC = os.path.normpath(os.path.join(os.path.dirname(__file__), '../../fused-src/iutest.min.hpp'))
23
IUTEST_WANDBOX_FUSED_SRC = os.path.normpath(os.path.join(os.path.dirname(__file__), '../../fused-src/iutest.wandbox.min.hpp'))
24
IUTEST_INCLUDE_PATH = os.path.normpath(os.path.join(os.path.dirname(__file__), '../../include'))
25
IUTEST_INCLUDE_REGEX = re.compile(r'^\s*#\s*include\s*".*(iutest|iutest_switch)\.hpp"')
26
EXPAND_INCLUDE_REGEX = re.compile(r'^\s*#\s*include\s*"(.*?)"')
27
IUTEST_INCG_REGEX = re.compile(r'\s*#\s*define[/\s]*(INCG_IRIS_\S*)\s*')
28
29
iutest_incg_list = []
30
workaround = True
31
api_retries = 3
32
api_retry_wait = 60
33
fused_src = IUTEST_FUSED_SRC
34
35
36
# command line option
37
def parse_command_line():
38
    global api_retries
39
    global api_retry_wait
40
    global fused_src
41
42
    parser = ArgumentParser()
43
    parser.add_argument(
44
        '-v',
45
        '--version',
46
        action='version',
47
        version=u'%(prog)s version 6.2'
48
    )
49
    parser.add_argument(
50
        '--list-compiler',
51
        '--list_compiler',
52
        action='store_true',
53
        help='listup compiler.'
54
    )
55
    parser.add_argument(
56
        '--list-options',
57
        '--list_options',
58
        metavar='COMPILER',
59
        help='listup compiler options.'
60
    )
61
    parser.add_argument(
62
        '-c',
63
        '--compiler',
64
        default='gcc-head',
65
        help='compiler select. default: %(default)s'
66
    )
67
    parser.add_argument(
68
        '-x',
69
        '--options',
70
        help='used options for a compiler.'
71
    )
72
    parser.add_argument(
73
        '--default',
74
        action='store_true',
75
        help='--default option is deprecated. default options are always set.'
76
    )
77
    parser.add_argument(
78
        '--no-default',
79
        action='store_true',
80
        help='no set default options.'
81
    )
82
    parser.add_argument(
83
        '--std',
84
        metavar='VERSION',
85
        help='set --std options.'
86
    )
87
    parser.add_argument(
88
        '--boost',
89
        metavar='VERSION',
90
        help='set boost options version X.XX or nothing.'
91
    )
92
    parser.add_argument(
93
        '--optimize',
94
        action='store_true',
95
        help='use optimization.'
96
    )
97
    parser.add_argument(
98
        '--cpp-verbose',
99
        action='store_true',
100
        help='use cpp-verbose.'
101
    )
102
    parser.add_argument(
103
        '--sprout',
104
        action='store_true',
105
        help='use sprout.'
106
    )
107
    parser.add_argument(
108
        '--msgpack',
109
        action='store_true',
110
        help='use msgpack.'
111
    )
112
    parser.add_argument(
113
        '--stdin',
114
        help='set stdin.'
115
    )
116
    parser.add_argument(
117
        '-f',
118
        '--compiler-option-raw',
119
        '--compiler_option_raw',
120
        metavar='OPTIONS',
121
        action='append',
122
        default=['-D__WANDBOX__'],
123
        help='compile-time any additional options.'
124
    )
125
    parser.add_argument(
126
        '-r',
127
        '--runtime-option-raw',
128
        '--runtime_option_raw',
129
        metavar='OPTIONS',
130
        action='append',
131
        help='runtime-time any additional options.'
132
    )
133
    parser.add_argument(
134
        '-s',
135
        '--save',
136
        action='store_true',
137
        help='generate permanent link.'
138
    )
139
    parser.add_argument(
140
        '--permlink',
141
        metavar='ID',
142
        help='get permanent link.'
143
    )
144
    parser.add_argument(
145
        '-o',
146
        '--output',
147
        metavar='FILE',
148
        help='output source code.'
149
    )
150
    parser.add_argument(
151
        '--xml',
152
        metavar='FILE',
153
        help='output result xml.'
154
    )
155
    parser.add_argument(
156
        '--junit',
157
        metavar='FILE',
158
        help='output result junit xml.'
159
    )
160
    parser.add_argument(
161
        '--stderr',
162
        action='store_true',
163
        help='output stderr.'
164
    )
165
    parser.add_argument(
166
        '--encoding',
167
        help='set encoding.'
168
    )
169
    parser.add_argument(
170
        '--expand-include',
171
        '--expand_include',
172
        action='store_true',
173
        help='expand include file.'
174
    )
175
    parser.add_argument(
176
        '--make',
177
        action='store_true',
178
        help=argparse.SUPPRESS
179
    )
180
    parser.add_argument(
181
        '--retry-wait',
182
        type=int,
183
        default=api_retry_wait,
184
        metavar='SECONDS',
185
        help='Wait time for retry when HTTPError occurs'
186
    )
187
    parser.add_argument(
188
        '--retry',
189
        type=int,
190
        default=api_retries,
191
        metavar='COUNT',
192
        help='Number of retries when HTTPError occurs'
193
    )
194
    parser.add_argument(
195
        '--check-config',
196
        '--check_config',
197
        action='store_true',
198
        help='check config.'
199
    )
200
    parser.add_argument(
201
        '--iutest-use-main',
202
        action='store_true',
203
        help='define IUTEST_USE_MAIN.'
204
    )
205
    parser.add_argument(
206
        '--iutest-use-wandbox-min',
207
        action='store_true',
208
        help='use iutest.wandbox.min.hpp (experimental).'
209
    )
210
    parser.add_argument(
211
        '--verbose',
212
        action='store_true',
213
        help='verbose.'
214
    )
215
    parser.add_argument(
216
        '--dryrun',
217
        action='store_true',
218
        help='dryrun.'
219
    )
220
    parser.add_argument(
221
        'code',
222
        metavar='CODE',
223
        nargs='*',
224
        help='source code file'
225
    )
226
    options = parser.parse_args()
227
    api_retries = options.retry
228
    api_retry_wait = options.retry_wait
229
    if options.iutest_use_wandbox_min:
230
        fused_src = IUTEST_WANDBOX_FUSED_SRC
231
    return options, parser
232
233
234
# file open
235
def file_open(path, mode, encoding):
236
    if encoding:
237
        file = codecs.open(path, mode, encoding)
238
    else:
239
        file = open(path, mode)
240
    return file
241
242
243
# make include filename
244
def make_include_filename(path, includes, included_files):
245
    if path in included_files:
246
        return included_files[path]
247
    include_dir, include_filename = os.path.split(path)
248
    while include_filename in includes:
249
        include_dir, dirname = os.path.split(include_dir)
250
        include_filename = dirname + '__' + include_filename
251
    included_files[path] = include_filename
252
    return include_filename
253
254
255
def is_iutest_included_file(filepath):
256
    if os.path.abspath(filepath).startswith(IUTEST_INCLUDE_PATH):
257
        incg = 'INCG_IRIS_' + os.path.basename(filepath).upper().replace('.', '_')
258
        for included_incg in iutest_incg_list:
259
            if included_incg.startswith(incg):
260
                return True
261
    return False
262
263
264
# make code
265
def make_code(path, encoding, expand, includes, included_files):
266
    code = ''
267
    file = file_open(path, 'r', encoding)
268
    for line in file:
269
        m = IUTEST_INCLUDE_REGEX.match(line)
270
        if m:
271
            code += '#include "iutest.hpp"\n'
272
            code += '//origin>> ' + line
273
            if 'iutest.hpp' not in includes:
274
                try:
275
                    f = codecs.open(fused_src, 'r', 'utf-8-sig')
276
                    iutest_src = f.read()
277
                    f.close()
278
                    includes['iutest.hpp'] = iutest_src
279
                    global iutest_incg_list
280
                    iutest_incg_list = IUTEST_INCG_REGEX.findall(iutest_src)
281
                except:
282
                    print('{0} is not found...'.format(fused_src))
283
                    print('please try \"make fused\"')
284
                    exit(1)
285
        else:
286
            m = EXPAND_INCLUDE_REGEX.match(line)
287
            if m:
288
                include_path = os.path.normpath(os.path.join(os.path.dirname(path), m.group(1)))
289
                if is_iutest_included_file(include_path):
290
                    code += '//origin>> '
291
                elif os.path.exists(include_path):
292
                    if expand:
293
                        expand_include_file_code = make_code(
294
                            include_path, encoding, expand, includes, included_files)
295
                        code += expand_include_file_code
296
                        code += '//origin>> '
297
                    else:
298
                        include_abspath = os.path.abspath(include_path)
299
                        include_filename = make_include_filename(
300
                            include_abspath, includes, included_files)
301
                        if not include_filename == include_path:
302
                            code += '#include "' + include_filename + '"\n'
303
                            code += '//origin>> '
304
                        if include_filename not in includes:
305
                            includes[include_filename] = ''
306
                            expand_include_file_code = make_code(
307
                                include_path, encoding, expand, includes, included_files)
308
                            includes[include_filename] = expand_include_file_code
309
            code += line
310
    file.close()
311
    return code
312
313
314
def print_undefined_option(option_name, compiler):
315
    print('Wandbox is not supported option [{0}] ({1})'.format(option_name, compiler))
316
317
318
def change_std_option(options, new_value):
319
    print('  change std option: {0} -> {1}'.format(options.std, new_value))
320
    options.std = new_value
321
322
323
def check_std_option_compatible(options, old, new, optlist):
324
    if (options.std == old) and (new in optlist):
325
        print('  [{0}] is not supported option. you can use [{1}]'.format(old, new))
326
        change_std_option(options, new)
327
        return True
328
    elif (options.std == new) and (old in optlist):
329
        print('  [{0}] is not supported option. you can use [{1}]'.format(new, old))
330
        change_std_option(options, old)
331
        return True
332
    return False
333
334
# check config
335
def check_config(options):
336
    has_error = False
337
    if not find_compiler(options.compiler):
338
        print('Wandbox is not supported compiler [' + options.compiler + ']')
339
        listup_compiler(options.verbose)
340
        has_error = True
341
    if options.options or options.std:
342
        opt = get_options(options.compiler)
343
        if options.options:
344
            for o in options.options.split(','):
345
                if o not in opt:
346
                    print_undefined_option(o, options.compiler)
347
                    has_error = True
348
        if options.std:
349
            if options.std not in opt:
350
                print_undefined_option(options.std, options.compiler)
351
                prev_std_option = options.std
352
                if  check_std_option_compatible(options, 'c++1z', 'c++17', opt) or \
353
                    check_std_option_compatible(options, 'gnu++1z', 'gnu++17', opt) or \
354
                    check_std_option_compatible(options, 'c++1y', 'c++14', opt) or \
355
                    check_std_option_compatible(options, 'gnu++1y', 'gnu++14', opt) or \
356
                    check_std_option_compatible(options, 'c++0x', 'c++11', opt) or \
357
                    check_std_option_compatible(options, 'gnu++0x', 'gnu++11', opt):
358
                    pass
359
                if (options.std == prev_std_option):
360
                    has_error = True
361
        if has_error:
362
            listup_options(options.compiler)
363
    if has_error:
364
        sys.exit(1)
365
    if options.default:
366
        print('--default option is deprecated. default options are always set.')
367
368
369
# setup additional files
370
def add_files(w, fileinfos):
371
    for filename, code in fileinfos.items():
372
        w.add_file(filename, code)
373
374
375
# create opt list
376
def create_option_list(options):
377
    def filterout_cppver(opt):
378
        tmp = list(filter(lambda s: s.find('c++') == -1, opt))
379
        tmp = list(filter(lambda s: s.find('gnu++') == -1, tmp))
380
        return tmp
381
    def find_cppname(opt):
382
        if any((x.startswith('c++') for x in opt)):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable x does not seem to be defined.
Loading history...
383
            return 'c++'
384
        return 'gnu++'
385
    opt = []
386
    if not options.no_default:
387
        opt = get_default_options(options.compiler)
388
    if options.options:
389
        for o in options.options.split(','):
390
            if o not in opt:
391
                if (o.find('c++') == 0) or (o.find('gnu++') == 0):
392
                    opt = filterout_cppver(opt)
393
                opt.append(o)
394
    # std
395
    if options.std:
396
        opt = filterout_cppver(opt)
397
        opt.append(options.std)
398
    # optimize
399
    if options.optimize and ('optimize' not in opt):
400
        opt.append('optimize')
401
    # cpp-verbose
402
    if options.cpp_verbose and ('cpp-verbose' not in opt):
403
        opt.append('cpp-verbose')
404
    # boost
405
    if workaround:
406
        if options.compiler in ['clang-3.1']:
407
            cppname = find_cppname(opt)
408
            opt = filterout_cppver(opt)
409
            opt.append(cppname + '98')
410
#        if options.compiler in ['clang-3.4', 'clang-3.3']:
411
#            if not options.boost:
412
#                options.boost = 'nothing'
413
        pass
414
    if options.boost:
415
        if options.compiler not in options.boost:
416
            options.boost = options.boost + '-' + options.compiler
417
        opt = list(filter(lambda s: s.find('boost') == -1, opt))
418
        opt.append('boost-' + str(options.boost))
419
    # sprout
420
    if options.sprout and ('sprout' not in opt):
421
        opt.append('sprout')
422
    # msgpack
423
    if options.msgpack and ('msgpack' not in opt):
424
        opt.append('msgpack')
425
    return opt
426
427
428
def expand_wandbox_options(w, compiler, options):
429
    colist = []
430
    defs = {}
431
    for d in w.get_compiler_list():
432
        if d['name'] == compiler:
433
            if 'switches' in d:
434
                switches = d['switches']
435
                for s in switches:
436
                    if 'options' in s:
437
                        for o in s['options']:
438
                            if ('name' in o) and ('display-flags' in o):
439
                                defs[o['name']] = o['display-flags']
440
                    elif ('name' in s) and ('display-flags' in s):
441
                        defs[s['name']] = s['display-flags']
442
    for opt in options:
443
        if opt in defs:
444
            colist.extend(defs[opt].split())
445
    return colist
446
447
448
def wandbox_api_call(callback, retries, retry_wait):
449
    try:
450
        return callback()
451
    except (HTTPError, ConnectionError) as e:
452
453
        def is_retry(e):
454
            if not e.response:
455
                return True
456
            return e.response.status_code in [504]
457
458
        if is_retry(e) and retries > 0:
459
            try:
460
                print(e.message)
461
            except:
462
                pass
463
            print('wait {0}sec...'.format(retry_wait))
464
            sleep(retry_wait)
465
            return wandbox_api_call(callback, retries - 1, retry_wait)
466
        else:
467
            raise
468
    except:
469
        raise
470
471
472
def wandbox_get_compilerlist():
473
    return wandbox_api_call(Wandbox.GetCompilerList, api_retries, api_retry_wait)
474
475
476
def wandbox_get_compilerswitches(compiler):
477
    for d in wandbox_get_compilerlist():
478
        if d['name'] == compiler:
479
            if 'switches' in d:
480
                return d['switches']
481
    return []
482
483
484
def run_wandbox_impl(w, options):
485
    if options.dryrun:
486
        sys.exit(0)
487
    retries = options.retry
488
489
    def run():
490
        return w.run()
491
    return wandbox_api_call(run, retries, options.retry_wait)
492
493
494
def create_compiler_raw_option_list(options):
495
    colist = []
496
    if options.compiler_option_raw:
497
        raw_options = options.compiler_option_raw
498
        for x in raw_options:
499
            colist.extend(re.split('\s(?=-)', x.strip('"')))
500
    if options.iutest_use_main:
501
        colist.append('-DIUTEST_USE_MAIN')
502
    if '-D__WANDBOX__' not in colist:
503
        colist.append('-D__WANDBOX__')
504
    return colist
505
506
507
# run wandbox (makefile)
508
def run_wandbox_make(main_filepath, code, includes, impliments, options):
509
    with Wandbox() as w:
510
        w.compiler('bash')
511
        woptions = create_option_list(options)
512
        if options.stdin:
513
            w.stdin(options.stdin)
514
        impliments[os.path.basename(main_filepath)] = code
515
516
        colist = create_compiler_raw_option_list(options)
517
        colist.extend(expand_wandbox_options(w, options.compiler, woptions))
518
519
        rolist = []
520
        if options.runtime_option_raw:
521
            for opt in options.runtime_option_raw:
522
                rolist.extend(opt.split())
523
524
        makefile = '#!/bin/make\n# generate makefile by iuwandbox.py\n'
525
        makefile += '\nCXXFLAGS+='
526
        for opt in colist:
527
            makefile += opt + ' '
528
        makefile += '\nOBJS='
529
        for filename in impliments.keys():
530
            makefile += os.path.splitext(filename)[0] + '.o '
531
532
        makefile += '\n\
533
prog: $(OBJS)\n\
534
\t$(CXX) -o $@ $^ $(CXXFLAGS) $(LDFLAGS)\n\
535
'
536
537
        impliments['Makefile'] = makefile
538
539
        bashscript = 'make -j 4\n'
540
        bashscript += './prog '
541
        for opt in rolist:
542
            bashscript += opt + ' '
543
        bashscript += '\n'
544
        w.code(bashscript)
545
546
        if options.save:
547
            w.permanent_link(options.save)
548
        if options.verbose:
549
            w.dump()
550
        add_files(w, impliments)
551
        add_files(w, includes)
552
553
        return run_wandbox_impl(w, options)
554
555
556
# run wandbox (cxx)
557
def run_wandbox_cxx(code, includes, impliments, options):
558
    with Wandbox() as w:
559
        w.compiler(options.compiler)
560
        woptions = ','.join(create_option_list(options))
561
        w.options(woptions)
562
        if options.stdin:
563
            w.stdin(options.stdin)
564
        colist = create_compiler_raw_option_list(options)
565
566
        if workaround:
567
            if options.compiler in ['clang-3.2']:
568
                colist.append('-ftemplate-depth=1024')
569
    #        if options.compiler in ['clang-3.4']:
570
    #            colist.append('-DIUTEST_HAS_HDR_CXXABI=0')
571
    #        if options.compiler in ['clang-3.3', 'clang-3.2', 'clang-3.1', 'clang-3.0']:
572
    #            colist.append('-Qunused-arguments')
573
            if 'boost-nothing' in woptions:
574
                if options.compiler in ['clang-3.4', 'clang-3.3']:
575
                    colist.append('-fno-exceptions')
576
                    colist.append('-fno-rtti')
577
            pass
578
        if colist:
579
            co = '\n'.join(colist)
580
            co = co.replace('\\n', '\n')
581
            w.compiler_options(co)
582
        if options.runtime_option_raw:
583
            rolist = []
584
            for opt in options.runtime_option_raw:
585
                rolist.extend(opt.split())
586
            ro = '\n'.join(rolist)
587
            ro = ro.replace('\\n', '\n')
588
            w.runtime_options(ro)
589
        if options.save:
590
            w.permanent_link(options.save)
591
        for filename in impliments.keys():
592
            w.add_compiler_options(filename)
593
        if options.verbose:
594
            w.dump()
595
        w.code(code)
596
        add_files(w, impliments)
597
        add_files(w, includes)
598
599
        return run_wandbox_impl(w, options)
600
601
602
# run wandbox
603
def run_wandbox(main_filepath, code, includes, impliments, options):
604
    if options.make:
605
        return run_wandbox_make(main_filepath, code, includes, impliments, options)
606
    return run_wandbox_cxx(code, includes, impliments, options)
607
608
609
def wandbox_hint(r):
610
    if 'compiler_error' in r:
611
        if 'undefined reference to `main' in r['compiler_error']:
612
            print('hint:')
613
            print('  In "iutest" you can omit the definition of the main function, please define IUTEST_USE_MAIN. (--iutest-use-main or -f"-DIUTEST_USE_MAIN")')
614
        elif 'undefined reference to `init_unit_test_suite' in r['compiler_error']:
615
            print('hint:')
616
            print('  If you do not use boost test, please specify the file with the main function first.')
617
618
619
def text_transform(value):
620
    try:
621
        if isinstance(value, str):
622
            return value.decode()
623
        elif isinstance(value, unicode):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable unicode does not seem to be defined.
Loading history...
624
            return value.encode('utf_8')
625
    except:
626
        pass
627
    return value
628
629
630
# show result
631
def show_result(r, options):
632
    if r is None:
633
        print('failed: timeout...')
634
        sys.exit(1)
635
    if 'error' in r:
636
        print(r['error'])
637
        sys.exit(1)
638
    if options.stderr:
639
        if 'compiler_output' in r:
640
            print('compiler_output:')
641
            print(text_transform(r['compiler_output']))
642
        if 'compiler_error' in r:
643
            sys.stderr.write(text_transform(r['compiler_error']))
644
        if 'program_output' in r:
645
            print('program_output:')
646
            print(text_transform(r['program_output']))
647
        if options.xml is None and options.junit is None and 'program_error' in r:
648
            sys.stderr.write(text_transform(r['program_error']))
649
    else:
650
        if 'compiler_message' in r:
651
            print('compiler_message:')
652
            print(text_transform(r['compiler_message']))
653
        if 'program_message' in r:
654
            print('program_message:')
655
            print(text_transform(r['program_message']))
656
    if 'url' in r:
657
        print('permlink: ' + r['permlink'])
658
        print('url: ' + r['url'])
659
    if 'signal' in r:
660
        print('signal: ' + r['signal'])
661
    wandbox_hint(r)
662
663
    if 'status' in r:
664
        return int(r['status'])
665
    return 1
666
667
668
# show parameter
669
def show_parameter(r):
670
    if 'compiler' in r:
671
        print('compiler:' + r['compiler'])
672
    if 'options' in r:
673
        print('options:' + r['options'])
674
    if 'compiler-option-raw' in r:
675
        print('compiler-option-raw:' + r['compiler-option-raw'])
676
    if 'runtime-option-raw' in r:
677
        print('runtime-option-raw' + r['runtime-option-raw'])
678
    if 'created-at' in r:
679
        print(r['created-at'])
680
681
682
def set_output_xml(options, t, xml):
683
    options.stderr = True
684
    if options.runtime_option_raw:
685
        options.runtime_option_raw.append('--iutest_output=' + t + ':' + xml)
686
    else:
687
        options.runtime_option_raw = ['--iutest_output=' + t + ':' + xml]
688
689
690
def run(options):
691
    main_filepath = options.code[0].strip()
692
    if not os.path.exists(main_filepath):
693
        sys.exit(1)
694
    includes = {}
695
    included_files = {}
696
    impliments = {}
697
    code = make_code(main_filepath, options.encoding, options.expand_include, includes, included_files)
698
699
    for filepath_ in options.code[1:]:
700
        filepath = filepath_.strip()
701
        impliments[os.path.basename(filepath)] = make_code(filepath, options.encoding, options.expand_include, includes, included_files)
702
703
    if options.output:
704
        f = file_open(options.output, 'w', options.encoding)
705
        f.write(code)
706
        f.close()
707
    xml = None
708
    if options.xml:
709
        xml = options.xml
710
        set_output_xml(options, 'xml', xml)
711
    if options.junit:
712
        xml = options.junit
713
        set_output_xml(options, 'junit', xml)
714
    r = run_wandbox(main_filepath, code, includes, impliments, options)
715
    b = show_result(r, options)
716
    if xml and 'program_error' in r:
717
        f = file_open(xml, 'w', options.encoding)
718
        f.write(r['program_error'])
719
        f.close()
720
    sys.exit(b)
721
722
723
# listup compiler
724
def listup_compiler(verbose):
725
    r = wandbox_get_compilerlist()
726
    for d in r:
727
        if d['language'] == 'C++':
728
            if verbose:
729
                print(d['name'] + ' (' + d['version'] + ')')
730
            else:
731
                print(d['name'])
732
733
734
# find compiler
735
def find_compiler(c):
736
    r = wandbox_get_compilerlist()
737
    for d in r:
738
        if d['language'] == 'C++' and d['name'] == c:
739
            return True
740
    return False
741
742
743
# listup options
744
def listup_options(compiler):
745
    r = wandbox_get_compilerlist()
746
    for d in r:
747
        if d['name'] == compiler:
748
            print('# ' + compiler)
749
            if 'switches' in d:
750
                switches = d['switches']
751
                for s in switches:
752
                    try:
753
                        if 'options' in s:
754
                            default_option = s['default']
755
                            if 'name' in s:
756
                                print(s['name'])
757
                            for o in s['options']:
758
                                if o['name'] == default_option:
759
                                    print('  ' + o['name'] + ' (default)')
760
                                else:
761
                                    print('  ' + o['name'])
762
                        elif 'name' in s:
763
                            if s['default']:
764
                                print(s['name'] + ' (default)')
765
                            else:
766
                                print(s['name'])
767
                    except KeyError:
768
                        print("unknown format:")
769
                        print(s)
770
771
772
def get_options(compiler):
773
    opt = []
774
    for s in wandbox_get_compilerswitches(compiler):
775
        if 'options' in s:
776
            opt.append(s['default'])
777
            for o in s['options']:
778
                opt.append(o['name'])
779
        elif 'name' in s:
780
            opt.append(s['name'])
781
    return opt
782
783
784
# get default options
785
def get_default_options(compiler):
786
    opt = []
787
    for s in wandbox_get_compilerswitches(compiler):
788
        if 'options' in s:
789
            opt.append(s['default'])
790
        elif 'name' in s:
791
            if s['default']:
792
                opt.append(s['name'])
793
    return opt
794
795
796
# get permlink
797
def get_permlink(options):
798
    r = Wandbox.GetPermlink(options.permlink)
799
    p = r['parameter']
800
    show_parameter(p)
801
    print('result:')
802
    b = show_result(r['result'], options)
803
    if options.output:
804
        f = open(options.output, 'w')
805
        f.write(p['code'])
806
        f.close()
807
    sys.exit(b)
808
809
810
def main():
811
    options, parser = parse_command_line()
812
    if options.list_compiler:
813
        listup_compiler(options.verbose)
814
    elif options.list_options:
815
        listup_options(options.list_options)
816
    elif options.permlink:
817
        get_permlink(options)
818
    else:
819
        if options.check_config:
820
            check_config(options)
821
        elif not options.code:
822
            parser.print_help()
823
            sys.exit(1)
824
        run(options)
825
826
827
if __name__ == '__main__':
828
    main()
829