Passed
Push — feature/gtest_legacy_compat ( 10b2d8...6be031 )
by srz
56:31
created

iuwandbox   F

Complexity

Total Complexity 210

Size/Duplication

Total Lines 830
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 658
dl 0
loc 830
rs 1.942
c 0
b 0
f 0
wmc 210

34 Functions

Rating   Name   Duplication   Size   Complexity  
A wandbox_get_compilerlist() 0 2 1
A run_wandbox_impl() 0 8 2
A wandbox_get_compilerswitches() 0 6 4
A add_files() 0 3 2
A make_include_filename() 0 9 3
A is_iutest_included_file() 0 7 4
A change_std_option() 0 3 1
A wandbox_api_call() 0 2 1
F create_option_list() 0 49 24
F check_config() 0 32 19
B parse_command_line() 0 201 2
A print_undefined_option() 0 2 1
D expand_wandbox_options() 0 18 13
A check_std_option_compatible() 0 10 5
C make_code() 0 47 11
A file_open() 0 6 2
D run_wandbox_cxx() 0 42 13
A get_default_options() 0 9 5
A get_permlink() 0 11 2
B show_parameter() 0 11 6
A listup_compiler() 0 8 4
B create_compiler_raw_option_list() 0 12 6
A get_compiler_exec() 0 8 4
A run_wandbox() 0 4 2
A find_compiler() 0 6 4
A get_options() 0 10 5
A set_output_xml() 0 6 2
F show_result() 0 35 15
D listup_options() 0 26 12
C run_wandbox_make() 0 51 11
B main() 0 15 6
C run() 0 35 10
A text_transform() 0 9 4
A wandbox_hint() 0 8 4

How to fix   Complexity   

Complexity

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

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

1
#!/usr/bin/env python
2
#
3
# iuwandbox.py
4
#
5
# Copyright (C) 2014-2018, Takazumi Shirayanagi
6
# This software is released under the new BSD License,
7
# see LICENSE
8
#
9
10
import os
11
import sys
12
import re
13
import codecs
14
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
        if len(options.code) < 2:
484
            colist.append('-DIUTEST_USE_MAIN')
485
    if '-D__WANDBOX__' not in colist:
486
        colist.append('-D__WANDBOX__')
487
    return colist
488
489
490
def get_compiler_exec(compiler):
491
    if 'gcc' in compiler:
492
        return 'g++'
493
    if 'clang' in compiler:
494
        return 'clang++'
495
    if 'zapcc' in compiler:
496
        return 'zapcc++'
497
    return None
498
499
500
# run wandbox (makefile)
501
def run_wandbox_make(main_filepath, code, includes, impliments, options):
502
    with Wandbox() as w:
503
        w.compiler('bash')
504
        woptions = create_option_list(options)
505
        if options.stdin:
506
            w.stdin(options.stdin)
507
        impliments[os.path.basename(main_filepath)] = code
508
509
        colist = create_compiler_raw_option_list(options)
510
        colist.extend(expand_wandbox_options(w, options.compiler, woptions))
511
512
        rolist = []
513
        if options.runtime_option_raw:
514
            for opt in options.runtime_option_raw:
515
                rolist.extend(opt.split())
516
517
        makefile = '#!/bin/make\n# generate makefile by iuwandbox.py\n'
518
        cxx = get_compiler_exec(options.compiler)
519
        if cxx is None:
520
            print('failed: invalid compiler...')
521
            sys.exit(1)
522
        makefile += '\nCXX=/opt/wandbox/' + options.compiler + '/bin/' + cxx
523
        makefile += '\nCXXFLAGS+='
524
        for opt in colist:
525
            makefile += opt + ' '
526
        makefile += '\nOBJS='
527
        for filename in impliments.keys():
528
            makefile += os.path.splitext(filename)[0] + '.o '
529
530
        makefile += '\n\
531
prog: $(OBJS)\n\
532
\t$(CXX) -o $@ $^ $(CXXFLAGS) $(LDFLAGS)\n\
533
'
534
535
        impliments['Makefile'] = makefile
536
537
        bashscript = 'make -j 4\n'
538
        bashscript += './prog '
539
        for opt in rolist:
540
            bashscript += opt + ' '
541
        bashscript += '\n'
542
        w.code(bashscript)
543
544
        if options.save:
545
            w.permanent_link(options.save)
546
        if options.verbose:
547
            w.dump()
548
        add_files(w, impliments)
549
        add_files(w, includes)
550
551
        return run_wandbox_impl(w, options)
552
553
554
# run wandbox (cxx)
555
def run_wandbox_cxx(code, includes, impliments, options):
556
    with Wandbox() as w:
