iuwandbox.change_std_option()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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