Passed
Push — feature/wandbox_make ( 861991 )
by srz
57:59
created

iuwandbox.get_compiler_exec()   A

Complexity

Conditions 4

Size

Total Lines 8
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 8
nop 1
dl 0
loc 8
rs 10
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
15
from argparse import ArgumentParser
16
from argparse import SUPPRESS
17
from wandbox import Wandbox
18
19
IUTEST_FUSED_SRC = os.path.normpath(os.path.join(os.path.dirname(__file__), '../../fused-src/iutest.min.hpp'))
20
IUTEST_WANDBOX_FUSED_SRC = os.path.normpath(os.path.join(os.path.dirname(__file__), '../../fused-src/iutest.wandbox.min.hpp'))
21
IUTEST_INCLUDE_PATH = os.path.normpath(os.path.join(os.path.dirname(__file__), '../../include'))
22
IUTEST_INCLUDE_REGEX = re.compile(r'^\s*#\s*include\s*".*(iutest|iutest_switch)\.hpp"')
23
EXPAND_INCLUDE_REGEX = re.compile(r'^\s*#\s*include\s*"(.*?)"')
24
IUTEST_INCG_REGEX = re.compile(r'\s*#\s*define[/\s]*(INCG_IRIS_\S*)\s*')
25
26
iutest_incg_list = []
27
workaround = True
28
api_retries = 3
29
api_retry_wait = 60
30
fused_src = IUTEST_WANDBOX_FUSED_SRC
31
32
33
# command line option
34
def parse_command_line():
35
    global api_retries
36
    global api_retry_wait
37
    global fused_src
38
39
    parser = ArgumentParser()
40
    parser.add_argument(
41
        '-v',
42
        '--version',
43
        action='version',
44
        version=u'%(prog)s version 7.1'
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=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
        '--iutest-use-wandbox-min',
204
        action='store_true',
205
        default=True,
206
        help='!this option is deprecated! use iutest.wandbox.min.hpp (default true).'
207
    )
208
    parser.add_argument(
209
        '--no-iutest-use-wandbox-min',
210
        action='store_true',
211
        help='not use iutest.wandbox.min.hpp (experimental).'
212
    )
213
    parser.add_argument(
214
        '--verbose',
215
        action='store_true',
216
        help='verbose.'
217
    )
218
    parser.add_argument(
219
        '--dryrun',
220
        action='store_true',
221
        help='dryrun.'
222
    )
223
    parser.add_argument(
224
        'code',
225
        metavar='CODE',
226
        nargs='*',
227
        help='source code file'
228
    )
229
    options = parser.parse_args()
230
    api_retries = options.retry
231
    api_retry_wait = options.retry_wait
232
    if options.no_iutest_use_wandbox_min:
233
        fused_src = IUTEST_FUSED_SRC
234
    return options, parser
235
236
237
# file open
238
def file_open(path, mode, encoding):
239
    if encoding:
240
        file = codecs.open(path, mode, encoding)
241
    else:
242
        file = open(path, mode)
243
    return file
244
245
246
# make include filename
247
def make_include_filename(path, includes, included_files):
248
    if path in included_files:
249
        return included_files[path]
250
    include_dir, include_filename = os.path.split(path)
251
    while include_filename in includes:
252
        include_dir, dirname = os.path.split(include_dir)
253
        include_filename = dirname + '__' + include_filename
254
    included_files[path] = include_filename
255
    return include_filename
256
257
258
def is_iutest_included_file(filepath):
259
    if os.path.abspath(filepath).startswith(IUTEST_INCLUDE_PATH):
260
        incg = 'INCG_IRIS_' + os.path.basename(filepath).upper().replace('.', '_')
261
        for included_incg in iutest_incg_list:
262
            if included_incg.startswith(incg):
263
                return True
264
    return False
265
266
267
# make code
268
def make_code(path, encoding, expand, includes, included_files):
269
    code = ''
270
    file = file_open(path, 'r', encoding)
271
    for line in file:
272
        m = IUTEST_INCLUDE_REGEX.match(line)
273
        if m:
274
            code += '#include "iutest.hpp"\n'
275
            code += '//origin>> ' + line
276
            if 'iutest.hpp' not in includes:
277
                try:
278
                    f = codecs.open(fused_src, 'r', 'utf-8-sig')
279
                    iutest_src = f.read()
280
                    f.close()
281
                    includes['iutest.hpp'] = iutest_src
282
                    global iutest_incg_list