557
        w.compiler(options.compiler)
558
        woptions = ','.join(create_option_list(options))
559
        w.options(woptions)
560
        if options.stdin:
561
            w.stdin(options.stdin)
562
        colist = create_compiler_raw_option_list(options)
563
564
        if workaround:
565
            if options.compiler in ['clang-3.2']:
566
                colist.append('-ftemplate-depth=1024')
567
    #        if options.compiler in ['clang-3.4']:
568
    #            colist.append('-DIUTEST_HAS_HDR_CXXABI=0')
569
    #        if options.compiler in ['clang-3.3', 'clang-3.2', 'clang-3.1', 'clang-3.0']:
570
    #            colist.append('-Qunused-arguments')
571
            if 'boost-nothing' in woptions:
572
                if options.compiler in ['clang-3.4', 'clang-3.3']:
573
                    colist.append('-fno-exceptions')
574
                    colist.append('-fno-rtti')
575
        if colist:
576
            co = '\n'.join(colist)
577
            co = co.replace('\\n', '\n')
578
            w.compiler_options(co)
579
        if options.runtime_option_raw:
580
            rolist = []
581
            for opt in options.runtime_option_raw:
582
                rolist.extend(opt.split())
583
            ro = '\n'.join(rolist)
584
            ro = ro.replace('\\n', '\n')
585
            w.runtime_options(ro)
586
        if options.save:
587
            w.permanent_link(options.save)
588
        for filename in impliments.keys():
589
            w.add_compiler_options(filename)
590
        if options.verbose:
591
            w.dump()
592
        w.code(code)
593
        add_files(w, impliments)
594
        add_files(w, includes)
595
596
        return run_wandbox_impl(w, options)
597
598
599
# run wandbox
600
def run_wandbox(main_filepath, code, includes, impliments, options):
601
    if options.make:
602
        return run_wandbox_make(main_filepath, code, includes, impliments, options)
603
    return run_wandbox_cxx(code, includes, impliments, options)
604
605
606
def wandbox_hint(r):
607
    if 'compiler_error' in r:
608
        if 'undefined reference to `main' in r['compiler_error']:
609
            print('hint:')
610
            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")')
611
        elif 'undefined reference to `init_unit_test_suite' in r['compiler_error']:
612
            print('hint:')
613
            print('  If you do not use boost test, please specify the file with the main function first.')
614
615
616
def text_transform(value):
617
    try:
618
        if isinstance(value, str):
619
            return value.decode()
620
        elif isinstance(value, unicode):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable unicode does not seem to be defined.
Loading history...
621
            return value.encode('utf_8')
622
    except Exception:
623
        pass
624
    return value
625
626
627
# show result
628
def show_result(r, options):
629
    if r is None:
630
        print('failed: timeout...')
631
        sys.exit(1)
632
    if 'error' in r:
633
        print(r['error'])
634
        sys.exit(1)
635
    if options.stderr:
636
        if 'compiler_output' in r:
637
            print('compiler_output:')
638
            print(text_transform(r['compiler_output']))
639
        if 'compiler_error' in r:
640
            sys.stderr.write(text_transform(r['compiler_error']))
641
        if 'program_output' in r:
642
            print('program_output:')
643
            print(text_transform(r['program_output']))
644
        if options.xml is None and options.junit is None and 'program_error' in r:
645
            sys.stderr.write(text_transform(r['program_error']))
646
    else:
647
        if 'compiler_message' in r:
648
            print('compiler_message:')
649
            print(text_transform(r['compiler_message']))
650
        if 'program_message' in r:
651
            print('program_message:')
652
            print(text_transform(r['program_message']))
653
    if 'url' in r:
654
        print('permlink: ' + r['permlink'])
655
        print('url: ' + r['url'])
656
    if 'signal' in r:
657
        print('signal: ' + r['signal'])
658
    wandbox_hint(r)
659
660
    if 'status' in r:
661
        return int(r['status'])
662
    return 1
663
664
665
# show parameter
666
def show_parameter(r):
667
    if 'compiler' in r:
668
        print('compiler:' + r['compiler'])
669
    if 'options' in r:
670
        print('options:' + r['options'])
671
    if 'compiler-option-raw' in r:
672
        print('compiler-option-raw:' + r['compiler-option-raw'])
673
    if 'runtime-option-raw' in r:
674
        print('runtime-option-raw' + r['runtime-option-raw'])
675
    if 'created-at' in r:
676
        print(r['created-at'])
677
678
679
def set_output_xml(options, t, xml):
680
    options.stderr = True
