Passed
Push — feature/variant_op ( 29d94f...8855ef )
by srz
27:08 queued 21:07
created

iuwandbox.text_transform()   A

Complexity

Conditions 4

Size

Total Lines 9
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 9
nop 1
dl 0
loc 9
rs 9.95
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_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.3'
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
    return Wandbox.Call(callback, retries, retry_wait)
450
451
452
def wandbox_get_compilerlist():
453
    return wandbox_api_call(Wandbox.GetCompilerList, api_retries, api_retry_wait)
454
455
456
def wandbox_get_compilerswitches(compiler):
457
    for d in wandbox_get_compilerlist():
458
        if d['name'] == compiler:
459
            if 'switches' in d:
460
                return d['switches']
461
    return []
462
463
464
def run_wandbox_impl(w, options):
465
    if options.dryrun:
466
        sys.exit(0)
467
    retries = options.retry
468
469
    def run():
470
        return w.run()
471
    return wandbox_api_call(run, retries, options.retry_wait)
472
473
474
def create_compiler_raw_option_list(options):
475
    colist = []
476
    if options.compiler_option_raw:
477
        raw_options = options.compiler_option_raw
478
        for x in raw_options:
479
            colist.extend(re.split('\s(?=-)', x.strip('"')))
480
    if options.iutest_use_main:
481
        colist.append('-DIUTEST_USE_MAIN')
482
    if '-D__WANDBOX__' not in colist:
483
        colist.append('-D__WANDBOX__')
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
        woptions = ','.join(create_option_list(options))
541
        w.options(woptions)
542
        if options.stdin:
543
            w.stdin(options.stdin)
544
        colist = create_compiler_raw_option_list(options)
545
546
        if workaround:
547
            if options.compiler in ['clang-3.2']:
548
                colist.append('-ftemplate-depth=1024')
549
    #        if options.compiler in ['clang-3.4']:
550
    #            colist.append('-DIUTEST_HAS_HDR_CXXABI=0')
551
    #        if options.compiler in ['clang-3.3', 'clang-3.2', 'clang-3.1', 'clang-3.0']:
552
    #            colist.append('-Qunused-arguments')
553
            if 'boost-nothing' in woptions:
554
                if options.compiler in ['clang-3.4', 'clang-3.3']:
555
                    colist.append('-fno-exceptions')
556
                    colist.append('-fno-rtti')
557
            pass
558
        if colist:
559
            co = '\n'.join(colist)
560
            co = co.replace('\\n', '\n')
561
            w.compiler_options(co)
562
        if options.runtime_option_raw:
563
            rolist = []
564
            for opt in options.runtime_option_raw:
565
                rolist.extend(opt.split())
566
            ro = '\n'.join(rolist)
567
            ro = ro.replace('\\n', '\n')
568
            w.runtime_options(ro)
569
        if options.save:
570
            w.permanent_link(options.save)
571
        for filename in impliments.keys():
572
            w.add_compiler_options(filename)
573
        if options.verbose:
574
            w.dump()
575
        w.code(code)
576
        add_files(w, impliments)
577
        add_files(w, includes)
578
579
        return run_wandbox_impl(w, options)
580
581
582
# run wandbox
583
def run_wandbox(main_filepath, code, includes, impliments, options):
584
    if options.make:
585
        return run_wandbox_make(main_filepath, code, includes, impliments, options)
586
    return run_wandbox_cxx(code, includes, impliments, options)
587
588
589
def wandbox_hint(r):
590
    if 'compiler_error' in r:
591
        if 'undefined reference to `main' in r['compiler_error']:
592
            print('hint:')
593
            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")')
594
        elif 'undefined reference to `init_unit_test_suite' in r['compiler_error']:
595
            print('hint:')
596
            print('  If you do not use boost test, please specify the file with the main function first.')
597
598
599
def text_transform(value):
600
    try:
601
        if isinstance(value, str):
602
            return value.decode()
603
        elif isinstance(value, unicode):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable unicode does not seem to be defined.
Loading history...
604
            return value.encode('utf_8')
605
    except:
606
        pass
607
    return value
608
609
610
# show result
611
def show_result(r, options):
612
    if r is None:
613
        print('failed: timeout...')
614
        sys.exit(1)
615
    if 'error' in r:
616
        print(r['error'])
617
        sys.exit(1)
618
    if options.stderr:
619
        if 'compiler_output' in r:
620
            print('compiler_output:')
621
            print(text_transform(r['compiler_output']))
622
        if 'compiler_error' in r:
623
            sys.stderr.write(text_transform(r['compiler_error']))
624
        if 'program_output' in r:
625
            print('program_output:')
626
            print(text_transform(r['program_output']))
627
        if options.xml is None and options.junit is None and 'program_error' in r:
628
            sys.stderr.write(text_transform(r['program_error']))
629
    else:
630
        if 'compiler_message' in r:
631
            print('compiler_message:')
632
            print(text_transform(r['compiler_message']))
633
        if 'program_message' in r:
634
            print('program_message:')
635
            print(text_transform(r['program_message']))
636
    if 'url' in r:
637
        print('permlink: ' + r['permlink'])
638
        print('url: ' + r['url'])