283
                    iutest_incg_list = IUTEST_INCG_REGEX.findall(iutest_src)
284
                except Exception:
285
                    print('{0} is not found...'.format(fused_src))
286
                    print('please try \"make fused\"')
287
                    exit(1)
288
        else:
289
            m = EXPAND_INCLUDE_REGEX.match(line)
290
            if m:
291
                include_path = os.path.normpath(os.path.join(os.path.dirname(path), m.group(1)))
292
                if is_iutest_included_file(include_path):
293
                    code += '//origin>> '
294
                elif os.path.exists(include_path):
295
                    if expand:
296
                        expand_include_file_code = make_code(
297
                            include_path, encoding, expand, includes, included_files)
298
                        code += expand_include_file_code
299
                        code += '//origin>> '
300
                    else:
301
                        include_abspath = os.path.abspath(include_path)
302
                        include_filename = make_include_filename(
303
                            include_abspath, includes, included_files)
304
                        if not include_filename == include_path:
305
                            code += '#include "' + include_filename + '"\n'
306
                            code += '//origin>> '
307
                        if include_filename not in includes:
308
                            includes[include_filename] = ''
309
                            expand_include_file_code = make_code(
310
                                include_path, encoding, expand, includes, included_files)
311
                            includes[include_filename] = expand_include_file_code
312
            code += line
313
    file.close()
314
    return code
315
316
317
def print_undefined_option(option_name, compiler):
318
    print('Wandbox is not supported option [{0}] ({1})'.format(option_name, compiler))
319
320
321
def change_std_option(options, new_value):
322
    print('  change std option: {0} -> {1}'.format(options.std, new_value))
323
    options.std = new_value
324
325
326
def check_std_option_compatible(options, old, new, optlist):
327
    if (options.std == old) and (new in optlist):
328
        print('  [{0}] is not supported option. you can use [{1}]'.format(old, new))
329
        change_std_option(options, new)
330
        return True
331
    elif (options.std == new) and (old in optlist):
332
        print('  [{0}] is not supported option. you can use [{1}]'.format(new, old))
333
        change_std_option(options, old)
334
        return True
335
    return False
336
337
# check config
338
def check_config(options):
339
    has_error = False
340
    if not find_compiler(options.compiler):
341
        print('Wandbox is not supported compiler [' + options.compiler + ']')
342
        listup_compiler(options.verbose)
343
        has_error = True
344
    if options.options or options.std:
345
        opt = get_options(options.compiler)
346
        if options.options:
347
            for o in options.options.split(','):
348
                if o not in opt:
349
                    print_undefined_option(o, options.compiler)
350
                    has_error = True
351
        if options.std:
352
            if options.std not in opt:
353
                print_undefined_option(options.std, options.compiler)
354
                prev_std_option = options.std
355
                if  check_std_option_compatible(options, 'c++1z', 'c++17', opt) or \
356
                    check_std_option_compatible(options, 'gnu++1z', 'gnu++17', opt) or \
357
                    check_std_option_compatible(options, 'c++1y', 'c++14', opt) or \
358
                    check_std_option_compatible(options, 'gnu++1y', 'gnu++14', opt) or \
359
                    check_std_option_compatible(options, 'c++0x', 'c++11', opt) or \
360
                    check_std_option_compatible(options, 'gnu++0x', 'gnu++11', opt):
361
                    pass
362
                if (options.std == prev_std_option):
363
                    has_error = True
364
        if has_error:
365
            listup_options(options.compiler)
366
    if has_error:
367
        sys.exit(1)
368
    if options.default:
369
        print('--default option is deprecated. default options are always set.')
370
371
372
# setup additional files
373
def add_files(w, fileinfos):
374
    for filename, code in fileinfos.items():
375
        w.add_file(filename, code)
376
377
378
# create opt list
379
def create_option_list(options):
380
    def filterout_cppver(opt):
381
        tmp = list(filter(lambda s: s.find('c++') == -1, opt))
382
        tmp = list(filter(lambda s: s.find('gnu++') == -1, tmp))
383
        return tmp
384
    def find_cppname(opt):
385
        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...
386
            return 'c++'
387
        return 'gnu++'
388
    opt = []
389
    if not options.no_default:
390
        opt = get_default_options(options.compiler)
391
    if options.options:
392
        for o in options.options.split(','):
393
            if o not in opt:
394
                if (o.find('c++') == 0) or (o.find('gnu++') == 0):
395
                    opt = filterout_cppver(opt)
396
                opt.append(o)
397
    # std
398
    if options.std:
399
        opt = filterout_cppver(opt)
400
        opt.append(options.std)
401
    # optimize
402
    if options.optimize and ('optimize' not in opt):
403
        opt.append('optimize')
404
    # cpp-verbose
405
    if options.cpp_verbose and ('cpp-verbose' not in opt):
406
        opt.append('cpp-verbose')
407
    # boost
408
    if workaround:
409
        if options.compiler in ['clang-3.1']:
410
            cppname = find_cppname(opt)
411
            opt = filterout_cppver(opt)
412
            opt.append(cppname + '98')
413
#        if options.compiler in ['clang-3.4', 'clang-3.3']:
414
#            if not options.boost:
415
#                options.boost = 'nothing'
416
    if options.boost:
417
        if options.compiler not in options.boost:
418
            options.boost = options.boost + '-' + options.compiler
419
        opt = list(filter(lambda s: s.find('boost') == -1, opt))
420
        opt.append('boost-' + str(options.boost))
421
    # sprout
422
    if options.sprout and ('sprout' not in opt):
423
        opt.append('sprout')
424
    # msgpack
425
    if options.msgpack and ('msgpack' not in opt):
426
        opt.append('msgpack')
427
    return opt
428
429
430
def expand_wandbox_options(w, compiler, options):
431
    colist = []
432
    defs = {}
433
    for d in w.get_compiler_list():
434
        if d['name'] == compiler:
435
            if 'switches' in d:
436
                switches = d['switches']
437
                for s in switches:
438
                    if 'options' in s:
439
                        for o in s['options']:
440
                            if ('name' in o) and ('display-flags' in o):
441
                                defs[o['name']] = o['display-flags']
442
                    elif ('name' in s) and ('display-flags' in s):
443
                        defs[s['name']] = s['display-flags']
444
    for opt in options:
445
        if opt in defs:
446
            colist.extend(defs[opt].split())
447
    return colist
448
449
450
def wandbox_api_call(callback, retries, retry_wait):
451
    return Wandbox.Call(callback, retries, retry_wait)
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
    if '-D__WANDBOX__' not in colist:
485
        colist.append('-D__WANDBOX__')
486
    return colist
487
488
489
def get_compiler_exec(compiler):
490
    if 'gcc' in compiler:
491
        return 'g++'
492
    if 'clang' in compiler:
493
        return 'clang++'
494
    if 'zapcc' in compiler:
495
        return 'zapcc++'
496
    return nil
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable nil does not seem to be defined.
Loading history...
497
498
499
# run wandbox (makefile)
500
def run_wandbox_make(main_filepath, code, includes, impliments, options):
501
    with Wandbox() as w:
502
        w.compiler('bash')
503
        woptions = create_option_list(options)
504
        if options.stdin:
505
            w.stdin(options.stdin)
506
        impliments[os.path.basename(main_filepath)] = code
507
508
        colist = create_compiler_raw_option_list(options)
509
        colist.extend(expand_wandbox_options(w, options.compiler, woptions))
510
511
        rolist = []
512
        if options.runtime_option_raw:
513
            for opt in options.runtime_option_raw:
514
                rolist.extend(opt.split())
515
516
        makefile = '#!/bin/make\n# generate makefile by iuwandbox.py\n'
517
        cxx = get_compiler_exec(options.compiler)
518
        makefile += '\nCXX=/opt/wandbox/' + options.compiler + '/bin/' + cxx
519
        makefile += '\nCXXFLAGS+='
520
        for opt in colist:
521
            makefile += opt + ' '
522
        makefile += '\nOBJS='
523
        for filename in impliments.keys():
524
            makefile += os.path.splitext(filename)[0] + '.o '
525
526
        makefile += '\n\
527
prog: $(OBJS)\n\
528
\t$(CXX) -o $@ $^ $(CXXFLAGS) $(LDFLAGS)\n\
529
'
530
531
        impliments['Makefile'] = makefile
532
533
        bashscript = 'make -j 4\n'
534
        bashscript += './prog '
535
        for opt in rolist:
536
            bashscript += opt + ' '
537
        bashscript += '\n'
538
        w.code(bashscript)
539
540
        if options.save:
541
            w.permanent_link(options.save)
542
        if options.verbose:
543
            w.dump()
544
        add_files(w, impliments)
545
        add_files(w, includes)
546
547
        return run_wandbox_impl(w, options)
548
549
550
# run wandbox (cxx)
551
def run_wandbox_cxx(code, includes, impliments, options):
552
    with Wandbox() as w:
553
        w.compiler(options.compiler)
554
        woptions = ','.join(create_option_list(options))
555
        w.options(woptions)
556
        if options.stdin:
557
            w.stdin(options.stdin)
558
        colist = create_compiler_raw_option_list(options)
559
560
        if workaround:
561
            if options.compiler in ['clang-3.2']:
562
                colist.append('-ftemplate-depth=1024')
563
    #        if options.compiler in ['clang-3.4']:
564
    #            colist.append('-DIUTEST_HAS_HDR_CXXABI=0')
565
    #        if options.compiler in ['clang-3.3', 'clang-3.2', 'clang-3.1', 'clang-3.0']:
566
    #            colist.append('-Qunused-arguments')
567
            if 'boost-nothing' in woptions:
568
                if options.compiler in ['clang-3.4', 'clang-3.3']:
569
                    colist.append('-fno-exceptions')
570
                    colist.append('-fno-rtti')
571
        if colist:
572
            co = '\n'.join(colist)
573
            co = co.replace('\\n', '\n')
574
            w.compiler_options(co)
575
        if options.runtime_option_raw:
576
            rolist = []
577
            for opt in options.runtime_option_raw:
578
                rolist.extend(opt.split())
579
            ro = '\n'.join(rolist)
580
            ro = ro.replace('\\n', '\n')
581
            w.runtime_options(ro)
582
        if options.save:
583
            w.permanent_link(options.save)
584
        for filename in impliments.keys():
585
            w.add_compiler_options(filename)
586
        if options.verbose:
587
            w.dump()
588
        w.code(code)
589
        add_files(w, impliments)
590
        add_files(w, includes)
591
592
        return run_wandbox_impl(w, options)
593
594
595
# run wandbox
596
def run_wandbox(main_filepath, code, includes, impliments, options):
597
    if options.make:
598
        return run_wandbox_make(main_filepath, code, includes, impliments, options)
599
    return run_wandbox_cxx(code, includes, impliments, options)
600
601
602
def wandbox_hint(r):
603
    if 'compiler_error' in r:
604
        if 'undefined reference to `main' in r['compiler_error']:
605
            print('hint:')
606
            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")')
607
        elif 'undefined reference to `init_unit_test_suite' in r['compiler_error']:
608
            print('hint:')
609
            print('  If you do not use boost test, please specify the file with the main function first.')
610
611
612
def text_transform(value):
613
    try:
614
        if isinstance(value, str):
615
            return value.decode()
616
        elif isinstance(value, unicode):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable unicode does not seem to be defined.
Loading history...
617
            return value.encode('utf_8')
618
    except Exception:
619
        pass
620
    return value
621
622
623
# show result
624
def show_result(r, options):
625
    if r is None:
626
        print('failed: timeout...')
627
        sys.exit(1)
628
    if 'error' in r:
629
        print(r['error'])
630
        sys.exit(1)
631
    if options.stderr:
632
        if 'compiler_output' in r:
633
            print('compiler_output:')
634
            print(text_transform(r['compiler_output']))
635
        if 'compiler_error' in r:
636
            sys.stderr.write(text_transform(r['compiler_error']))
637
        if 'program_output' in r:
638
            print('program_output:')
639
            print(text_transform(r['program_output']))
640
        if options.xml is None and options.junit is None and 'program_error' in r:
641
            sys.stderr.write(text_transform(r['program_error']))
642
    else:
643
        if 'compiler_message' in r:
644
            print('compiler_message:')
645
            print(text_transform(r['compiler_message']))
646
        if 'program_message' in r:
647
            print('program_message:')
648
            print(text_transform(r['program_message']))
649
    if 'url' in r:
650
        print('permlink: ' + r['permlink'])
651
        print('url: ' + r['url'])
652
    if 'signal' in r:
653
        print('signal: ' + r['signal'])
654
    wandbox_hint(r)
655
656
    if 'status' in r:
657
        return int(r['status'])
658
    return 1
659
660
661
# show parameter
662
def show_parameter(r):
663
    if 'compiler' in r:
664
        print('compiler:' + r['compiler'])
665
    if 'options' in r:
666
        print('options:' + r['options'])
667
    if 'compiler-option-raw' in r:
668
        print('compiler-option-raw:' + r['compiler-option-raw'])
669
    if 'runtime-option-raw' in r:
670
        print('runtime-option-raw' + r['runtime-option-raw'])
671
    if 'created-at' in r:
672
        print(r['created-at'])