681
    if options.runtime_option_raw:
682
        options.runtime_option_raw.append('--iutest_output=' + t + ':' + xml)
683
    else:
684
        options.runtime_option_raw = ['--iutest_output=' + t + ':' + xml]
685
686
687
def run(options):
688
    main_filepath = options.code[0].strip()
689
    if not os.path.exists(main_filepath):
690
        sys.exit(1)
691
    includes = {}
692
    included_files = {}
693
    impliments = {}
694
    code = ""
695
    if len(options.code) > 1 and options.iutest_use_main:
696
        code += '#define IUTEST_USE_MAIN\n'
697
    code += make_code(main_filepath, options.encoding, options.expand_include, includes, included_files)
698
699
700
    for filepath_ in options.code[1:]:
701
        filepath = filepath_.strip()
702
        impliments[os.path.basename(filepath)] = make_code(filepath, options.encoding, options.expand_include, includes, included_files)
703
704
    if options.output:
705
        f = file_open(options.output, 'w', options.encoding)
706
        f.write(code)
707
        f.close()
708
    xml = None
709
    if options.xml:
710
        xml = options.xml
711
        set_output_xml(options, 'xml', xml)
712
    if options.junit:
713
        xml = options.junit
714
        set_output_xml(options, 'junit', xml)
715
    r = run_wandbox(main_filepath, code, includes, impliments, options)
716
    b = show_result(r, options)
717
    if xml and 'program_error' in r:
718
        f = file_open(xml, 'w', options.encoding)
719
        f.write(r['program_error'])
720
        f.close()
721
    sys.exit(b)
722
723
724
# listup compiler
725
def listup_compiler(verbose):
726
    r = wandbox_get_compilerlist()
727
    for d in r:
728
        if d['language'] == 'C++':
729
            if verbose:
730
                print(d['name'] + ' (' + d['version'] + ')')
731
            else:
732
                print(d['name'])
733
734
735
# find compiler
736
def find_compiler(c):
737
    r = wandbox_get_compilerlist()
738
    for d in r:
739
        if d['language'] == 'C++' and d['name'] == c:
740
            return True
741
    return False
742
743
744
# listup options
745
def listup_options(compiler):
746
    r = wandbox_get_compilerlist()
747
    for d in r:
748
        if d['name'] == compiler:
749
            print('# ' + compiler)
750
            if 'switches' in d:
751
                switches = d['switches']
752
                for s in switches:
753
                    try:
754
                        if 'options' in s:
755
                            default_option = s['default']
756
                            if 'name' in s:
757
                                print(s['name'])
758
                            for o in s['options']:
759
                                if o['name'] == default_option:
760
                                    print('  ' + o['name'] + ' (default)')
761
                                else:
762
                                    print('  ' + o['name'])
763
                        elif 'name' in s:
764
                            if s['default']:
765
                                print(s['name'] + ' (default)')
766
                            else:
767
                                print(s['name'])
768
                    except KeyError:
769
                        print("unknown format:")
770
                        print(s)
771
772
773
def get_options(compiler):
774
    opt = []
775
    for s in wandbox_get_compilerswitches(compiler):
776
        if 'options' in s:
777
            opt.append(s['default'])
778
            for o in s['options']:
779
                opt.append(o['name'])
780
        elif 'name' in s:
781
            opt.append(s['name'])
782
    return opt
783
784
785
# get default options
786
def get_default_options(compiler):
787
    opt = []
788
    for s in wandbox_get_compilerswitches(compiler):
789
        if 'options' in s:
790
            opt.append(s['default'])
791
        elif 'name' in s:
792
            if s['default']:
793
                opt.append(s['name'])
794
    return opt
795
796
797
# get permlink
798
def get_permlink(options):
799
    r = Wandbox.GetPermlink(options.permlink)
800
    p = r['parameter']
801
    show_parameter(p)
802
    print('result:')
803
    b = show_result(r['result'], options)
804
    if options.output:
805
        f = open(options.output, 'w')
806
        f.write(p['code'])
807
        f.close()
808
    sys.exit(b)
809
810
811
def main():
812
    options, parser = parse_command_line()
813
    if options.list_compiler:
814
        listup_compiler(options.verbose)
815
    elif options.list_options:
816
        listup_options(options.list_options)
817
    elif options.permlink:
818
        get_permlink(options)
819
    else:
820
        if options.check_config:
821
            check_config(options)
822
        elif not options.code:
823
            parser.print_help()
824
            sys.exit(1)
825
        run(options)
826
827
828
if __name__ == '__main__':
829
    main()
830