Changeset ebe9144 in rtems-central


Ignore:
Timestamp:
01/13/23 15:42:20 (14 months ago)
Author:
Andrew Butterfield <Andrew.Butterfield@…>
Branches:
master
Children:
8cca199
Parents:
a64e772
git-author:
Andrew Butterfield <Andrew.Butterfield@…> (01/13/23 15:42:20)
git-committer:
Sebastian Huber <sebastian.huber@…> (01/18/23 11:42:32)
Message:

modifications made to promela_yacc

Location:
formal/promela/src/src/modules/promela_yacc
Files:
4 deleted
4 edited

Legend:

Unmodified
Added
Removed
  • formal/promela/src/src/modules/promela_yacc/LICENSE

    ra64e772 rebe9144  
     1Copyright (c) 2019-2021 by Trinity College Dublin, Ireland
    12Copyright (c) 2014-2018 by California Institute of Technology
    23Copyright (c) 2014-2018 by Ioannis Filippidis
  • formal/promela/src/src/modules/promela_yacc/promela/ast.py

    ra64e772 rebe9144  
    4949    def __init__(self, name, body, args=None,
    5050                 active=None, d_proc=False,
    51                  priority=None, provided=None):
     51                 priority=None, provided=None,
     52                 disable_negation=False):
    5253        self.name = name
    5354        self.body = body
     
    5556        if active is None:
    5657            active = 0
    57         else:
    58             active = int(active.value)
     58        self.d_proc = d_proc
    5959        if priority is not None:
    6060            priority = int(priority.value)
     
    6262        self.priority = priority
    6363        self.provided = provided
     64        self.disable_negation = disable_negation
    6465
    6566    def __str__(self):
     
    8788            args = ''
    8889        else:
    89             args = to_str(self.args)
     90            args = '; '.join(to_str(xx) for x in self.args for xx in x)
    9091        return args
    9192
     
    224225class Program(list):
    225226    def __str__(self):
    226         return '\n'.join(to_str(x) for x in self)
     227        return '\n'.join(to_str(x) for x, _ in self)
    227228
    228229    def __repr__(self):
     
    246247    """Used to mark strings as LTL blocks."""
    247248
    248     def __init__(self, formula):
     249    def __init__(self, formula, name = None):
    249250        self.formula = formula
     251        self.name = name
    250252
    251253    def __repr__(self):
     
    253255
    254256    def __str__(self):
    255         return 'ltl {' + str(self.formula) + '}'
     257        return 'ltl ' + (self.name + ' ' if self.name else '') + '{' + str(self.formula) + '}'
    256258
    257259
    258260class Sequence(list):
    259     def __init__(self, iterable, context=None, is_option=False):
     261    def __init__(self, iterable, context=None, context_for_var=None, context_for_begin=None, context_for_end=None, is_option=False):
    260262        super(Sequence, self).__init__(iterable)
    261         # "atomic" or "dstep"
     263        # "for" or "atomic" or "dstep"
    262264        self.context = context
     265        self.context_for_var = context_for_var
     266        self.context_for_begin = context_for_begin
     267        self.context_for_end = context_for_end
    263268        self.is_option = is_option
    264269
     
    268273        else:
    269274            return (
    270                 self.context + '{\n' +
    271                 _indent(to_str(self)) + '\n}\n')
     275                self.context +
     276                (' (' + self.context_for_var + ' : ' + to_str (self.context_for_begin) + ' .. ' + to_str (self.context_for_end) + ') ' if self.context == 'for' else '') +
     277                '{\n' +
     278                '\n'.join(_indent(to_str(x)) for x in self) + '\n}\n')
    272279
    273280    def __repr__(self):
    274281        l = super(Sequence, self).__repr__()
    275         return 'Sequence({l}, context={c}, is_option={isopt})'.format(
    276             l=l, c=self.context, isopt=self.is_option)
     282        return 'Sequence({l}, context={c}, context_for_var={cfv}, context_for_begin={cfb}, context_for_end={cfe}, is_option={isopt})'.format(
     283            l=l, c=self.context, cfv=self.context_for_var, cfb=self.context_for_begin, cfe=self.context_for_end, isopt=self.is_option)
    277284
    278285    def to_pg(self, g, context=None, option_guard=None, **kw):
     
    281288            context = self.context
    282289        c = context
    283         assert c in {'atomic', 'd_step', None}
     290        assert c in {'atomic', 'd_step', None} # TODO: 'for'
    284291        # atomic cannot appear inside d_step
    285292        if context == 'd_step' and c == 'atomic':
     
    542549        self.length = l
    543550        self.visible = visible
    544         if bitwidth is not None:
    545             self.bitwidth = int(bitwidth.value)
     551        self.bitwidth = int(bitwidth.value) if bitwidth else None
    546552        if vartype == 'bool':
    547553            default_initval = Bool('false')
    548554        else:
    549555            default_initval = Integer('0')
     556        self.msg_types = msg_types
     557        self.initial_value0 = initval
    550558        if initval is None:
    551559            initval = Expression(default_initval)
     
    557565
    558566    def to_str(self):
    559         s = '{type} {varname}{len}'.format(
     567        s = '{type} {varname}{bitwidth}{len}{initval}{msg_types}'.format(
    560568            type=self._type_str(),
    561569            varname=self.name,
    562             len='[{n}]'.format(n=self.len) if self.len else '')
     570            bitwidth=' : {n}'.format(n =self.bitwidth) if self.bitwidth else '',
     571            len=' [{n}]'.format(n=self.length) if self.length and not self.msg_types else '',
     572            initval=' = {i}'.format(i=self.initial_value0) if self.initial_value0 else '',
     573            msg_types=' = [{l}] of {{ {m} }}'.format(l=self.length, m=' , '.join(to_str(x) for x in self.msg_types)) if self.msg_types else '')
    563574        return s
    564575
     
    742753
    743754    def __str__(self):
    744         return 'typedef {name} {\ndecls\n}'.format(
    745             name=self.name, decls=to_str(self.decls))
     755        return 'typedef {name} {{ {decls} }}'.format(
     756            name=self.name, decls='; '.join(to_str(x) for x in self.decls))
    746757
    747758    def exe(self, t):
     
    753764        self.values = values
    754765
    755     def __str__(self):
    756         return 'mtype {{ {values} }}'.format(values=self.values)
     766    def to_str(self):
     767        return 'mtype = {{ {values} }}'.format(values=' , '.join(to_str(x) for x in self.values))
    757768
    758769    def exe(self, t):
     
    775786
    776787    def __str__(self):
    777         return 'run({f})'.format(f=self.func)
    778 
    779 
    780 class Inline(Node):
     788        return 'run {f} ({args})'.format(f=self.func, args='' if self.args is None else ' , '.join(to_str(x) for x in self.args))
     789
     790
     791class InlineDef(Node):
     792    def __init__(self, name, decl, body, disable_negation=False):
     793        self.name = name
     794        self.decl = decl
     795        self.body = body
     796        self.disable_negation = disable_negation
     797
     798    def __str__(self):
     799        return ('inline {name} ({decl}) {{\n'
     800                '{body}\n'
     801                '}}\n\n').format(
     802                    name = self.name,
     803                    decl = ', '.join(to_str(x) for x in self.decl) if self.decl else '',
     804                    body = _indent(to_str(self.body)))
     805
     806class Call(Node):
    781807    def __init__(self, name, args):
    782808        self.name = name
    783809        self.args = args
    784810
    785 
    786 class Call(Node):
    787     def __init__(self, func, args):
    788         self.func = func
    789         self.args = args
     811    def __str__(self):
     812        return '{name} ({args})'.format(name = self.name, args = ', '.join(to_str(x) for x in self.args) if self.args else '')
    790813
    791814
    792815class Assert(Node):
    793     def __init__(self, expr):
     816    def __init__(self, expr, pos = None):
    794817        self.expr = expr
    795 
    796     def __repr__(self):
    797         return 'assert({expr})'.format(expr=repr(self.expr))
     818        self.pos = pos
     819
     820    def __str__(self):
     821        return 'assert({expr})'.format(expr=to_str(self.expr))
    798822
    799823
     
    873897
    874898class Receive(Node):
    875     def __init__(self, varref, args=None):
     899    def __init__(self, varref, args):
    876900        self.var = varref
    877901        self.args = args
     
    879903    def __str__(self):
    880904        v = to_str(self.var)
    881         return 'Rx({v})'.format(v=v)
     905        return '{v} ? {args}'.format(v=v, args = ' , '.join(to_str(x) for x in self.args))
    882906
    883907
    884908class Send(Node):
    885     def __init__(self, varref, args=None):
    886         self.varref = varref
     909    def __init__(self, varref, args):
     910        self.var = varref
    887911        self.args = args
    888912
    889913    def __str__(self):
    890914        v = to_str(self.var)
    891         return 'Tx({v})'.format(v=v)
     915        return '{v} ! {args}'.format(v=v, args = ' , '.join(to_str(x) for x in self.args))
    892916
    893917
    894918class Printf(Node):
    895     def __init__(self, s, args):
     919    def __init__(self, s, args=None):
    896920        self.s = s
    897921        self.args = args
    898922
    899923    def __str__(self):
    900         return 'printf()'.format(s=self.s, args=self.args)
     924        return 'printf({s}{args})'.format(s=self.s, args='' if self.args is None else ' , ' + ' , '.join(to_str(x) for x in self.args))
    901925
    902926
     
    928952    pass
    929953
     954class ReceiveExpr(Node):
     955    def __init__(self, varref, args):
     956        self.var = varref
     957        self.args = args
     958
     959    def __str__(self):
     960        v = to_str(self.var)
     961        return '({v} ? [{args}])'.format(v=v, args = ' , '.join(to_str(x) for x in self.args))
    930962
    931963class Terminal(object):
     
    9681000            name=self.name,
    9691001            index=i,
    970             ext='' if self.extension is None else self.extension)
     1002            ext=('.' + to_str(self.extension)) if self.extension else '' )
    9711003
    9721004
     
    9871019
    9881020    def __str__(self):
    989         return str(self.value)
     1021        return str('true' if self.value else 'false')
    9901022
    9911023
     
    10071039        return '{proc} {inst} @ {label}'.format(
    10081040            proc=self.proctype, inst=inst, label=self.label)
     1041
     1042
     1043class Timeout(Node):
     1044    def __init__(self):
     1045        return
     1046
     1047    def __str__(self):
     1048        return 'timeout'
    10091049
    10101050
  • formal/promela/src/src/modules/promela_yacc/promela/lex.py

    ra64e772 rebe9144  
    22import logging
    33import ply.lex
    4 
     4import re
    55
    66logger = logging.getLogger(__name__)
     
    3131        'eval': 'EVAL',
    3232        'fi': 'FI',
     33        'for': 'FOR',
    3334        'full': 'FULL',
    3435        'get_priority': 'GET_P',
     
    3738        'if': 'IF',
    3839        'init': 'INIT',
     40        'inline': 'INLINE',
    3941        'int': 'INT',
    4042        'len': 'LEN',
     
    5759        'run': 'RUN',
    5860        'short': 'SHORT',
    59         'skip': 'TRUE',
     61        'skip': 'SKIP',
    6062        'show': 'SHOW',
    6163        'timeout': 'TIMEOUT',
     
    6870        'xs': 'XS',
    6971        'W': 'WEAK_UNTIL'}
    70     values = {'skip': 'true'}
     72    values = {'': ''}
    7173    delimiters = ['LPAREN', 'RPAREN', 'LBRACKET', 'RBRACKET',
    72                   'LBRACE', 'RBRACE', 'COMMA', 'PERIOD',
     74                  'LBRACE', 'RBRACE', 'COMMA', 'PERIODS', 'PERIOD',
    7375                  'SEMI', 'COLONS', 'COLON', 'ELLIPSIS']
    7476    # remember to check precedence
     
    160162    t_RBRACE = r'\}'
    161163    t_COMMA = r','
     164    t_PERIODS = r'\.\.'
    162165    t_PERIOD = r'\.'
    163166    t_SEMI = r';'
     
    185188    t_INITIAL_ARROW = r'->'
    186189
     190    def t_PREPROC_stdin(self, t):
     191        r'\# .+ "<stdin>"[0-9 ]*' # WARNING: using '\d+' instead of '.+' does not necessarily result in the same matching
     192        t.lexer.lineno = int (re.search (r'\# (\d+) "<stdin>"', t.value).group (1)) - 1
     193        pass
     194
    187195    def t_PREPROC(self, t):
    188196        r'\#.*'
     
    205213    def t_COMMENT(self, t):
    206214        r' /\*(.|\n)*?\*/'
    207         t.lineno += t.value.count('\n')
     215        t.lexer.lineno += t.value.count('\n')
    208216
    209217    def t_error(self, t):
  • formal/promela/src/src/modules/promela_yacc/promela/yacc.py

    ra64e772 rebe9144  
    1616import warnings
    1717import ply.yacc
     18from sys import platform as _platform
    1819# inline
    1920#
     
    9192            errorlog=errorlog)
    9293
    93     def parse(self, promela):
     94    def parse(self, promela, fic):
    9495        """Parse string of Promela code."""
    95         s = cpp(promela)
     96        s = cpp(promela, fic)
    9697        program = self.parser.parse(
    97             s, lexer=self.lexer.lexer, debug=self.logger)
     98            s, lexer=self.lexer.lexer, debug=self.logger, tracking=True)
    9899        return program
    99100
     
    116117        p[0] = self.ast.Program(p[1])
    117118
     119    def p_program_empty(self, p):
     120        """program : empty"""
     121        p[0] = self.ast.Program([])
     122
    118123    def p_units_iter(self, p):
    119124        """units : units unit"""
     
    127132    def p_unit_proc(self, p):
    128133        """unit : proc
     134                | inline
    129135                | init
    130136                | claim
    131137                | ltl
    132138        """
    133         p[0] = p[1]
     139        p[0] = (p[1], p.lineno(1))
    134140
    135141    def p_unit_decl(self, p):
     
    137143                | utype
    138144        """
    139         p[0] = p[1]
     145        p[0] = (p[1], p.lineno(1))
    140146
    141147    def p_unit_semi(self, p):
     
    159165            provided=enabler, **inst)
    160166
     167    def p_inline(self, p):
     168        ("""inline : INLINE NAME"""
     169         """         LPAREN var_list0 RPAREN"""
     170         """         body
     171         """)
     172        p[0] = self.ast.InlineDef(name = p[2], decl = p[4], body = p[6])
     173
    161174    # instantiator
    162175    def p_inst(self, p):
     
    167180        else:
    168181            n_active = p[2]
    169         d['active'] = n_active
     182        d['active'] = int(n_active.value)
    170183        p[0] = d
    171184
     
    198211        p[0] = self.ast.TypeDef(p[2], seq)
    199212
    200     def p_ltl(self, p):
     213    def p_ltl1(self, p):
     214        """ltl : LTL NAME LBRACE expr RBRACE"""
     215        p[0] = self.ast.LTL(p[4], name = p[2])
     216
     217    def p_ltl2(self, p):
    201218        """ltl : LTL LBRACE expr RBRACE"""
    202219        p[0] = self.ast.LTL(p[3])
     
    218235    def p_decl_lst_end(self, p):
    219236        """decl_lst : one_decl"""
     237        p[0] = [p[1]]
     238
     239    def p_decl0(self, p):
     240        """decl0 : decl_lst0"""
     241        p[0] = self.ast.Sequence(p[1])
     242
     243    def p_decl_empty0(self, p):
     244        """decl0 : empty"""
     245
     246    def p_decl_lst_iter0(self, p):
     247        """decl_lst0 : expr COMMA decl_lst0"""
     248        p[0] = [p[1]] + p[3]
     249
     250    def p_decl_lst_end0(self, p):
     251        """decl_lst0 : expr"""
    220252        p[0] = [p[1]]
    221253
     
    252284    def p_one_decl_mtype(self, p):
    253285        """one_decl : MTYPE asgn LBRACE name_list RBRACE"""
    254         p[0] = self.ast.MessageType(p[3])
     286        p[0] = self.ast.MessageType(p[4])
    255287
    256288    def p_name_list_iter(self, p):
     
    271303        p[0] = [p[1]]
    272304
     305    def p_var_list00_iter(self, p):
     306        """var_list00 : ivar0 COMMA var_list00"""
     307        p[0] = [p[1]] + p[3]
     308
     309    def p_var_list00_end(self, p):
     310        """var_list00 : ivar0"""
     311        p[0] = [p[1]]
     312
     313    def p_var_list0(self, p):
     314        """var_list0 : var_list00"""
     315        p[0] = p[1]
     316
     317    def p_var_list0_empty(self, p):
     318        """var_list0 : empty"""
     319        p[0] = []
     320
    273321    # TODO: vardcl asgn LBRACE c_list RBRACE
     322
     323    def p_ivar0(self, p):
     324        """ivar0 : NAME"""
     325        p[0] = p[1]
    274326
    275327    # ivar = initialized variable
     
    343395    def p_cmpnd_iter(self, p):
    344396        """cmpnd : cmpnd PERIOD cmpnd %prec DOT"""
    345         p[0] = self.ast.VarRef(extension=p[3], **p[1])
     397        p[0] = self.ast.VarRef(extension=p[3], name = p[1].name, index = p[1].index)
    346398
    347399    def p_cmpnd_end(self, p):
     
    468520    def p_statement_assert(self, p):
    469521        """statement : ASSERT full_expr"""
    470         p[0] = self.ast.Assert(p[2])
     522        p[0] = self.ast.Assert(p[2], pos = p.lineno(1))
    471523
    472524    def p_statement_fifo_receive(self, p):
     
    487539
    488540    def p_statement_tx2(self, p):
    489         """statement : varref TX2 margs"""
     541        """statement : varref TX2 rargs"""
    490542        p[0] = self.ast.Send(p[1], p[3])
    491543
     
    497549        """statement : ELSE"""
    498550        p[0] = self.ast.Else()
     551
     552    def p_statement_for(self, p):
     553        """statement : for"""
     554        p[0] = p[1]
     555
     556    def p_for(self, p):
     557        """for : FOR LPAREN NAME COLON full_expr PERIODS full_expr RPAREN LBRACE sequence os RBRACE"""
     558        s = p[10]
     559        s.context = 'for'
     560        s.context_for_var = p[3]
     561        s.context_for_begin = p[5]
     562        s.context_for_end = p[7]
     563        p[0] = s
    499564
    500565    def p_statement_atomic(self, p):
     
    524589    # the stmt of line 696 in spin.y collects the inline ?
    525590    def p_statement_call(self, p):
    526         """statement : NAME LPAREN args RPAREN"""
     591        """statement : NAME LPAREN decl0 RPAREN"""
    527592        # NAME = INAME = inline
    528         c = self.ast.Inline(p[1], p[3])
     593        c = self.ast.Call(p[1], p[3])
    529594        p[0] = self.ast.Sequence([c])
    530595
    531596    def p_statement_assgn_call(self, p):
    532         """statement : varref asgn NAME LPAREN args RPAREN statement"""
    533         inline = self.ast.Inline(p[3], p[5])
     597        """statement : varref asgn NAME LPAREN decl0 RPAREN statement"""
     598        inline = self.ast.Call(p[3], p[5])
    534599        p[0] = self.ast.Assignment(p[1], inline)
    535600
     
    538603        p[0] = self.ast.Return(p[2])
    539604
    540     def p_printf(self, p):
    541         """statement : PRINT LPAREN STRING prargs RPAREN"""
    542         p[0] = self.ast.Printf(p[3], p[4])
     605    def p_printf1(self, p):
     606        """statement : PRINT LPAREN STRING RPAREN"""
     607        p[0] = self.ast.Printf(p[3])
     608
     609    def p_printf2(self, p):
     610        """statement : PRINT LPAREN STRING COMMA decl0 RPAREN"""
     611        p[0] = self.ast.Printf(p[3], p[5])
    543612
    544613    # yet unimplemented for statement:
     
    556625
    557626    def p_varref_lnot(self, p):
    558         """special : varref LNOT margs"""
    559         raise NotImplementedError
     627        """special : varref LNOT rargs"""
     628        p[0] = self.ast.Send(p[1], p[3])
    560629
    561630    def p_break(self, p):
     
    610679
    611680    # probe expr = no negation allowed (positive)
    612     def p_pexpr(self, p):
    613         """pexpr : probe
    614                  | LPAREN pexpr RPAREN
    615                  | pexpr LAND pexpr
     681    def p_pexpr_probe(self, p):
     682        """pexpr : probe"""
     683        p[0] = p[1]
     684
     685    def p_pexpr_paren(self, p):
     686        """pexpr : LPAREN pexpr RPAREN"""
     687        p[0] = p[2]
     688
     689    def p_pexpr_logical(self, p):
     690        """pexpr : pexpr LAND pexpr
    616691                 | pexpr LAND expr
    617692                 | expr LAND pexpr
     
    620695                 | expr LOR pexpr
    621696        """
    622         p[0] = 'pexpr'
     697        p[0] = self.ast.Binary(p[2], p[1], p[3])
    623698
    624699    def p_probe(self, p):
     
    628703                 | NEMPTY LPAREN varref RPAREN
    629704        """
    630         p[0] = 'probe'
     705        p[0] = self.ast.Call(p[1], self.ast.Sequence([p[3]]))
    631706
    632707    def p_expr_paren(self, p):
     
    677752                | varref R_RCV LBRACKET rargs RBRACKET
    678753        """
    679         p[0] = p[1]
    680         warnings.warn('not implemented')
     754        p[0] = self.ast.ReceiveExpr(p[1], p[4])
    681755
    682756    def p_expr_other(self, p):
     
    690764
    691765    def p_expr_run(self, p):
    692         """expr : RUN aname LPAREN args RPAREN opt_priority"""
     766        """expr : RUN aname LPAREN decl0 RPAREN opt_priority"""
    693767        p[0] = self.ast.Run(p[2], p[4], p[6])
    694768
     769    def p_expr_other_1(self, p):
     770        """expr : TIMEOUT"""
     771        p[0] = self.ast.Timeout()
     772
    695773    def p_expr_other_2(self, p):
    696         """expr : TIMEOUT
    697                 | NONPROGRESS
     774        """expr : NONPROGRESS
    698775                | PC_VAL LPAREN expr RPAREN
    699776        """
     
    765842
    766843    def p_const(self, p):
    767         """const : boolean
     844        """const : SKIP
     845                 | boolean
    768846                 | number
    769847        """
    770         # lex maps `skip` to `TRUE`
    771848        p[0] = p[1]
    772849
     
    784861    # =========
    785862
    786     def p_two_args(self, p):
    787         """two_args : expr COMMA expr"""
    788 
    789     def p_args(self, p):
    790         """args : arg"""
    791         p[0] = p[1]
    792 
    793     def p_prargs(self, p):
    794         """prargs : COMMA arg"""
    795         p[0] = p[2]
    796 
    797     def p_prargs_empty(self, p):
    798         """prargs : empty"""
    799 
    800     def p_args_empty(self, p):
    801         """args : empty"""
    802 
    803     def p_margs(self, p):
    804         """margs : arg
    805                  | expr LPAREN arg RPAREN
    806         """
    807 
    808     def p_arg(self, p):
    809         """arg : expr
    810                | expr COMMA arg
    811         """
    812         p[0] = 'arg'
    813 
    814863    # TODO: CONST, MINUS CONST %prec UMIN
    815864    def p_rarg(self, p):
    816         """rarg : varref
     865        """rarg : const
     866                | varref
    817867                | EVAL LPAREN expr RPAREN
    818868        """
    819         p[0] = 'rarg'
    820 
    821     def p_rargs(self, p):
    822         """rargs : rarg
    823                  | rarg COMMA rargs
    824                  | rarg LPAREN rargs RPAREN
    825                  | LPAREN rargs RPAREN
    826         """
     869        # todo: support all cases
     870        #       | rarg LPAREN rargs RPAREN
     871        #       | LPAREN rargs RPAREN
     872        p[0] = p[1]
     873
     874    def p_rargs_iter(self, p):
     875        """rargs : rarg COMMA rargs"""
     876        p[0] = [p[1]] + p[3]
     877
     878    def p_rargs_end(self, p):
     879        """rargs : rarg"""
     880        p[0] = [p[1]]
    827881
    828882    def p_proctype(self, p):
     
    888942
    889943
    890 def cpp(s):
     944def cpp(code, fic):
    891945    """Call the C{C} preprocessor with input C{s}."""
    892946    try:
    893         p = subprocess.Popen(['cpp', '-E', '-x', 'c'],
     947        if _platform == "darwin":
     948            cppprog = 'clang'
     949        else:
     950            cppprog = 'cpp'
     951        p = subprocess.Popen([cppprog, '-E', '-x', 'c', '-' if code is not None else fic], # NOTE: if code is empty, then '-' must be returned as well
    894952                             stdin=subprocess.PIPE,
    895953                             stdout=subprocess.PIPE,
     
    901959        else:
    902960            raise
    903     logger.debug('cpp input:\n' + s)
    904     stdout, stderr = p.communicate(s)
     961    if code:
     962        logger.debug('cpp input:\n' + code)
     963    stdout, stderr = p.communicate(code)
    905964    logger.debug('cpp returned: {c}'.format(c=p.returncode))
    906965    logger.debug('cpp stdout:\n {out}'.format(out=stdout))
     966    if p.returncode != 0:
     967        raise Exception('C preprocessor return code: {returncode}'.format(returncode=p.returncode))
    907968    return stdout
    908969
Note: See TracChangeset for help on using the changeset viewer.