673
674
675
def set_output_xml(options, t, xml):
676
    options.stderr = True
677
    if options.runtime_option_raw:
678
        options.runtime_option_raw.append('--iutest_output=' + t + ':' + xml)
679
    else:
680
        options.runtime_option_raw = ['--iutest_output=' + t + ':' + xml]
681
682
683
def run(options):
684
    main_filepath = options.code[0].strip()
685
    if not os.path.exists(main_filepath):
686
        sys.exit(1)
687
    includes = {}
688
    included_files = {}
689
    impliments = {}
690
    code = make_code(main_filepath, options.encoding, options.expand_include, includes, included_files)
691
692
    for filepath_ in options.code[1:]:
693
        filepath = filepath_.strip()
694
        impliments[os.path.basename(filepath)] = make_code(filepath, options.encoding, options.expand_include, includes, included_files)
695
696
    if options.output:
697
        f = file_open(options.output, 'w', options.encoding)
698
        f.write(code)
699
        f.close()
700
    xml = None
701
    if options.xml:
702
        xml = options.xml
703
        set_output_xml(options, 'xml', xml)
704
    if options.junit:
705
        xml = options.junit
706
        set_output_xml(options, 'junit', xml)
707
    r = run_wandbox(main_filepath, code, includes, impliments, options)
708
    b = show_result(r, options)
709
    if xml and 'program_error' in r:
710
        f = file_open(xml, 'w', options.encoding)
711
        f.write(r['program_error'])
712
        f.close()
713
    sys.exit(b)
714
715
716
# listup compiler
717
def listup_compiler(verbose):
718
    r = wandbox_get_compilerlist()
719
    for d in r:
720
        if d['language'] == 'C++':
721
            if verbose:
722
                print(d['name'] + ' (' + d['version'] + ')')
723
            else:
724
                print(d['name'])
725
726
727
# find compiler
728
def find_compiler(c):
729
    r = wandbox_get_compilerlist()
730
    for d in r:
731
        if d['language'] == 'C++' and d['name'] == c:
732
            return True
733
    return False
734
735
736
# listup options
737
def listup_options(compiler):
738
    r = wandbox_get_compilerlist()
739
    for d in r:
740
        if d['name'] == compiler:
741
            print('# ' + compiler)
742
            if 'switches' in d:
743
                switches = d['switches']
744
                for s in switches:
745
                    try:
746
                        if 'options' in s:
747
                            default_option = s['default']
748
                            if 'name' in s:
749
                                print(s['name'])
750
                            for o in s['options']:
751
                                if o['name'] == default_option:
752
                                    print('  ' + o['name'] + ' (default)')
753
                                else:
754
                                    print('  ' + o['name'])
755
                        elif 'name' in s:
756
                            if s['default']:
757
                                print(s['name'] + ' (default)')
758
                            else:
759
                                print(s['name'])
760
                    except KeyError:
761
                        print("unknown format:")
762
                        print(s)
763
764
765
def get_options(compiler):
766
    opt = []
767
    for s in wandbox_get_compilerswitches(compiler):
768
        if 'options' in s:
769
            opt.append(s['default'])
770
            for o in s['options']:
771
                opt.append(o['name'])
772
        elif 'name' in s:
773
            opt.append(s['name'])
774
    return opt
775
776
777
# get default options
778
def get_default_options(compiler):
779
    opt = []
780
    for s in wandbox_get_compilerswitches(compiler):
781
        if 'options' in s:
782
            opt.append(s['default'])
783
        elif 'name' in s:
784
            if s['default']:
785
                opt.append(s['name'])
786
    return opt
787
788
789
# get permlink
790
def get_permlink(options):
791
    r = Wandbox.GetPermlink(options.permlink)
792
    p = r['parameter']
793
    show_parameter(p)
794
    print('result:')
795
    b = show_result(r['result'], options)
796
    if options.output:
797
        f = open(options.output, 'w')
798
        f.write(p['code'])
799
        f.close()
800
    sys.exit(b)
801
802
803
def main():
804
    options, parser = parse_command_line()
805
    if options.list_compiler:
806
        listup_compiler(options.verbose)
807
    elif options.list_options:
808
        listup_options(options.list_options)
809
    elif options.permlink:
810
        get_permlink(options)
811
    else:
812
        if options.check_config:
813
            check_config(options)
814
        elif not options.code:
815
            parser.print_help()
816
            sys.exit(1)
817
        run(options)
818
819
820
if __name__ == '__main__':
821
    main()
822