639
    if 'signal' in r:
640
        print('signal: ' + r['signal'])
641
    wandbox_hint(r)
642
643
    if 'status' in r:
644
        return int(r['status'])
645
    return 1
646
647
648
# show parameter
649
def show_parameter(r):
650
    if 'compiler' in r:
651
        print('compiler:' + r['compiler'])
652
    if 'options' in r:
653
        print('options:' + r['options'])
654
    if 'compiler-option-raw' in r:
655
        print('compiler-option-raw:' + r['compiler-option-raw'])
656
    if 'runtime-option-raw' in r:
657
        print('runtime-option-raw' + r['runtime-option-raw'])
658
    if 'created-at' in r:
659
        print(r['created-at'])
660
661
662
def set_output_xml(options, t, xml):
663
    options.stderr = True
664
    if options.runtime_option_raw:
665
        options.runtime_option_raw.append('--iutest_output=' + t + ':' + xml)
666
    else:
667
        options.runtime_option_raw = ['--iutest_output=' + t + ':' + xml]
668
669
670
def run(options):
671
    main_filepath = options.code[0].strip()
672
    if not os.path.exists(main_filepath):
673
        sys.exit(1)
674
    includes = {}
675
    included_files = {}
676
    impliments = {}
677
    code = make_code(main_filepath, options.encoding, options.expand_include, includes, included_files)
678
679
    for filepath_ in options.code[1:]:
680
        filepath = filepath_.strip()
681
        impliments[os.path.basename(filepath)] = make_code(filepath, options.encoding, options.expand_include, includes, included_files)
682
683
    if options.output:
684
        f = file_open(options.output, 'w', options.encoding)
685
        f.write(code)
686
        f.close()
687
    xml = None
688
    if options.xml:
689
        xml = options.xml
690
        set_output_xml(options, 'xml', xml)
691
    if options.junit:
692
        xml = options.junit
693
        set_output_xml(options, 'junit', xml)
694
    r = run_wandbox(main_filepath, code, includes, impliments, options)
695
    b = show_result(r, options)
696
    if xml and 'program_error' in r:
697
        f = file_open(xml, 'w', options.encoding)
698
        f.write(r['program_error'])
699
        f.close()
700
    sys.exit(b)
701
702
703
# listup compiler
704
def listup_compiler(verbose):
705
    r = wandbox_get_compilerlist()
706
    for d in r:
707
        if d['language'] == 'C++':
708
            if verbose:
709
                print(d['name'] + ' (' + d['version'] + ')')
710
            else:
711
                print(d['name'])
712
713
714
# find compiler
715
def find_compiler(c):
716
    r = wandbox_get_compilerlist()
717
    for d in r:
718
        if d['language'] == 'C++' and d['name'] == c:
719
            return True
720
    return False
721
722
723
# listup options
724
def listup_options(compiler):
725
    r = wandbox_get_compilerlist()
726
    for d in r:
727
        if d['name'] == compiler:
728
            print('# ' + compiler)
729
            if 'switches' in d:
730
                switches = d['switches']
731
                for s in switches:
732
                    try:
733
                        if 'options' in s:
734
                            default_option = s['default']
735
                            if 'name' in s:
736
                                print(s['name'])
737
                            for o in s['options']:
738
                                if o['name'] == default_option:
739
                                    print('  ' + o['name'] + ' (default)')
740
                                else:
741
                                    print('  ' + o['name'])
742
                        elif 'name' in s:
743
                            if s['default']:
744
                                print(s['name'] + ' (default)')
745
                            else:
746
                                print(s['name'])
747
                    except KeyError:
748
                        print("unknown format:")
749
                        print(s)
750
751
752
def get_options(compiler):
753
    opt = []
754
    for s in wandbox_get_compilerswitches(compiler):
755
        if 'options' in s:
756
            opt.append(s['default'])
757
            for o in s['options']:
758
                opt.append(o['name'])
759
        elif 'name' in s:
760
            opt.append(s['name'])
761
    return opt
762
763
764
# get default options
765
def get_default_options(compiler):
766
    opt = []
767
    for s in wandbox_get_compilerswitches(compiler):
768
        if 'options' in s:
769
            opt.append(s['default'])
770
        elif 'name' in s:
771
            if s['default']:
772
                opt.append(s['name'])
773
    return opt
774
775
776
# get permlink
777
def get_permlink(options):
778
    r = Wandbox.GetPermlink(options.permlink)
779
    p = r['parameter']
780
    show_parameter(p)
781
    print('result:')
782
    b = show_result(r['result'], options)
783
    if options.output:
784
        f = open(options.output, 'w')
785
        f.write(p['code'])
786
        f.close()
787
    sys.exit(b)
788
789
790
def main():
791
    options, parser = parse_command_line()
792
    if options.list_compiler:
793
        listup_compiler(options.verbose)
794
    elif options.list_options:
795
        listup_options(options.list_options)
796
    elif options.permlink:
797
        get_permlink(options)
798
    else:
799
        if options.check_config:
800
            check_config(options)
801
        elif not options.code:
802
            parser.print_help()
803
            sys.exit(1)
804
        run(options)
805
806
807
if __name__ == '__main__':
808
    main()
809