Passed
Push — master ( a48eb7...0ecc19 )
by srz
05:26
created

iuwandbox.check_std_option_compatible()   B

Complexity

Conditions 5

Size

Total Lines 10
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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