2 * Copyright 2010, INRIA, University of Copenhagen
3 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
4 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
5 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
6 * This file is part of Coccinelle.
8 * Coccinelle is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, according to version 2 of the License.
12 * Coccinelle is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
20 * The authors reserve the right to distribute this or future versions of
21 * Coccinelle under other licenses.
25 (* splits the entire file into minus and plus fragments, and parses each
26 separately (thus duplicating work for the parsing of the context elements) *)
29 module PC
= Parser_cocci_menhir
30 module V0
= Visitor_ast0
31 module VT0
= Visitor_ast0_types
32 module Ast
= Ast_cocci
33 module Ast0
= Ast0_cocci
35 exception Bad_virt
of string
37 let pr = Printf.sprintf
38 (*let pr2 s = prerr_string s; prerr_string "\n"; flush stderr*)
39 let pr2 s
= Printf.printf
"%s\n" s
41 (* for isomorphisms. all should be at the front!!! *)
43 ["all";"optional_storage";"optional_qualifier";"value_format";"comm_assoc"]
45 (* ----------------------------------------------------------------------- *)
48 let line_type (d
,_
,_
,_
,_
,_
,_
,_
) = d
51 match line_type tok
with
52 D.MINUS
| D.OPTMINUS
| D.UNIQUEMINUS
-> ":-"
55 | D.CONTEXT
| D.UNIQUE
| D.OPT
-> ""
59 PC.TMetavariable
-> "metavariable"
60 | PC.TIdentifier
-> "identifier"
62 | PC.TParameter
-> "parameter"
63 | PC.TConstant
-> "constant"
64 | PC.TExpression
-> "expression"
65 | PC.TIdExpression
-> "idexpression"
66 | PC.TInitialiser
-> "initialiser"
67 | PC.TDeclaration
-> "declaration"
68 | PC.TField
-> "field"
69 | PC.TStatement
-> "statement"
70 | PC.TPosition
-> "position"
72 | PC.TFunction
-> "function"
73 | PC.TLocal
-> "local"
75 | PC.TFresh
-> "fresh"
76 | PC.TCppConcatOp
-> "##"
78 | PC.TContext
-> "context"
79 | PC.TTypedef
-> "typedef"
80 | PC.TDeclarer
-> "declarer"
81 | PC.TIterator
-> "iterator"
83 | PC.TRuleName str
-> "rule_name-"^str
84 | PC.TUsing
-> "using"
85 | PC.TVirtual
-> "virtual"
86 | PC.TPathIsoFile str
-> "path_iso_file-"^str
87 | PC.TDisable
-> "disable"
88 | PC.TExtends
-> "extends"
89 | PC.TDepends
-> "depends"
92 | PC.TNever
-> "never"
93 | PC.TExists
-> "exists"
94 | PC.TForall
-> "forall"
95 | PC.TError
-> "error"
96 | PC.TWords
-> "words"
97 | PC.TGenerated
-> "generated"
99 | PC.TNothing
-> "nothing"
101 | PC.Tchar
(clt
) -> "char"^
(line_type2c clt
)
102 | PC.Tshort
(clt
) -> "short"^
(line_type2c clt
)
103 | PC.Tint
(clt
) -> "int"^
(line_type2c clt
)
104 | PC.Tdouble
(clt
) -> "double"^
(line_type2c clt
)
105 | PC.Tfloat
(clt
) -> "float"^
(line_type2c clt
)
106 | PC.Tlong
(clt
) -> "long"^
(line_type2c clt
)
107 | PC.Tvoid
(clt
) -> "void"^
(line_type2c clt
)
108 | PC.Tsize_t
(clt
) -> "size_t"^
(line_type2c clt
)
109 | PC.Tssize_t
(clt
) -> "ssize_t"^
(line_type2c clt
)
110 | PC.Tptrdiff_t
(clt
) -> "ptrdiff_t"^
(line_type2c clt
)
111 | PC.Tstruct
(clt
) -> "struct"^
(line_type2c clt
)
112 | PC.Tunion
(clt
) -> "union"^
(line_type2c clt
)
113 | PC.Tenum
(clt
) -> "enum"^
(line_type2c clt
)
114 | PC.Tunsigned
(clt
) -> "unsigned"^
(line_type2c clt
)
115 | PC.Tsigned
(clt
) -> "signed"^
(line_type2c clt
)
116 | PC.Tstatic
(clt
) -> "static"^
(line_type2c clt
)
117 | PC.Tinline
(clt
) -> "inline"^
(line_type2c clt
)
118 | PC.Ttypedef
(clt
) -> "typedef"^
(line_type2c clt
)
119 | PC.Tattr
(s
,clt
) -> s^
(line_type2c clt
)
120 | PC.Tauto
(clt
) -> "auto"^
(line_type2c clt
)
121 | PC.Tregister
(clt
) -> "register"^
(line_type2c clt
)
122 | PC.Textern
(clt
) -> "extern"^
(line_type2c clt
)
123 | PC.Tconst
(clt
) -> "const"^
(line_type2c clt
)
124 | PC.Tvolatile
(clt
) -> "volatile"^
(line_type2c clt
)
126 | PC.TPragma
(Ast.Noindent s
,_
) -> s
127 | PC.TPragma
(Ast.Indent s
,_
) -> s
128 | PC.TPragma
(Ast.Space s
,_
) -> s
129 | PC.TIncludeL
(s
,clt
) -> (pr "#include \"%s\"" s
)^
(line_type2c clt
)
130 | PC.TIncludeNL
(s
,clt
) -> (pr "#include <%s>" s
)^
(line_type2c clt
)
131 | PC.TUndef
(clt
,_
) -> "#undef"^
(line_type2c clt
)
132 | PC.TDefine
(clt
,_
) -> "#define"^
(line_type2c clt
)
133 | PC.TDefineParam
(clt
,_
,_
,_
) -> "#define_param"^
(line_type2c clt
)
134 | PC.TMinusFile
(s
,clt
) -> (pr "--- %s" s
)^
(line_type2c clt
)
135 | PC.TPlusFile
(s
,clt
) -> (pr "+++ %s" s
)^
(line_type2c clt
)
137 | PC.TInc
(clt
) -> "++"^
(line_type2c clt
)
138 | PC.TDec
(clt
) -> "--"^
(line_type2c clt
)
140 | PC.TIf
(clt
) -> "if"^
(line_type2c clt
)
141 | PC.TElse
(clt
) -> "else"^
(line_type2c clt
)
142 | PC.TWhile
(clt
) -> "while"^
(line_type2c clt
)
143 | PC.TFor
(clt
) -> "for"^
(line_type2c clt
)
144 | PC.TDo
(clt
) -> "do"^
(line_type2c clt
)
145 | PC.TSwitch
(clt
) -> "switch"^
(line_type2c clt
)
146 | PC.TCase
(clt
) -> "case"^
(line_type2c clt
)
147 | PC.TDefault
(clt
) -> "default"^
(line_type2c clt
)
148 | PC.TReturn
(clt
) -> "return"^
(line_type2c clt
)
149 | PC.TBreak
(clt
) -> "break"^
(line_type2c clt
)
150 | PC.TContinue
(clt
) -> "continue"^
(line_type2c clt
)
151 | PC.TGoto
(clt
) -> "goto"^
(line_type2c clt
)
152 | PC.TIdent
(s
,clt
) -> (pr "ident-%s" s
)^
(line_type2c clt
)
153 | PC.TTypeId
(s
,clt
) -> (pr "typename-%s" s
)^
(line_type2c clt
)
154 | PC.TDeclarerId
(s
,clt
) -> (pr "declarername-%s" s
)^
(line_type2c clt
)
155 | PC.TIteratorId
(s
,clt
) -> (pr "iteratorname-%s" s
)^
(line_type2c clt
)
156 | PC.TMetaDeclarer
(_
,_
,_
,clt
) -> "declmeta"^
(line_type2c clt
)
157 | PC.TMetaIterator
(_
,_
,_
,clt
) -> "itermeta"^
(line_type2c clt
)
159 | PC.TSizeof
(clt
) -> "sizeof"^
(line_type2c clt
)
161 | PC.TString
(x
,clt
) -> x^
(line_type2c clt
)
162 | PC.TChar
(x
,clt
) -> x^
(line_type2c clt
)
163 | PC.TFloat
(x
,clt
) -> x^
(line_type2c clt
)
164 | PC.TInt
(x
,clt
) -> x^
(line_type2c clt
)
166 | PC.TOrLog
(clt
) -> "||"^
(line_type2c clt
)
167 | PC.TAndLog
(clt
) -> "&&"^
(line_type2c clt
)
168 | PC.TOr
(clt
) -> "|"^
(line_type2c clt
)
169 | PC.TXor
(clt
) -> "^"^
(line_type2c clt
)
170 | PC.TAnd
(clt
) -> "&"^
(line_type2c clt
)
171 | PC.TEqEq
(clt
) -> "=="^
(line_type2c clt
)
172 | PC.TNotEq
(clt
) -> "!="^
(line_type2c clt
)
173 | PC.TSub
(clt
) -> "<="^
(line_type2c clt
)
174 | PC.TTildeEq
(clt
) -> "~="^
(line_type2c clt
)
175 | PC.TTildeExclEq
(clt
) -> "~!="^
(line_type2c clt
)
176 | PC.TLogOp
(op
,clt
) ->
182 | _
-> failwith
"not possible")
184 | PC.TShLOp
(op
,clt
) -> "<<"^
(line_type2c clt
)
185 | PC.TShROp
(op
,clt
) -> ">>"^
(line_type2c clt
)
186 | PC.TPlus
(clt
) -> "+"^
(line_type2c clt
)
187 | PC.TMinus
(clt
) -> "-"^
(line_type2c clt
)
188 | PC.TMul
(clt
) -> "*"^
(line_type2c clt
)
189 | PC.TDmOp
(op
,clt
) ->
193 | _
-> failwith
"not possible")
195 | PC.TTilde
(clt
) -> "~"^
(line_type2c clt
)
197 | PC.TMeta
(_
,_
,clt
) -> "meta"^
(line_type2c clt
)
198 | PC.TMetaParam
(_
,_
,clt
) -> "parammeta"^
(line_type2c clt
)
199 | PC.TMetaParamList
(_
,_
,_
,clt
) -> "paramlistmeta"^
(line_type2c clt
)
200 | PC.TMetaConst
(_
,_
,_
,_
,clt
) -> "constmeta"^
(line_type2c clt
)
201 | PC.TMetaErr
(_
,_
,_
,clt
) -> "errmeta"^
(line_type2c clt
)
202 | PC.TMetaExp
(_
,_
,_
,_
,clt
) -> "expmeta"^
(line_type2c clt
)
203 | PC.TMetaIdExp
(_
,_
,_
,_
,clt
) -> "idexpmeta"^
(line_type2c clt
)
204 | PC.TMetaLocalIdExp
(_
,_
,_
,_
,clt
) -> "localidexpmeta"^
(line_type2c clt
)
205 | PC.TMetaExpList
(_
,_
,_
,clt
) -> "explistmeta"^
(line_type2c clt
)
206 | PC.TMetaId
(nm
,_
,_
,_
,clt
) -> "idmeta-"^
(Dumper.dump nm
)^
(line_type2c clt
)
207 | PC.TMetaType
(_
,_
,clt
) -> "typemeta"^
(line_type2c clt
)
208 | PC.TMetaInit
(_
,_
,clt
) -> "initmeta"^
(line_type2c clt
)
209 | PC.TMetaInitList
(_
,_
,_
,clt
) -> "initlistmeta"^
(line_type2c clt
)
210 | PC.TMetaDecl
(_
,_
,clt
) -> "declmeta"^
(line_type2c clt
)
211 | PC.TMetaField
(_
,_
,clt
) -> "fieldmeta"^
(line_type2c clt
)
212 | PC.TMetaFieldList
(_
,_
,_
,clt
) -> "fieldlistmeta"^
(line_type2c clt
)
213 | PC.TMetaStm
(_
,_
,clt
) -> "stmmeta"^
(line_type2c clt
)
214 | PC.TMetaStmList
(_
,_
,clt
) -> "stmlistmeta"^
(line_type2c clt
)
215 | PC.TMetaFunc
(_
,_
,_
,clt
) -> "funcmeta"^
(line_type2c clt
)
216 | PC.TMetaLocalFunc
(_
,_
,_
,clt
) -> "funcmeta"^
(line_type2c clt
)
217 | PC.TMetaPos
(_
,_
,_
,clt
) -> "posmeta"
219 | PC.TArobArob
-> "@@"
222 | PC.TScript
-> "script"
223 | PC.TInitialize
-> "initialize"
224 | PC.TFinalize
-> "finalize"
226 | PC.TWhen
(clt
) -> "WHEN"^
(line_type2c clt
)
227 | PC.TWhenTrue
(clt
) -> "WHEN TRUE"^
(line_type2c clt
)
228 | PC.TWhenFalse
(clt
) -> "WHEN FALSE"^
(line_type2c clt
)
229 | PC.TAny
(clt
) -> "ANY"^
(line_type2c clt
)
230 | PC.TStrict
(clt
) -> "STRICT"^
(line_type2c clt
)
231 | PC.TEllipsis
(clt
) -> "..."^
(line_type2c clt
)
233 | PC.TCircles(clt) -> "ooo"^(line_type2c clt)
234 | PC.TStars(clt) -> "***"^(line_type2c clt)
237 | PC.TOEllipsis
(clt
) -> "<..."^
(line_type2c clt
)
238 | PC.TCEllipsis
(clt
) -> "...>"^
(line_type2c clt
)
239 | PC.TPOEllipsis
(clt
) -> "<+..."^
(line_type2c clt
)
240 | PC.TPCEllipsis
(clt
) -> "...+>"^
(line_type2c clt
)
242 | PC.TOCircles(clt) -> "<ooo"^(line_type2c clt)
243 | PC.TCCircles(clt) -> "ooo>"^(line_type2c clt)
244 | PC.TOStars(clt) -> "<***"^(line_type2c clt)
245 | PC.TCStars(clt) -> "***>"^(line_type2c clt)
251 | PC.TWhy
(clt
) -> "?"^
(line_type2c clt
)
252 | PC.TDotDot
(clt
) -> ":"^
(line_type2c clt
)
253 | PC.TBang
(clt
) -> "!"^
(line_type2c clt
)
254 | PC.TOPar
(clt
) -> "("^
(line_type2c clt
)
255 | PC.TOPar0
(clt
) -> "("^
(line_type2c clt
)
256 | PC.TMid0
(clt
) -> "|"^
(line_type2c clt
)
257 | PC.TCPar
(clt
) -> ")"^
(line_type2c clt
)
258 | PC.TCPar0
(clt
) -> ")"^
(line_type2c clt
)
260 | PC.TOBrace
(clt
) -> "{"^
(line_type2c clt
)
261 | PC.TCBrace
(clt
) -> "}"^
(line_type2c clt
)
262 | PC.TOCro
(clt
) -> "["^
(line_type2c clt
)
263 | PC.TCCro
(clt
) -> "]"^
(line_type2c clt
)
264 | PC.TOInit
(clt
) -> "{"^
(line_type2c clt
)
266 | PC.TPtrOp
(clt
) -> "->"^
(line_type2c clt
)
268 | PC.TEq
(clt
) -> "="^
(line_type2c clt
)
269 | PC.TAssign
(_
,clt
) -> "=op"^
(line_type2c clt
)
270 | PC.TDot
(clt
) -> "."^
(line_type2c clt
)
271 | PC.TComma
(clt
) -> ","^
(line_type2c clt
)
272 | PC.TPtVirg
(clt
) -> ";"^
(line_type2c clt
)
275 | PC.TLineEnd
(clt
) -> "line end"
276 | PC.TInvalid
-> "invalid"
277 | PC.TFunDecl
(clt
) -> "fundecl"
280 | PC.TRightIso
-> "=>"
281 | PC.TIsoTopLevel
-> "TopLevel"
282 | PC.TIsoExpression
-> "Expression"
283 | PC.TIsoArgExpression
-> "ArgExpression"
284 | PC.TIsoTestExpression
-> "TestExpression"
285 | PC.TIsoToTestExpression
-> "ToTestExpression"
286 | PC.TIsoStatement
-> "Statement"
287 | PC.TIsoDeclaration
-> "Declaration"
288 | PC.TIsoType
-> "Type"
289 | PC.TUnderscore
-> "_"
290 | PC.TScriptData s
-> s
292 let print_tokens s tokens
=
293 Printf.printf
"%s\n" s
;
294 List.iter
(function x
-> Printf.printf
"%s " (token2c x
)) tokens
;
295 Printf.printf
"\n\n";
298 type plus
= PLUS
| NOTPLUS
| SKIP
300 let plus_attachable only_plus
(tok
,_
) =
302 PC.Tchar
(clt
) | PC.Tshort
(clt
) | PC.Tint
(clt
) | PC.Tdouble
(clt
)
303 | PC.Tfloat
(clt
) | PC.Tlong
(clt
)
304 | PC.Tsize_t
(clt
) | PC.Tssize_t
(clt
) | PC.Tptrdiff_t
(clt
)
306 | PC.Tunion
(clt
) | PC.Tenum
(clt
) | PC.Tunsigned
(clt
) | PC.Tsigned
(clt
)
308 | PC.Tinline
(clt
) | PC.Ttypedef
(clt
) | PC.Tattr
(_
,clt
)
309 | PC.Tauto
(clt
) | PC.Tregister
(clt
)
310 | PC.Textern
(clt
) | PC.Tconst
(clt
) | PC.Tvolatile
(clt
)
312 | PC.TIncludeL
(_
,clt
) | PC.TIncludeNL
(_
,clt
) | PC.TUndef
(clt
,_
)
314 | PC.TDefineParam
(clt
,_
,_
,_
) | PC.TMinusFile
(_
,clt
) | PC.TPlusFile
(_
,clt
)
316 | PC.TInc
(clt
) | PC.TDec
(clt
)
318 | PC.TIf
(clt
) | PC.TElse
(clt
) | PC.TWhile
(clt
) | PC.TFor
(clt
) | PC.TDo
(clt
)
319 | PC.TSwitch
(clt
) | PC.TCase
(clt
) | PC.TDefault
(clt
) | PC.TReturn
(clt
)
320 | PC.TBreak
(clt
) | PC.TContinue
(clt
) | PC.TGoto
(clt
) | PC.TIdent
(_
,clt
)
321 | PC.TTypeId
(_
,clt
) | PC.TDeclarerId
(_
,clt
) | PC.TIteratorId
(_
,clt
)
325 | PC.TString
(_
,clt
) | PC.TChar
(_
,clt
) | PC.TFloat
(_
,clt
) | PC.TInt
(_
,clt
)
327 | PC.TOrLog
(clt
) | PC.TAndLog
(clt
) | PC.TOr
(clt
) | PC.TXor
(clt
)
328 | PC.TAnd
(clt
) | PC.TEqEq
(clt
) | PC.TNotEq
(clt
) | PC.TTildeEq
(clt
)
330 | PC.TShLOp
(_
,clt
) | PC.TShROp
(_
,clt
)
331 | PC.TPlus
(clt
) | PC.TMinus
(clt
) | PC.TMul
(clt
)
332 | PC.TDmOp
(_
,clt
) | PC.TTilde
(clt
)
334 | PC.TMeta
(_
,_
,clt
) | PC.TMetaParam
(_
,_
,clt
) | PC.TMetaParamList
(_
,_
,_
,clt
)
335 | PC.TMetaConst
(_
,_
,_
,_
,clt
) | PC.TMetaErr
(_
,_
,_
,clt
)
336 | PC.TMetaExp
(_
,_
,_
,_
,clt
) | PC.TMetaIdExp
(_
,_
,_
,_
,clt
)
337 | PC.TMetaLocalIdExp
(_
,_
,_
,_
,clt
)
338 | PC.TMetaExpList
(_
,_
,_
,clt
)
339 | PC.TMetaId
(_
,_
,_
,_
,clt
)
340 | PC.TMetaType
(_
,_
,clt
) | PC.TMetaInit
(_
,_
,clt
) | PC.TMetaInitList
(_
,_
,_
,clt
)
341 | PC.TMetaStm
(_
,_
,clt
)
342 | PC.TMetaStmList
(_
,_
,clt
)
343 | PC.TMetaDecl
(_
,_
,clt
) | PC.TMetaField
(_
,_
,clt
)
344 | PC.TMetaFieldList
(_
,_
,_
,clt
)
345 | PC.TMetaFunc
(_
,_
,_
,clt
) | PC.TMetaLocalFunc
(_
,_
,_
,clt
)
347 | PC.TWhen
(clt
) | PC.TWhenTrue
(clt
) | PC.TWhenFalse
(clt
)
348 | PC.TAny
(clt
) | PC.TStrict
(clt
) | PC.TEllipsis
(clt
)
349 (* | PC.TCircles(clt) | PC.TStars(clt) *)
350 | PC.TOEllipsis
(clt
) | PC.TCEllipsis
(clt
)
351 | PC.TPOEllipsis
(clt
) | PC.TPCEllipsis
(clt
) (* | PC.TOCircles(clt)
352 | PC.TCCircles(clt) | PC.TOStars(clt) | PC.TCStars(clt) *)
354 | PC.TWhy
(clt
) | PC.TDotDot
(clt
) | PC.TBang
(clt
) | PC.TOPar
(clt
)
357 | PC.TOBrace
(clt
) | PC.TCBrace
(clt
) | PC.TOCro
(clt
) | PC.TCCro
(clt
)
362 | PC.TEq
(clt
) | PC.TAssign
(_
,clt
) | PC.TDot
(clt
) | PC.TComma
(clt
)
364 if List.mem
(line_type clt
) [D.PLUS
;D.PLUSPLUS
]
366 else if only_plus
then NOTPLUS
367 else if line_type clt
= D.CONTEXT
then PLUS
else NOTPLUS
369 | PC.TOPar0
(clt
) | PC.TMid0
(clt
) | PC.TCPar0
(clt
) -> NOTPLUS
370 | PC.TMetaPos
(nm
,_
,_
,_
) -> NOTPLUS
371 | PC.TSub
(clt
) -> NOTPLUS
375 let get_clt (tok
,_
) =
377 PC.Tchar
(clt
) | PC.Tshort
(clt
) | PC.Tint
(clt
) | PC.Tdouble
(clt
)
378 | PC.Tfloat
(clt
) | PC.Tlong
(clt
) | PC.Tvoid
(clt
)
379 | PC.Tsize_t
(clt
) | PC.Tssize_t
(clt
) | PC.Tptrdiff_t
(clt
)
381 | PC.Tunion
(clt
) | PC.Tenum
(clt
) | PC.Tunsigned
(clt
) | PC.Tsigned
(clt
)
383 | PC.Tinline
(clt
) | PC.Tattr
(_
,clt
) | PC.Tauto
(clt
) | PC.Tregister
(clt
)
384 | PC.Textern
(clt
) | PC.Tconst
(clt
) | PC.Tvolatile
(clt
)
386 | PC.TIncludeL
(_
,clt
) | PC.TIncludeNL
(_
,clt
) | PC.TUndef
(clt
,_
)
388 | PC.TDefineParam
(clt
,_
,_
,_
) | PC.TMinusFile
(_
,clt
) | PC.TPlusFile
(_
,clt
)
390 | PC.TInc
(clt
) | PC.TDec
(clt
)
392 | PC.TIf
(clt
) | PC.TElse
(clt
) | PC.TWhile
(clt
) | PC.TFor
(clt
) | PC.TDo
(clt
)
393 | PC.TSwitch
(clt
) | PC.TCase
(clt
) | PC.TDefault
(clt
) | PC.TReturn
(clt
)
394 | PC.TBreak
(clt
) | PC.TContinue
(clt
) | PC.TGoto
(clt
) | PC.TIdent
(_
,clt
)
395 | PC.TTypeId
(_
,clt
) | PC.TDeclarerId
(_
,clt
) | PC.TIteratorId
(_
,clt
)
399 | PC.TString
(_
,clt
) | PC.TChar
(_
,clt
) | PC.TFloat
(_
,clt
) | PC.TInt
(_
,clt
)
401 | PC.TOrLog
(clt
) | PC.TAndLog
(clt
) | PC.TOr
(clt
) | PC.TXor
(clt
)
402 | PC.TAnd
(clt
) | PC.TEqEq
(clt
) | PC.TNotEq
(clt
) | PC.TTildeEq
(clt
)
403 | PC.TSub
(clt
) | PC.TLogOp
(_
,clt
)
404 | PC.TShLOp
(_
,clt
) | PC.TShROp
(_
,clt
)
405 | PC.TPlus
(clt
) | PC.TMinus
(clt
) | PC.TMul
(clt
)
406 | PC.TDmOp
(_
,clt
) | PC.TTilde
(clt
)
408 | PC.TMeta
(_
,_
,clt
) | PC.TMetaParam
(_
,_
,clt
) | PC.TMetaParamList
(_
,_
,_
,clt
)
409 | PC.TMetaConst
(_
,_
,_
,_
,clt
) | PC.TMetaErr
(_
,_
,_
,clt
)
410 | PC.TMetaExp
(_
,_
,_
,_
,clt
) | PC.TMetaIdExp
(_
,_
,_
,_
,clt
)
411 | PC.TMetaLocalIdExp
(_
,_
,_
,_
,clt
)
412 | PC.TMetaExpList
(_
,_
,_
,clt
)
413 | PC.TMetaId
(_
,_
,_
,_
,clt
)
414 | PC.TMetaType
(_
,_
,clt
) | PC.TMetaInit
(_
,_
,clt
) | PC.TMetaInitList
(_
,_
,_
,clt
)
415 | PC.TMetaStm
(_
,_
,clt
)
416 | PC.TMetaStmList
(_
,_
,clt
)
417 | PC.TMetaDecl
(_
,_
,clt
) | PC.TMetaField
(_
,_
,clt
)
418 | PC.TMetaFieldList
(_
,_
,_
,clt
)
419 | PC.TMetaFunc
(_
,_
,_
,clt
) | PC.TMetaLocalFunc
(_
,_
,_
,clt
)
420 | PC.TMetaPos
(_
,_
,_
,clt
)
422 | PC.TWhen
(clt
) | PC.TWhenTrue
(clt
) | PC.TWhenFalse
(clt
) |
423 PC.TAny
(clt
) | PC.TStrict
(clt
) | PC.TEllipsis
(clt
)
424 (* | PC.TCircles(clt) | PC.TStars(clt) *)
426 | PC.TWhy
(clt
) | PC.TDotDot
(clt
) | PC.TBang
(clt
) | PC.TOPar
(clt
)
429 | PC.TOBrace
(clt
) | PC.TCBrace
(clt
) | PC.TOCro
(clt
) | PC.TCCro
(clt
)
434 | PC.TEq
(clt
) | PC.TAssign
(_
,clt
) | PC.TDot
(clt
) | PC.TComma
(clt
)
437 | PC.TOPar0
(clt
) | PC.TMid0
(clt
) | PC.TCPar0
(clt
)
438 | PC.TOEllipsis
(clt
) | PC.TCEllipsis
(clt
)
439 | PC.TPOEllipsis
(clt
) | PC.TPCEllipsis
(clt
) (* | PC.TOCircles(clt)
440 | PC.TCCircles(clt) | PC.TOStars(clt) | PC.TCStars(clt) *) -> clt
442 | _
-> failwith
"no clt"
444 let update_clt (tok
,x
) clt
=
446 PC.Tchar
(_
) -> (PC.Tchar
(clt
),x
)
447 | PC.Tshort
(_
) -> (PC.Tshort
(clt
),x
)
448 | PC.Tint
(_
) -> (PC.Tint
(clt
),x
)
449 | PC.Tdouble
(_
) -> (PC.Tdouble
(clt
),x
)
450 | PC.Tfloat
(_
) -> (PC.Tfloat
(clt
),x
)
451 | PC.Tlong
(_
) -> (PC.Tlong
(clt
),x
)
452 | PC.Tvoid
(_
) -> (PC.Tvoid
(clt
),x
)
453 | PC.Tsize_t
(_
) -> (PC.Tsize_t
(clt
),x
)
454 | PC.Tssize_t
(_
) -> (PC.Tssize_t
(clt
),x
)
455 | PC.Tptrdiff_t
(_
) -> (PC.Tptrdiff_t
(clt
),x
)
456 | PC.Tstruct
(_
) -> (PC.Tstruct
(clt
),x
)
457 | PC.Tunion
(_
) -> (PC.Tunion
(clt
),x
)
458 | PC.Tenum
(_
) -> (PC.Tenum
(clt
),x
)
459 | PC.Tunsigned
(_
) -> (PC.Tunsigned
(clt
),x
)
460 | PC.Tsigned
(_
) -> (PC.Tsigned
(clt
),x
)
461 | PC.Tstatic
(_
) -> (PC.Tstatic
(clt
),x
)
462 | PC.Tinline
(_
) -> (PC.Tinline
(clt
),x
)
463 | PC.Ttypedef
(_
) -> (PC.Ttypedef
(clt
),x
)
464 | PC.Tattr
(s
,_
) -> (PC.Tattr
(s
,clt
),x
)
465 | PC.Tauto
(_
) -> (PC.Tauto
(clt
),x
)
466 | PC.Tregister
(_
) -> (PC.Tregister
(clt
),x
)
467 | PC.Textern
(_
) -> (PC.Textern
(clt
),x
)
468 | PC.Tconst
(_
) -> (PC.Tconst
(clt
),x
)
469 | PC.Tvolatile
(_
) -> (PC.Tvolatile
(clt
),x
)
471 | PC.TIncludeL
(s
,_
) -> (PC.TIncludeL
(s
,clt
),x
)
472 | PC.TIncludeNL
(s
,_
) -> (PC.TIncludeNL
(s
,clt
),x
)
473 | PC.TUndef
(_
,a
) -> (PC.TUndef
(clt
,a
),x
)
474 | PC.TDefine
(_
,a
) -> (PC.TDefine
(clt
,a
),x
)
475 | PC.TDefineParam
(_
,a
,b
,c
) -> (PC.TDefineParam
(clt
,a
,b
,c
),x
)
476 | PC.TMinusFile
(s
,_
) -> (PC.TMinusFile
(s
,clt
),x
)
477 | PC.TPlusFile
(s
,_
) -> (PC.TPlusFile
(s
,clt
),x
)
479 | PC.TInc
(_
) -> (PC.TInc
(clt
),x
)
480 | PC.TDec
(_
) -> (PC.TDec
(clt
),x
)
482 | PC.TIf
(_
) -> (PC.TIf
(clt
),x
)
483 | PC.TElse
(_
) -> (PC.TElse
(clt
),x
)
484 | PC.TWhile
(_
) -> (PC.TWhile
(clt
),x
)
485 | PC.TFor
(_
) -> (PC.TFor
(clt
),x
)
486 | PC.TDo
(_
) -> (PC.TDo
(clt
),x
)
487 | PC.TSwitch
(_
) -> (PC.TSwitch
(clt
),x
)
488 | PC.TCase
(_
) -> (PC.TCase
(clt
),x
)
489 | PC.TDefault
(_
) -> (PC.TDefault
(clt
),x
)
490 | PC.TReturn
(_
) -> (PC.TReturn
(clt
),x
)
491 | PC.TBreak
(_
) -> (PC.TBreak
(clt
),x
)
492 | PC.TContinue
(_
) -> (PC.TContinue
(clt
),x
)
493 | PC.TGoto
(_
) -> (PC.TGoto
(clt
),x
)
494 | PC.TIdent
(s
,_
) -> (PC.TIdent
(s
,clt
),x
)
495 | PC.TTypeId
(s
,_
) -> (PC.TTypeId
(s
,clt
),x
)
496 | PC.TDeclarerId
(s
,_
) -> (PC.TDeclarerId
(s
,clt
),x
)
497 | PC.TIteratorId
(s
,_
) -> (PC.TIteratorId
(s
,clt
),x
)
499 | PC.TSizeof
(_
) -> (PC.TSizeof
(clt
),x
)
501 | PC.TString
(s
,_
) -> (PC.TString
(s
,clt
),x
)
502 | PC.TChar
(s
,_
) -> (PC.TChar
(s
,clt
),x
)
503 | PC.TFloat
(s
,_
) -> (PC.TFloat
(s
,clt
),x
)
504 | PC.TInt
(s
,_
) -> (PC.TInt
(s
,clt
),x
)
506 | PC.TOrLog
(_
) -> (PC.TOrLog
(clt
),x
)
507 | PC.TAndLog
(_
) -> (PC.TAndLog
(clt
),x
)
508 | PC.TOr
(_
) -> (PC.TOr
(clt
),x
)
509 | PC.TXor
(_
) -> (PC.TXor
(clt
),x
)
510 | PC.TAnd
(_
) -> (PC.TAnd
(clt
),x
)
511 | PC.TEqEq
(_
) -> (PC.TEqEq
(clt
),x
)
512 | PC.TNotEq
(_
) -> (PC.TNotEq
(clt
),x
)
513 | PC.TTildeEq
(_
) -> (PC.TTildeEq
(clt
),x
)
514 | PC.TSub
(_
) -> (PC.TSub
(clt
),x
)
515 | PC.TLogOp
(op
,_
) -> (PC.TLogOp
(op
,clt
),x
)
516 | PC.TShLOp
(op
,_
) -> (PC.TShLOp
(op
,clt
),x
)
517 | PC.TShROp
(op
,_
) -> (PC.TShROp
(op
,clt
),x
)
518 | PC.TPlus
(_
) -> (PC.TPlus
(clt
),x
)
519 | PC.TMinus
(_
) -> (PC.TMinus
(clt
),x
)
520 | PC.TMul
(_
) -> (PC.TMul
(clt
),x
)
521 | PC.TDmOp
(op
,_
) -> (PC.TDmOp
(op
,clt
),x
)
522 | PC.TTilde
(_
) -> (PC.TTilde
(clt
),x
)
524 | PC.TMeta
(a
,b
,_
) -> (PC.TMeta
(a
,b
,clt
),x
)
525 | PC.TMetaParam
(a
,b
,_
) -> (PC.TMetaParam
(a
,b
,clt
),x
)
526 | PC.TMetaParamList
(a
,b
,c
,_
) -> (PC.TMetaParamList
(a
,b
,c
,clt
),x
)
527 | PC.TMetaConst
(a
,b
,c
,d
,_
) -> (PC.TMetaConst
(a
,b
,c
,d
,clt
),x
)
528 | PC.TMetaErr
(a
,b
,c
,_
) -> (PC.TMetaErr
(a
,b
,c
,clt
),x
)
529 | PC.TMetaExp
(a
,b
,c
,d
,_
) -> (PC.TMetaExp
(a
,b
,c
,d
,clt
),x
)
530 | PC.TMetaIdExp
(a
,b
,c
,d
,_
) -> (PC.TMetaIdExp
(a
,b
,c
,d
,clt
),x
)
531 | PC.TMetaLocalIdExp
(a
,b
,c
,d
,_
) -> (PC.TMetaLocalIdExp
(a
,b
,c
,d
,clt
),x
)
532 | PC.TMetaExpList
(a
,b
,c
,_
) -> (PC.TMetaExpList
(a
,b
,c
,clt
),x
)
533 | PC.TMetaId
(a
,b
,c
,d
,_
) -> (PC.TMetaId
(a
,b
,c
,d
,clt
),x
)
534 | PC.TMetaType
(a
,b
,_
) -> (PC.TMetaType
(a
,b
,clt
),x
)
535 | PC.TMetaInit
(a
,b
,_
) -> (PC.TMetaInit
(a
,b
,clt
),x
)
536 | PC.TMetaInitList
(a
,b
,c
,_
) -> (PC.TMetaInitList
(a
,b
,c
,clt
),x
)
537 | PC.TMetaDecl
(a
,b
,_
) -> (PC.TMetaDecl
(a
,b
,clt
),x
)
538 | PC.TMetaField
(a
,b
,_
) -> (PC.TMetaField
(a
,b
,clt
),x
)
539 | PC.TMetaFieldList
(a
,b
,c
,_
) -> (PC.TMetaFieldList
(a
,b
,c
,clt
),x
)
540 | PC.TMetaStm
(a
,b
,_
) -> (PC.TMetaStm
(a
,b
,clt
),x
)
541 | PC.TMetaStmList
(a
,b
,_
) -> (PC.TMetaStmList
(a
,b
,clt
),x
)
542 | PC.TMetaFunc
(a
,b
,c
,_
) -> (PC.TMetaFunc
(a
,b
,c
,clt
),x
)
543 | PC.TMetaLocalFunc
(a
,b
,c
,_
) -> (PC.TMetaLocalFunc
(a
,b
,c
,clt
),x
)
545 | PC.TWhen
(_
) -> (PC.TWhen
(clt
),x
)
546 | PC.TWhenTrue
(_
) -> (PC.TWhenTrue
(clt
),x
)
547 | PC.TWhenFalse
(_
) -> (PC.TWhenFalse
(clt
),x
)
548 | PC.TAny
(_
) -> (PC.TAny
(clt
),x
)
549 | PC.TStrict
(_
) -> (PC.TStrict
(clt
),x
)
550 | PC.TEllipsis
(_
) -> (PC.TEllipsis
(clt
),x
)
552 | PC.TCircles(_) -> (PC.TCircles(clt),x)
553 | PC.TStars(_) -> (PC.TStars(clt),x)
556 | PC.TOEllipsis
(_
) -> (PC.TOEllipsis
(clt
),x
)
557 | PC.TCEllipsis
(_
) -> (PC.TCEllipsis
(clt
),x
)
558 | PC.TPOEllipsis
(_
) -> (PC.TPOEllipsis
(clt
),x
)
559 | PC.TPCEllipsis
(_
) -> (PC.TPCEllipsis
(clt
),x
)
561 | PC.TOCircles(_) -> (PC.TOCircles(clt),x)
562 | PC.TCCircles(_) -> (PC.TCCircles(clt),x)
563 | PC.TOStars(_) -> (PC.TOStars(clt),x)
564 | PC.TCStars(_) -> (PC.TCStars(clt),x)
567 | PC.TWhy
(_
) -> (PC.TWhy
(clt
),x
)
568 | PC.TDotDot
(_
) -> (PC.TDotDot
(clt
),x
)
569 | PC.TBang
(_
) -> (PC.TBang
(clt
),x
)
570 | PC.TOPar
(_
) -> (PC.TOPar
(clt
),x
)
571 | PC.TOPar0
(_
) -> (PC.TOPar0
(clt
),x
)
572 | PC.TMid0
(_
) -> (PC.TMid0
(clt
),x
)
573 | PC.TCPar
(_
) -> (PC.TCPar
(clt
),x
)
574 | PC.TCPar0
(_
) -> (PC.TCPar0
(clt
),x
)
576 | PC.TOBrace
(_
) -> (PC.TOBrace
(clt
),x
)
577 | PC.TCBrace
(_
) -> (PC.TCBrace
(clt
),x
)
578 | PC.TOCro
(_
) -> (PC.TOCro
(clt
),x
)
579 | PC.TCCro
(_
) -> (PC.TCCro
(clt
),x
)
580 | PC.TOInit
(_
) -> (PC.TOInit
(clt
),x
)
582 | PC.TPtrOp
(_
) -> (PC.TPtrOp
(clt
),x
)
584 | PC.TEq
(_
) -> (PC.TEq
(clt
),x
)
585 | PC.TAssign
(s
,_
) -> (PC.TAssign
(s
,clt
),x
)
586 | PC.TDot
(_
) -> (PC.TDot
(clt
),x
)
587 | PC.TComma
(_
) -> (PC.TComma
(clt
),x
)
588 | PC.TPtVirg
(_
) -> (PC.TPtVirg
(clt
),x
)
590 | PC.TLineEnd
(_
) -> (PC.TLineEnd
(clt
),x
)
591 | PC.TFunDecl
(_
) -> (PC.TFunDecl
(clt
),x
)
593 | _
-> failwith
"no clt"
596 (* ----------------------------------------------------------------------- *)
598 let make_name prefix ln
= Printf.sprintf
"%s starting on line %d" prefix ln
600 (* ----------------------------------------------------------------------- *)
603 let wrap_lexbuf_info lexbuf
=
604 (Lexing.lexeme lexbuf
, Lexing.lexeme_start lexbuf
)
606 let tokens_all_full token table file get_ats lexbuf end_markers
:
607 (bool * ((PC.token
* (string * (int * int) * (int * int))) list
)) =
610 let result = token lexbuf
in
611 let info = (Lexing.lexeme lexbuf
,
612 (table
.(Lexing.lexeme_start lexbuf
)),
613 (Lexing.lexeme_start lexbuf
, Lexing.lexeme_end lexbuf
)) in
617 then failwith
"unexpected end of file in a metavariable declaration"
618 else (false,[(result,info)])
619 else if List.mem
result end_markers
620 then (true,[(result,info)])
622 let (more
,rest
) = aux() in
623 (more
,(result, info)::rest
)
626 e
-> pr2 (Common.error_message file
(wrap_lexbuf_info lexbuf
) ); raise e
628 let tokens_all table file get_ats lexbuf end_markers
:
629 (bool * ((PC.token
* (string * (int * int) * (int * int))) list
)) =
630 tokens_all_full Lexer_cocci.token table file get_ats lexbuf end_markers
632 let tokens_script_all table file get_ats lexbuf end_markers
:
633 (bool * ((PC.token
* (string * (int * int) * (int * int))) list
)) =
634 tokens_all_full Lexer_script.token table file get_ats lexbuf end_markers
636 (* ----------------------------------------------------------------------- *)
637 (* Split tokens into minus and plus fragments *)
640 let (d
,_
,_
,_
,_
,_
,_
,_
) = clt
in
642 D.MINUS
| D.OPTMINUS
| D.UNIQUEMINUS
-> ([t
],[])
643 | D.PLUS
| D.PLUSPLUS
-> ([],[t
])
644 | D.CONTEXT
| D.UNIQUE
| D.OPT
-> ([t
],[t
])
646 let split_token ((tok
,_
) as t
) =
648 PC.TMetavariable
| PC.TIdentifier
649 | PC.TConstant
| PC.TExpression
| PC.TIdExpression
650 | PC.TDeclaration
| PC.TField
651 | PC.TStatement
| PC.TPosition
| PC.TPosAny
| PC.TInitialiser
652 | PC.TFunction
| PC.TTypedef
| PC.TDeclarer
| PC.TIterator
| PC.TName
653 | PC.TType
| PC.TParameter
| PC.TLocal
| PC.Tlist
| PC.TFresh
654 | PC.TCppConcatOp
| PC.TPure
655 | PC.TContext
| PC.TRuleName
(_
) | PC.TUsing
| PC.TVirtual
| PC.TDisable
656 | PC.TExtends
| PC.TPathIsoFile
(_
)
657 | PC.TDepends
| PC.TOn
| PC.TEver
| PC.TNever
| PC.TExists
| PC.TForall
658 | PC.TError
| PC.TWords
| PC.TGenerated
| PC.TNothing
-> ([t
],[t
])
660 | PC.Tchar
(clt
) | PC.Tshort
(clt
) | PC.Tint
(clt
) | PC.Tdouble
(clt
)
661 | PC.Tfloat
(clt
) | PC.Tlong
(clt
) | PC.Tvoid
(clt
)
662 | PC.Tsize_t
(clt
) | PC.Tssize_t
(clt
) | PC.Tptrdiff_t
(clt
)
664 | PC.Tunion
(clt
) | PC.Tenum
(clt
) | PC.Tunsigned
(clt
) | PC.Tsigned
(clt
)
665 | PC.Tstatic
(clt
) | PC.Tauto
(clt
) | PC.Tregister
(clt
) | PC.Textern
(clt
)
666 | PC.Tinline
(clt
) | PC.Ttypedef
(clt
) | PC.Tattr
(_
,clt
)
667 | PC.Tconst
(clt
) | PC.Tvolatile
(clt
) -> split t clt
669 | PC.TPragma
(s
,_
) -> ([],[t
]) (* only allowed in + *)
670 | PC.TPlusFile
(s
,clt
) | PC.TMinusFile
(s
,clt
)
671 | PC.TIncludeL
(s
,clt
) | PC.TIncludeNL
(s
,clt
) ->
673 | PC.TUndef
(clt
,_
) | PC.TDefine
(clt
,_
) | PC.TDefineParam
(clt
,_
,_
,_
) ->
676 | PC.TIf
(clt
) | PC.TElse
(clt
) | PC.TWhile
(clt
) | PC.TFor
(clt
) | PC.TDo
(clt
)
677 | PC.TSwitch
(clt
) | PC.TCase
(clt
) | PC.TDefault
(clt
)
679 | PC.TReturn
(clt
) | PC.TBreak
(clt
) | PC.TContinue
(clt
) | PC.TGoto
(clt
)
681 | PC.TTypeId
(_
,clt
) | PC.TDeclarerId
(_
,clt
) | PC.TIteratorId
(_
,clt
)
682 | PC.TMeta
(_
,_
,clt
) | PC.TMetaConst
(_
,_
,_
,_
,clt
) | PC.TMetaExp
(_
,_
,_
,_
,clt
)
683 | PC.TMetaIdExp
(_
,_
,_
,_
,clt
) | PC.TMetaLocalIdExp
(_
,_
,_
,_
,clt
)
684 | PC.TMetaExpList
(_
,_
,_
,clt
)
685 | PC.TMetaParam
(_
,_
,clt
) | PC.TMetaParamList
(_
,_
,_
,clt
)
686 | PC.TMetaId
(_
,_
,_
,_
,clt
) | PC.TMetaType
(_
,_
,clt
)
687 | PC.TMetaInit
(_
,_
,clt
) | PC.TMetaInitList
(_
,_
,_
,clt
)
688 | PC.TMetaDecl
(_
,_
,clt
) | PC.TMetaField
(_
,_
,clt
)
689 | PC.TMetaFieldList
(_
,_
,_
,clt
)
690 | PC.TMetaStm
(_
,_
,clt
) | PC.TMetaStmList
(_
,_
,clt
) | PC.TMetaErr
(_
,_
,_
,clt
)
691 | PC.TMetaFunc
(_
,_
,_
,clt
) | PC.TMetaLocalFunc
(_
,_
,_
,clt
)
692 | PC.TMetaDeclarer
(_
,_
,_
,clt
) | PC.TMetaIterator
(_
,_
,_
,clt
) -> split t clt
693 | PC.TMPtVirg
| PC.TArob
| PC.TArobArob
| PC.TScript
694 | PC.TInitialize
| PC.TFinalize
-> ([t
],[t
])
695 | PC.TPArob
| PC.TMetaPos
(_
,_
,_
,_
) -> ([t
],[])
698 | PC.TWhen
(clt
) | PC.TWhenTrue
(clt
) | PC.TWhenFalse
(clt
)
699 | PC.TAny
(clt
) | PC.TStrict
(clt
) | PC.TLineEnd
(clt
)
700 | PC.TEllipsis
(clt
) (* | PC.TCircles(clt) | PC.TStars(clt) *)
701 | PC.TOEllipsis
(clt
) | PC.TCEllipsis
(clt
)
702 | PC.TPOEllipsis
(clt
) | PC.TPCEllipsis
(clt
) -> split t clt
705 | PC.TOCircles(_) | PC.TCCircles(_) (* clt must be context *)
706 | PC.TOStars
(_
) | PC.TCStars
(_
) (* clt must be context *)
709 | PC.TBang0
| PC.TPlus0
| PC.TWhy0
->
712 | PC.TWhy
(clt
) | PC.TDotDot
(clt
)
713 | PC.TBang
(clt
) | PC.TOPar
(clt
) | PC.TOPar0
(clt
)
714 | PC.TMid0
(clt
) | PC.TCPar
(clt
) | PC.TCPar0
(clt
) -> split t clt
716 | PC.TInc
(clt
) | PC.TDec
(clt
) -> split t clt
718 | PC.TString
(_
,clt
) | PC.TChar
(_
,clt
) | PC.TFloat
(_
,clt
) | PC.TInt
(_
,clt
) ->
721 | PC.TOrLog
(clt
) | PC.TAndLog
(clt
) | PC.TOr
(clt
) | PC.TXor
(clt
)
722 | PC.TAnd
(clt
) | PC.TEqEq
(clt
) | PC.TNotEq
(clt
) | PC.TTildeEq
(clt
)
723 | PC.TTildeExclEq
(clt
) | PC.TSub
(clt
) | PC.TLogOp
(_
,clt
)
724 | PC.TShLOp
(_
,clt
) | PC.TShROp
(_
,clt
)
725 | PC.TPlus
(clt
) | PC.TMinus
(clt
) | PC.TMul
(clt
)
726 | PC.TDmOp
(_
,clt
) | PC.TTilde
(clt
) -> split t clt
728 | PC.TOBrace
(clt
) | PC.TCBrace
(clt
) | PC.TOInit
(clt
) -> split t clt
729 | PC.TOCro
(clt
) | PC.TCCro
(clt
) -> split t clt
731 | PC.TPtrOp
(clt
) -> split t clt
733 | PC.TEq
(clt
) | PC.TAssign
(_
,clt
) | PC.TDot
(clt
) | PC.TComma
(clt
)
734 | PC.TPtVirg
(clt
) -> split t clt
736 | PC.EOF
| PC.TInvalid
| PC.TUnderscore
-> ([t
],[t
])
738 | PC.TIso
| PC.TRightIso
739 | PC.TIsoExpression
| PC.TIsoStatement
| PC.TIsoDeclaration
| PC.TIsoType
740 | PC.TIsoTopLevel
| PC.TIsoArgExpression
| PC.TIsoTestExpression
741 | PC.TIsoToTestExpression
->
742 failwith
"unexpected tokens"
743 | PC.TScriptData s
-> ([t
],[t
])
745 let split_token_stream tokens
=
746 let rec loop = function
749 let (minus
,plus
) = split_token token
in
750 let (minus_stream
,plus_stream
) = loop tokens
in
751 (minus
@minus_stream
,plus
@plus_stream
) in
754 (* ----------------------------------------------------------------------- *)
755 (* Find function names *)
756 (* This addresses a shift-reduce problem in the parser, allowing us to
757 distinguish a function declaration from a function call even if the latter
758 has no return type. Undoubtedly, this is not very nice, but it doesn't
759 seem very convenient to refactor the grammar to get around the problem. *)
763 let rec find_function_names l
=
764 let is_ident = function
765 (PC.TIdent
(_
,clt
),info)
766 | (PC.TMeta
(_
,_
,clt
),info)
767 | (PC.TMetaId
(_
,_
,_
,_
,clt
),info)
768 | (PC.TMetaFunc
(_
,_
,_
,clt
),info)
769 | (PC.TMetaLocalFunc
(_
,_
,_
,clt
),info) -> true
771 let is_mid = function
772 (PC.TMid0
(_
),info) -> true
774 let is_par = function
775 (PC.TOPar0
(_
),info) -> true
777 let rec split acc
= function
778 [] | [_
] -> raise Irrelevant
779 | ((PC.TCPar
(_
),_
) as t1
) :: ((PC.TOBrace
(_
),_
) as t2
) :: rest
->
780 (List.rev
(t1
::acc
),(t2
::rest
))
781 | x
::xs
-> split (x
::acc
) xs
in
782 let rec balanced_name level
= function
783 [] -> raise Irrelevant
784 | (PC.TCPar0
(_
),_
)::rest
->
785 let level = level - 1 in
788 else balanced_name level rest
789 | (PC.TOPar0
(_
),_
)::rest
->
790 let level = level + 1 in
791 balanced_name level rest
792 | (PC.TArobArob
,_
)::_
| (PC.TArob
,_
)::_
| (PC.EOF
,_
)::_
->
794 | t
::rest
when is_ident t
&& level = 0 -> rest
795 | t
::rest
when is_ident t
or is_mid t
-> balanced_name level rest
796 | _
-> raise Irrelevant
in
797 let rec balanced_args level = function
798 [] -> raise Irrelevant
799 | (PC.TCPar
(_
),_
)::rest
->
800 let level = level - 1 in
803 else balanced_args level rest
804 | (PC.TOPar
(_
),_
)::rest
->
805 let level = level + 1 in
806 balanced_args level rest
807 | (PC.TArobArob
,_
)::_
| (PC.TArob
,_
)::_
| (PC.EOF
,_
)::_
->
809 | t
::rest
-> balanced_args level rest
in
810 let rec loop = function
813 if is_par t
or is_mid t
or is_ident t
817 let (bef
,aft
) = split [] (t
::rest
) in
818 let rest = balanced_name 0 bef
in
820 (PC.TOPar
(_
),_
)::_
->
821 (match balanced_args 0 rest with
823 let (_
,info) as h
= List.hd bef
in
824 let clt = get_clt h
in
825 (((PC.TFunDecl
(clt),info) :: bef
), aft
)
826 | _
-> raise Irrelevant
)
827 | _
-> raise Irrelevant
)
828 with Irrelevant
-> ([t
],rest) in
830 else t
:: (loop rest) in
833 (* ----------------------------------------------------------------------- *)
834 (* an attribute is an identifier that preceeds another identifier and
837 let rec detect_attr l
=
839 (PC.TIdent
(_
,_
),_
) | (PC.TMetaId
(_
,_
,_
,_
,_
),_
) | (PC.TMetaFunc
(_
,_
,_
,_
),_
)
840 | (PC.TMetaLocalFunc
(_
,_
,_
,_
),_
) -> true
842 let rec loop = function
845 | ((PC.TIdent
(nm
,clt),info) as t1
)::id
::rest when is_id id
->
846 if String.length nm
> 2 && String.sub nm
0 2 = "__"
847 then (PC.Tattr
(nm
,clt),info)::(loop (id
::rest))
848 else t1
::(loop (id
::rest))
849 | x
::xs
-> x
::(loop xs
) in
852 (* ----------------------------------------------------------------------- *)
853 (* Look for variable declarations where the name is a typedef name.
854 We assume that C code does not contain a multiplication as a top-level
857 (* bug: once a type, always a type, even if the same name is later intended
858 to be used as a real identifier *)
859 let detect_types in_meta_decls l
=
860 let is_delim infn
= function
861 (PC.TOEllipsis
(_
),_
) (* | (PC.TOCircles(_),_) | (PC.TOStars(_),_) *)
862 | (PC.TPOEllipsis
(_
),_
) (* | (PC.TOCircles(_),_) | (PC.TOStars(_),_) *)
863 | (PC.TEllipsis
(_
),_
) (* | (PC.TCircles(_),_) | (PC.TStars(_),_) *)
864 | (PC.TPtVirg
(_
),_
) | (PC.TOBrace
(_
),_
) | (PC.TOInit
(_
),_
)
866 | (PC.TPure
,_
) | (PC.TContext
,_
)
867 | (PC.Tstatic
(_
),_
) | (PC.Textern
(_
),_
)
868 | (PC.Tinline
(_
),_
) | (PC.Ttypedef
(_
),_
) | (PC.Tattr
(_
),_
) -> true
869 | (PC.TComma
(_
),_
) when infn
> 0 or in_meta_decls
-> true
870 | (PC.TDotDot
(_
),_
) when in_meta_decls
-> true
872 let is_choices_delim = function
873 (PC.TOBrace
(_
),_
) | (PC.TComma
(_
),_
) -> true | _
-> false in
875 (PC.TIdent
(_
,_
),_
) | (PC.TMetaId
(_
,_
,_
,_
,_
),_
) | (PC.TMetaFunc
(_
,_
,_
,_
),_
)
876 | (PC.TMetaLocalFunc
(_
,_
,_
,_
),_
) -> true
877 | (PC.TMetaParam
(_
,_
,_
),_
)
878 | (PC.TMetaParamList
(_
,_
,_
,_
),_
)
879 | (PC.TMetaConst
(_
,_
,_
,_
,_
),_
)
880 | (PC.TMetaErr
(_
,_
,_
,_
),_
)
881 | (PC.TMetaExp
(_
,_
,_
,_
,_
),_
)
882 | (PC.TMetaIdExp
(_
,_
,_
,_
,_
),_
)
883 | (PC.TMetaLocalIdExp
(_
,_
,_
,_
,_
),_
)
884 | (PC.TMetaExpList
(_
,_
,_
,_
),_
)
885 | (PC.TMetaType
(_
,_
,_
),_
)
886 | (PC.TMetaInit
(_
,_
,_
),_
)
887 | (PC.TMetaInitList
(_
,_
,_
,_
),_
)
888 | (PC.TMetaDecl
(_
,_
,_
),_
)
889 | (PC.TMetaField
(_
,_
,_
),_
)
890 | (PC.TMetaFieldList
(_
,_
,_
,_
),_
)
891 | (PC.TMetaStm
(_
,_
,_
),_
)
892 | (PC.TMetaStmList
(_
,_
,_
),_
)
893 | (PC.TMetaPos
(_
,_
,_
,_
),_
) -> in_meta_decls
895 let redo_id ident
clt v
=
896 !Data.add_type_name ident
;
897 (PC.TTypeId
(ident
,clt),v
) in
898 let rec loop start infn type_names
= function
899 (* infn: 0 means not in a function header
900 > 0 means in a function header, after infn - 1 unmatched open parens*)
902 | ((PC.TOBrace
(clt),v
)::_
) as all
when in_meta_decls
->
903 collect_choices type_names all
(* never a function header *)
904 | delim
::(PC.TIdent
(ident
,clt),v
)::((PC.TMul
(_
),_
) as x
)::rest
905 when is_delim infn delim
->
906 let newid = redo_id ident
clt v
in
907 delim
::newid::x
::(loop false infn
(ident
::type_names
) rest)
908 | delim
::(PC.TIdent
(ident
,clt),v
)::id
::rest
909 when is_delim infn delim
&& is_id id
->
910 let newid = redo_id ident
clt v
in
911 delim
::newid::id
::(loop false infn
(ident
::type_names
) rest)
912 | ((PC.TFunDecl
(_
),_
) as fn
)::rest ->
913 fn
::(loop false 1 type_names
rest)
914 | ((PC.TOPar
(_
),_
) as lp
)::rest when infn
> 0 ->
915 lp
::(loop false (infn
+ 1) type_names
rest)
916 | ((PC.TCPar
(_
),_
) as rp
)::rest when infn
> 0 ->
918 then rp
::(loop false 0 type_names
rest) (* 0 means not in fn header *)
919 else rp
::(loop false (infn
- 1) type_names
rest)
920 | (PC.TIdent
(ident
,clt),v
)::((PC.TMul
(_
),_
) as x
)::rest when start
->
921 let newid = redo_id ident
clt v
in
922 newid::x
::(loop false infn
(ident
::type_names
) rest)
923 | (PC.TIdent
(ident
,clt),v
)::id
::rest when start
&& is_id id
->
924 let newid = redo_id ident
clt v
in
925 newid::id
::(loop false infn
(ident
::type_names
) rest)
926 | (PC.TIdent
(ident
,clt),v
)::rest when List.mem ident type_names
->
927 (PC.TTypeId
(ident
,clt),v
)::(loop false infn type_names
rest)
928 | ((PC.TIdent
(ident
,clt),v
) as x
)::rest ->
929 x
::(loop false infn type_names
rest)
930 | x
::rest -> x
::(loop false infn type_names
rest)
931 and collect_choices type_names
= function
932 [] -> [] (* should happen, but let the parser detect that *)
933 | (PC.TCBrace
(clt),v
)::rest ->
934 (PC.TCBrace
(clt),v
)::(loop false 0 type_names
rest)
935 | delim
::(PC.TIdent
(ident
,clt),v
)::rest
936 when is_choices_delim delim
->
937 let newid = redo_id ident
clt v
in
938 delim
::newid::(collect_choices
(ident
::type_names
) rest)
939 | x
::rest -> x
::(collect_choices type_names
rest) in
943 (* ----------------------------------------------------------------------- *)
944 (* Insert TLineEnd tokens at the end of a line that contains a WHEN.
945 WHEN is restricted to a single line, to avoid ambiguity in eg:
949 let token2line (tok
,_
) =
951 PC.Tchar
(clt) | PC.Tshort
(clt) | PC.Tint
(clt) | PC.Tdouble
(clt)
952 | PC.Tfloat
(clt) | PC.Tlong
(clt) | PC.Tvoid
(clt)
953 | PC.Tsize_t
(clt) | PC.Tssize_t
(clt) | PC.Tptrdiff_t
(clt)
955 | PC.Tunion
(clt) | PC.Tenum
(clt) | PC.Tunsigned
(clt) | PC.Tsigned
(clt)
956 | PC.Tstatic
(clt) | PC.Tauto
(clt) | PC.Tregister
(clt) | PC.Textern
(clt)
957 | PC.Tinline
(clt) | PC.Ttypedef
(clt) | PC.Tattr
(_
,clt) | PC.Tconst
(clt)
960 | PC.TInc
(clt) | PC.TDec
(clt)
962 | PC.TIf
(clt) | PC.TElse
(clt) | PC.TWhile
(clt) | PC.TFor
(clt) | PC.TDo
(clt)
963 | PC.TSwitch
(clt) | PC.TCase
(clt) | PC.TDefault
(clt) | PC.TSizeof
(clt)
964 | PC.TReturn
(clt) | PC.TBreak
(clt) | PC.TContinue
(clt) | PC.TGoto
(clt)
966 | PC.TTypeId
(_
,clt) | PC.TDeclarerId
(_
,clt) | PC.TIteratorId
(_
,clt)
967 | PC.TMetaDeclarer
(_
,_
,_
,clt) | PC.TMetaIterator
(_
,_
,_
,clt)
969 | PC.TString
(_
,clt) | PC.TChar
(_
,clt) | PC.TFloat
(_
,clt) | PC.TInt
(_
,clt)
971 | PC.TOrLog
(clt) | PC.TAndLog
(clt) | PC.TOr
(clt) | PC.TXor
(clt)
972 | PC.TAnd
(clt) | PC.TEqEq
(clt) | PC.TNotEq
(clt) | PC.TLogOp
(_
,clt)
973 | PC.TShLOp
(_
,clt) | PC.TShROp
(_
,clt)
974 | PC.TPlus
(clt) | PC.TMinus
(clt) | PC.TMul
(clt)
975 | PC.TDmOp
(_
,clt) | PC.TTilde
(clt)
977 | PC.TMeta
(_
,_
,clt) | PC.TMetaParam
(_
,_
,clt) | PC.TMetaParamList
(_
,_
,_
,clt)
978 | PC.TMetaConst
(_
,_
,_
,_
,clt) | PC.TMetaExp
(_
,_
,_
,_
,clt)
979 | PC.TMetaIdExp
(_
,_
,_
,_
,clt) | PC.TMetaLocalIdExp
(_
,_
,_
,_
,clt)
980 | PC.TMetaExpList
(_
,_
,_
,clt)
981 | PC.TMetaId
(_
,_
,_
,_
,clt) | PC.TMetaType
(_
,_
,clt)
982 | PC.TMetaInit
(_
,_
,clt) | PC.TMetaInitList
(_
,_
,_
,clt)
983 | PC.TMetaDecl
(_
,_
,clt) | PC.TMetaField
(_
,_
,clt)
984 | PC.TMetaFieldList
(_
,_
,_
,clt)
985 | PC.TMetaStm
(_
,_
,clt) | PC.TMetaStmList
(_
,_
,clt) | PC.TMetaFunc
(_
,_
,_
,clt)
986 | PC.TMetaLocalFunc
(_
,_
,_
,clt) | PC.TMetaPos
(_
,_
,_
,clt)
989 | PC.TWhen
(clt) | PC.TWhenTrue
(clt) | PC.TWhenFalse
(clt)
990 | PC.TAny
(clt) | PC.TStrict
(clt) | PC.TEllipsis
(clt)
991 (* | PC.TCircles(clt) | PC.TStars(clt) *)
993 | PC.TOEllipsis
(clt) | PC.TCEllipsis
(clt)
994 | PC.TPOEllipsis
(clt) | PC.TPCEllipsis
(clt) (*| PC.TOCircles(clt)
995 | PC.TCCircles(clt) | PC.TOStars(clt) | PC.TCStars(clt) *)
997 | PC.TWhy
(clt) | PC.TDotDot
(clt) | PC.TBang
(clt) | PC.TOPar
(clt)
998 | PC.TOPar0
(clt) | PC.TMid0
(clt) | PC.TCPar
(clt)
1001 | PC.TOBrace
(clt) | PC.TCBrace
(clt) | PC.TOCro
(clt) | PC.TCCro
(clt)
1006 | PC.TUndef
(clt,_
) | PC.TDefine
(clt,_
) | PC.TDefineParam
(clt,_
,_
,_
)
1007 | PC.TIncludeL
(_
,clt) | PC.TIncludeNL
(_
,clt)
1009 | PC.TEq
(clt) | PC.TAssign
(_
,clt) | PC.TDot
(clt) | PC.TComma
(clt)
1010 | PC.TPtVirg
(clt) ->
1011 let (_
,line
,_
,_
,_
,_
,_
,_
) = clt in Some line
1015 let rec insert_line_end = function
1017 | (((PC.TWhen
(clt),q
) as x
)::xs
) ->
1018 x
::(find_line_end
true (token2line x
) clt q xs
)
1019 | (((PC.TUndef
(clt,_
),q
) as x
)::xs
)
1020 | (((PC.TDefine
(clt,_
),q
) as x
)::xs
)
1021 | (((PC.TDefineParam
(clt,_
,_
,_
),q
) as x
)::xs
) ->
1022 x
::(find_line_end
false (token2line x
) clt q xs
)
1023 | x
::xs
-> x
::(insert_line_end xs
)
1025 and find_line_end inwhen line
clt q
= function
1026 (* don't know what 2nd component should be so just use the info of
1027 the When. Also inherit - of when, if any *)
1028 [] -> [(PC.TLineEnd
(clt),q
)]
1029 | ((PC.TIdent
("strict",clt),a
) as x
)::xs
when token2line x
= line
->
1030 (PC.TStrict
(clt),a
) :: (find_line_end inwhen line
clt q xs
)
1031 | ((PC.TIdent
("STRICT",clt),a
) as x
)::xs
when token2line x
= line
->
1032 (PC.TStrict
(clt),a
) :: (find_line_end inwhen line
clt q xs
)
1033 | ((PC.TIdent
("any",clt),a
) as x
)::xs
when token2line x
= line
->
1034 (PC.TAny
(clt),a
) :: (find_line_end inwhen line
clt q xs
)
1035 | ((PC.TIdent
("ANY",clt),a
) as x
)::xs
when token2line x
= line
->
1036 (PC.TAny
(clt),a
) :: (find_line_end inwhen line
clt q xs
)
1037 | ((PC.TIdent
("forall",clt),a
) as x
)::xs
when token2line x
= line
->
1038 (PC.TForall
,a
) :: (find_line_end inwhen line
clt q xs
)
1039 | ((PC.TIdent
("exists",clt),a
) as x
)::xs
when token2line x
= line
->
1040 (PC.TExists
,a
) :: (find_line_end inwhen line
clt q xs
)
1041 | ((PC.TComma
(clt),a
) as x
)::xs
when token2line x
= line
->
1042 (PC.TComma
(clt),a
) :: (find_line_end inwhen line
clt q xs
)
1043 | ((PC.TPArob
,a
) as x
)::xs
-> (* no line #, just assume on the same line *)
1044 x
:: (find_line_end inwhen line
clt q xs
)
1045 | x
::xs
when token2line x
= line
-> x
:: (find_line_end inwhen line
clt q xs
)
1046 | xs
-> (PC.TLineEnd
(clt),q
)::(insert_line_end xs
)
1048 let rec translate_when_true_false = function
1050 | (PC.TWhen
(clt),q
)::((PC.TNotEq
(_
),_
) as x
)::(PC.TIdent
("true",_
),_
)::xs
->
1051 (PC.TWhenTrue
(clt),q
)::x
::(translate_when_true_false xs
)
1052 | (PC.TWhen
(clt),q
)::((PC.TNotEq
(_
),_
) as x
)::(PC.TIdent
("false",_
),_
)::xs
->
1053 (PC.TWhenFalse
(clt),q
)::x
::(translate_when_true_false xs
)
1054 | x
::xs
-> x
:: (translate_when_true_false xs
)
1056 (* ----------------------------------------------------------------------- *)
1058 (* In a nest, if the nest is -, all of the nested code must also be -.
1059 All are converted to context, because the next takes care of the -. *)
1060 let check_nests tokens
=
1062 let (line_type,a
,b
,c
,d
,e
,f
,g
) = get_clt t
in
1063 List.mem
line_type [D.MINUS
;D.OPTMINUS
;D.UNIQUEMINUS
] in
1065 let clt = try Some
(get_clt t
) with Failure _
-> None
in
1067 Some
(line_type,a
,b
,c
,d
,e
,f
,g
) ->
1068 (match line_type with
1069 D.MINUS
-> update_clt t
(D.CONTEXT
,a
,b
,c
,d
,e
,f
,g
)
1070 | D.OPTMINUS
-> update_clt t
(D.OPT
,a
,b
,c
,d
,e
,f
,g
)
1071 | D.UNIQUEMINUS
-> update_clt t
(D.UNIQUE
,a
,b
,c
,d
,e
,f
,g
)
1072 | _
-> failwith
"minus token expected")
1074 let rec outside = function
1076 | ((PC.TPOEllipsis
(clt),q
) as t
)::r
when is_minus t
-> t
:: inside
0 r
1077 | t
::r
-> t
:: outside r
1078 and inside stack
= function
1079 [] -> failwith
"missing nest end"
1080 | ((PC.TPCEllipsis
(clt),q
) as t
)::r
->
1082 :: (if stack
= 0 then outside r
else inside
(stack
- 1) r
)
1083 | ((PC.TPOEllipsis
(clt),q
) as t
)::r
->
1084 (drop_minus t
) :: (inside
(stack
+ 1) r
)
1085 | t
:: r
-> (drop_minus t
) :: (inside stack r
) in
1088 let check_parentheses tokens
=
1089 let clt2line (_
,line
,_
,_
,_
,_
,_
,_
) = line
in
1090 let rec loop seen_open
= function
1092 | (PC.TOPar
(clt),q
) :: rest
1093 | (PC.TDefineParam
(clt,_
,_
,_
),q
) :: rest ->
1094 loop (Common.Left
(clt2line clt) :: seen_open
) rest
1095 | (PC.TOPar0
(clt),q
) :: rest ->
1096 loop (Common.Right
(clt2line clt) :: seen_open
) rest
1097 | (PC.TCPar
(clt),q
) :: rest ->
1098 (match seen_open
with
1102 "unexpected close parenthesis in line %d\n" (clt2line clt))
1103 | Common.Left _
:: seen_open
-> loop seen_open
rest
1104 | Common.Right open_line
:: _
->
1107 "disjunction parenthesis in line %d column 0 matched to normal parenthesis on line %d\n" open_line
(clt2line clt)))
1108 | (PC.TCPar0
(clt),q
) :: rest ->
1109 (match seen_open
with
1113 "unexpected close parenthesis in line %d\n" (clt2line clt))
1114 | Common.Right _
:: seen_open
-> loop seen_open
rest
1115 | Common.Left open_line
:: _
->
1118 "normal parenthesis in line %d matched to disjunction parenthesis on line %d column 0\n" open_line
(clt2line clt)))
1119 | x
::rest -> loop seen_open
rest in
1122 (* ----------------------------------------------------------------------- *)
1123 (* top level initializers: a sequence of braces followed by a dot *)
1125 let find_top_init tokens
=
1127 (PC.TOBrace
(clt),q
) :: rest ->
1128 let rec dot_start acc
= function
1129 ((PC.TOBrace
(_
),_
) as x
) :: rest ->
1130 dot_start (x
::acc
) rest
1131 | ((PC.TDot
(_
),_
) :: rest) as x
->
1132 Some
((PC.TOInit
(clt),q
) :: (List.rev acc
) @ x
)
1134 let rec comma_end acc
= function
1135 ((PC.TCBrace
(_
),_
) as x
) :: rest ->
1136 comma_end (x
::acc
) rest
1137 | ((PC.TComma
(_
),_
) :: rest) as x
->
1138 Some
((PC.TOInit
(clt),q
) :: (List.rev x
) @ acc
)
1140 (match dot_start [] rest with
1143 (match List.rev
rest with
1144 (* not super sure what this does, but EOF, @, and @@ should be
1145 the same, markind the end of a rule *)
1146 ((PC.EOF
,_
) as x
)::rest | ((PC.TArob
,_
) as x
)::rest
1147 | ((PC.TArobArob
,_
) as x
)::rest ->
1148 (match comma_end [x
] rest with
1152 failwith
"unexpected empty token list"))
1155 (* ----------------------------------------------------------------------- *)
1156 (* Integrate pragmas into some adjacent token. + tokens are preferred. Dots
1159 let rec collect_all_pragmas collected
= function
1160 (PC.TPragma
(s
,(_
,line
,logical_line
,offset
,col
,_
,_
,pos
)),_
)::rest ->
1162 { Ast0.line_start
= line
; Ast0.line_end
= line
;
1163 Ast0.logical_start
= logical_line
; Ast0.logical_end
= logical_line
;
1164 Ast0.column
= col
; Ast0.offset
= offset
; } in
1165 collect_all_pragmas ((s
,i)::collected
) rest
1166 | l
-> (List.rev collected
,l
)
1168 let rec collect_pass = function
1171 match plus_attachable false x
with
1173 let (pass
,rest) = collect_pass xs
in
1177 let plus_attach strict
= function
1179 | Some x
-> plus_attachable strict x
1181 let add_bef = function Some x
-> [x
] | None
-> []
1183 (*skips should be things like line end
1184 skips is things before pragmas that can't be attached to, pass is things
1185 after. pass is used immediately. skips accumulates.
1186 When stuff is added before some + code, the logical line of the + code
1187 becomes that of the pragma. context_neg relies on things that are adjacent
1188 having sequential logical lines. Not sure that this is good enough,
1189 as it might result in later gaps in the logical lines... *)
1190 let rec process_pragmas bef skips
= function
1191 [] -> add_bef bef
@ List.rev skips
1192 | ((PC.TPragma
(s
,i),_
)::_
) as l
->
1193 let (pragmas
,rest) = collect_all_pragmas [] l
in
1194 let (pass
,rest0
) = collect_pass rest in
1195 let (_
,_
,prag_lline
,_
,_
,_
,_
,_
) = i in
1197 match rest0
with [] -> (None
,[]) | next
::rest -> (Some next
,rest) in
1198 (match (bef
,plus_attach true bef
,next
,plus_attach true next
) with
1199 (Some bef
,PLUS
,_
,_
) ->
1200 let (a
,b
,c
,d
,e
,strbef
,straft
,pos
) = get_clt bef
in
1201 (update_clt bef
(a
,b
,c
,d
,e
,strbef
,pragmas
,pos
))::List.rev skips
@
1202 pass
@process_pragmas None
[] rest0
1203 | (_
,_
,Some next
,PLUS
) ->
1204 let (a
,b
,lline
,d
,e
,strbef
,straft
,pos
) = get_clt next
in
1205 (add_bef bef
) @ List.rev skips
@ pass
@
1207 (Some
(update_clt next
(a
,b
,prag_lline
,d
,e
,pragmas
,straft
,pos
)))
1210 (match (bef
,plus_attach false bef
,next
,plus_attach false next
) with
1211 (Some bef
,PLUS
,_
,_
) ->
1212 let (a
,b
,c
,d
,e
,strbef
,straft
,pos
) = get_clt bef
in
1213 (update_clt bef
(a
,b
,c
,d
,e
,strbef
,pragmas
,pos
))::List.rev skips
@
1214 pass
@process_pragmas None
[] rest0
1215 | (_
,_
,Some next
,PLUS
) ->
1216 let (a
,b
,lline
,d
,e
,strbef
,straft
,pos
) = get_clt next
in
1217 (add_bef bef
) @ List.rev skips
@ pass
@
1220 (update_clt next
(a
,b
,prag_lline
,d
,e
,pragmas
,straft
,pos
)))
1222 | _
-> failwith
"nothing to attach pragma to"))
1224 (match plus_attachable false x
with
1225 SKIP
-> process_pragmas bef
(x
::skips
) xs
1226 | _
-> (add_bef bef
) @ List.rev skips
@ (process_pragmas (Some x
) [] xs
))
1228 (* ----------------------------------------------------------------------- *)
1229 (* Drop ... ... . This is only allowed in + code, and arises when there is
1230 some - code between the ... *)
1231 (* drop whens as well - they serve no purpose in + code and they cause
1232 problems for drop_double_dots *)
1234 let rec drop_when = function
1236 | (PC.TWhen
(clt),info)::xs
->
1237 let rec loop = function
1239 | (PC.TLineEnd
(_
),info)::xs
-> drop_when xs
1240 | x
::xs
-> loop xs
in
1242 | x
::xs
-> x
::drop_when xs
1244 (* instead of dropping the double dots, we put TNothing in between them.
1245 these vanish after the parser, but keeping all the ...s in the + code makes
1246 it easier to align the + and - code in context_neg and in preparation for the
1247 isomorphisms. This shouldn't matter because the context code of the +
1248 slice is mostly ignored anyway *)
1249 let minus_to_nothing l
=
1250 (* for cases like | <..., which may or may not arise from removing minus
1251 code, depending on whether <... is a statement or expression *)
1254 let (d
,_
,_
,_
,_
,_
,_
,_
) = get_clt tok
in
1256 D.MINUS
| D.OPTMINUS
| D.UNIQUEMINUS
-> true
1257 | D.PLUS
| D.PLUSPLUS
-> false
1258 | D.CONTEXT
| D.UNIQUE
| D.OPT
-> false)
1260 let rec minus_loop = function
1262 | (d
::ds
) as l
-> if is_minus d
then minus_loop ds
else l
in
1263 let rec loop = function
1265 | ((PC.TMid0
(clt),i) as x
)::t1
::ts
when is_minus t1
->
1266 (match minus_loop ts
with
1267 ((PC.TOEllipsis
(_
),_
)::_
) | ((PC.TPOEllipsis
(_
),_
)::_
)
1268 | ((PC.TEllipsis
(_
),_
)::_
) as l
-> x
::(PC.TNothing
,i)::(loop l
)
1270 | t
::ts
-> t
::(loop ts
) in
1273 let rec drop_double_dots l
=
1274 let start = function
1275 (PC.TOEllipsis
(_
),_
) | (PC.TPOEllipsis
(_
),_
)
1276 (* | (PC.TOCircles(_),_) | (PC.TOStars(_),_) *) ->
1279 let middle = function
1280 (PC.TEllipsis
(_
),_
) (* | (PC.TCircles(_),_) | (PC.TStars(_),_) *) -> true
1282 let whenline = function
1283 (PC.TLineEnd
(_
),_
) -> true
1284 (*| (PC.TMid0(_),_) -> true*)
1286 let final = function
1287 (PC.TCEllipsis
(_
),_
) | (PC.TPCEllipsis
(_
),_
)
1288 (* | (PC.TCCircles(_),_) | (PC.TCStars(_),_) *) ->
1291 let any_before x
= start x
or middle x
or final x
or whenline x
in
1292 let any_after x
= start x
or middle x
or final x
in
1293 let rec loop ((_
,i) as prev
) = function
1295 | x
::rest when any_before prev
&& any_after x
->
1296 (PC.TNothing
,i)::x
::(loop x
rest)
1297 | ((PC.TComma
(_
),_
) as c
)::x
::rest when any_before prev
&& any_after x
->
1298 c
::(PC.TNothing
,i)::x
::(loop x
rest)
1299 | x
::rest -> x
:: (loop x
rest) in
1302 | (x
::xs
) -> x
:: loop x xs
1306 if l
= cur then l
else fix f
cur
1308 (* ( | ... | ) also causes parsing problems *)
1312 let rec drop_empty_thing starter
middle ender
= function
1314 | hd
::rest when starter hd
->
1315 let rec loop = function
1316 x
::rest when middle x
-> loop rest
1317 | x
::rest when ender x
-> rest
1318 | _
-> raise Not_empty
in
1319 (match try Some
(loop rest) with Not_empty
-> None
with
1320 Some x
-> drop_empty_thing starter
middle ender x
1321 | None
-> hd
:: drop_empty_thing starter
middle ender
rest)
1322 | x
::rest -> x
:: drop_empty_thing starter
middle ender
rest
1326 (function (PC.TOPar0
(_
),_
) -> true | _
-> false)
1327 (function (PC.TMid0
(_
),_
) -> true | _
-> false)
1328 (function (PC.TCPar0
(_
),_
) -> true | _
-> false)
1330 let drop_empty_nest = drop_empty_thing
1332 (* ----------------------------------------------------------------------- *)
1335 let get_s_starts (_
, (s
,_
,(starts
, ends
))) =
1336 Printf.printf
"%d %d\n" starts ends
; (s
, starts
)
1339 let v = List.hd
!l
in
1344 PC.reinit (function _
-> PC.TArobArob
(* a handy token *))
1345 (Lexing.from_function
1346 (function buf
-> function n
-> raise
Common.Impossible
))
1348 let parse_one str parsefn file toks
=
1349 let all_tokens = ref toks
in
1350 let cur_tok = ref (List.hd
!all_tokens) in
1352 let lexer_function _
=
1353 let (v, info) = pop2 all_tokens in
1354 cur_tok := (v, info);
1358 Lexing.from_function
1359 (function buf
-> function n
-> raise
Common.Impossible
)
1364 try parsefn
lexer_function lexbuf_fake
1366 Lexer_cocci.Lexical s
->
1368 (Printf.sprintf
"%s: lexical error: %s\n =%s\n" str s
1369 (Common.error_message file
(get_s_starts !cur_tok) ))
1370 | Parser_cocci_menhir.Error
->
1372 (Printf.sprintf
"%s: parse error: \n = %s\n" str
1373 (Common.error_message file
(get_s_starts !cur_tok) ))
1374 | Semantic_cocci.Semantic s
->
1376 (Printf.sprintf
"%s: semantic error: %s\n =%s\n" str s
1377 (Common.error_message file
(get_s_starts !cur_tok) ))
1381 let prepare_tokens tokens
=
1383 (translate_when_true_false (* after insert_line_end *)
1386 (find_function_names
1389 (check_parentheses tokens
)))))))
1391 let prepare_mv_tokens tokens
=
1392 detect_types false (detect_attr tokens
)
1394 let rec consume_minus_positions = function
1396 | ((PC.TOPar0
(_
),_
) as x
)::xs
| ((PC.TCPar0
(_
),_
) as x
)::xs
1397 | ((PC.TMid0
(_
),_
) as x
)::xs
-> x
::consume_minus_positions xs
1398 | x
::(PC.TPArob
,_
)::(PC.TMetaPos
(name
,constraints
,per
,clt),_
)::xs
->
1399 let (arity
,ln
,lln
,offset
,col
,strbef
,straft
,pos
) = get_clt x
in
1400 let name = Parse_aux.clt2mcode
name clt in
1403 (arity
,ln
,lln
,offset
,col
,strbef
,straft
,
1404 (Ast0.MetaPos
(name,constraints
,per
)::pos
)) in
1405 (consume_minus_positions (x::xs
))
1406 | x::xs
-> x::consume_minus_positions xs
1408 let any_modif rule
=
1410 match Ast0.get_mcode_mcodekind
x with
1411 Ast0.MINUS _
| Ast0.PLUS _
-> true
1413 let donothing r k e
= k e
in
1414 let bind x y
= x or y
in
1415 let option_default = false in
1417 V0.flat_combiner
bind option_default
1418 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
1419 donothing donothing donothing donothing donothing donothing
1420 donothing donothing donothing donothing donothing donothing donothing
1421 donothing donothing in
1422 List.exists
fn.VT0.combiner_rec_top_level rule
1424 let eval_virt virt
=
1427 if not
(List.mem
x virt
)
1428 then raise
(Bad_virt
x))
1429 !Flag.defined_virtual_rules
1431 let drop_last extra l
= List.rev
(extra
@(List.tl
(List.rev l
)))
1433 let partition_either l
=
1434 let rec part_either left right
= function
1435 | [] -> (List.rev left
, List.rev right
)
1438 | Common.Left e
-> part_either (e
:: left
) right l
1439 | Common.Right e
-> part_either left
(e
:: right
) l
) in
1442 let get_metavars parse_fn table file lexbuf
=
1443 let rec meta_loop acc
(* read one decl at a time *) =
1447 tokens_all table file
true lexbuf
[PC.TArobArob
;PC.TMPtVirg
]) in
1448 let tokens = prepare_mv_tokens tokens in
1450 [(PC.TArobArob
,_
)] -> List.rev acc
1452 let metavars = parse_one "meta" parse_fn file
tokens in
1453 meta_loop (metavars@acc
) in
1454 partition_either (meta_loop [])
1456 let get_script_metavars parse_fn table file lexbuf
=
1457 let rec meta_loop acc
=
1459 tokens_all table file
true lexbuf
[PC.TArobArob
; PC.TMPtVirg
] in
1460 let tokens = prepare_tokens tokens in
1462 [(PC.TArobArob
, _
)] -> List.rev acc
1464 let metavar = parse_one "scriptmeta" parse_fn file
tokens in
1465 meta_loop (metavar :: acc
)
1469 let get_rule_name parse_fn starts_with_name get_tokens file prefix
=
1470 Data.in_rule_name
:= true;
1471 let mknm _
= make_name prefix
(!Lexer_cocci.line
) in
1475 let (_
,tokens) = get_tokens
[PC.TArob
] in
1476 let check_name = function
1477 None
-> Some
(mknm())
1479 (if List.mem nm
reserved_names
1480 then failwith
(Printf.sprintf
"invalid name %s\n" nm
));
1482 match parse_one "rule name" parse_fn file
tokens with
1483 Ast.CocciRulename
(nm
,a
,b
,c
,d
,e
) ->
1484 Ast.CocciRulename
(check_name nm
,a
,b
,c
,d
,e
)
1485 | Ast.GeneratedRulename
(nm
,a
,b
,c
,d
,e
) ->
1486 Ast.GeneratedRulename
(check_name nm
,a
,b
,c
,d
,e
)
1487 | Ast.ScriptRulename
(nm
,s
,deps
) ->
1488 Ast.ScriptRulename
(check_name nm
,s
,deps
)
1489 | Ast.InitialScriptRulename
(_
,s
,deps
) ->
1490 Ast.InitialScriptRulename
(check_name None
,s
,deps
)
1491 | Ast.FinalScriptRulename
(_
,s
,deps
) ->
1492 Ast.FinalScriptRulename
(check_name None
,s
,deps
)
1494 Ast.CocciRulename
(Some
(mknm()),Ast.NoDep
,[],[],Ast.Undetermined
,false) in
1495 Data.in_rule_name
:= false;
1498 let parse_iso file
=
1499 let table = Common.full_charpos_to_pos file
in
1500 Common.with_open_infile file
(fun channel
->
1501 let lexbuf = Lexing.from_channel channel
in
1502 let get_tokens = tokens_all table file
false lexbuf in
1504 match get_tokens [PC.TArobArob
;PC.TArob
] with
1506 let parse_start start =
1507 let rev = List.rev start in
1508 let (arob
,_
) = List.hd
rev in
1509 (arob
= PC.TArob
,List.rev(List.tl
rev)) in
1510 let (starts_with_name
,start) = parse_start start in
1511 let rec loop starts_with_name
start =
1512 (!Data.init_rule
)();
1513 (* get metavariable declarations - have to be read before the
1515 let (rule_name
,_
,_
,_
,_
,_
) =
1516 match get_rule_name PC.iso_rule_name starts_with_name
get_tokens
1517 file
("iso file "^file
) with
1518 Ast.CocciRulename
(Some n
,a
,b
,c
,d
,e
) -> (n
,a
,b
,c
,d
,e
)
1519 | _
-> failwith
"Script rules cannot appear in isomorphism rules"
1521 Ast0.rule_name
:= rule_name
;
1523 match get_metavars PC.iso_meta_main
table file
lexbuf with
1524 (iso_metavars,[]) -> iso_metavars
1525 | _
-> failwith
"unexpected inheritance in iso" in
1529 [PC.TIsoStatement
;PC.TIsoExpression
;PC.TIsoArgExpression
;
1530 PC.TIsoTestExpression
; PC.TIsoToTestExpression
;
1531 PC.TIsoDeclaration
;PC.TIsoType
;PC.TIsoTopLevel
] in
1532 let next_start = List.hd
(List.rev tokens) in
1533 let dummy_info = ("",(-1,-1),(-1,-1)) in
1534 let tokens = drop_last [(PC.EOF
,dummy_info)] tokens in
1535 let tokens = prepare_tokens (start@tokens) in
1537 print_tokens "iso tokens" tokens;
1539 let entry = parse_one "iso main" PC.iso_main file
tokens in
1540 let entry = List.map
(List.map
Test_exps.process_anything
) entry in
1542 then (* The code below allows a header like Statement list,
1543 which is more than one word. We don't have that any more,
1544 but the code is left here in case it is put back. *)
1545 match get_tokens [PC.TArobArob
;PC.TArob
] with
1547 let (starts_with_name
,start) = parse_start start in
1548 (iso_metavars,entry,rule_name
) ::
1549 (loop starts_with_name
(next_start::start))
1550 | _
-> failwith
"isomorphism ends early"
1551 else [(iso_metavars,entry,rule_name
)] in
1552 loop starts_with_name
start
1553 | (false,_
) -> [] in
1556 let parse_iso_files existing_isos iso_files extra_path
=
1557 let get_names = List.map
(function (_
,_
,nm
) -> nm
) in
1558 let old_names = get_names existing_isos
in
1559 Data.in_iso
:= true;
1562 (function (prev
,names
) ->
1564 Lexer_cocci.init
();
1567 Common.Left
(fl
) -> Filename.concat extra_path fl
1568 | Common.Right
(fl
) -> Filename.concat
Config.path fl
in
1569 let current = parse_iso file in
1570 let new_names = get_names current in
1571 if List.exists
(function x -> List.mem
x names
) new_names
1572 then failwith
(Printf.sprintf
"repeated iso name found in %s" file);
1573 (current::prev
,new_names @ names
))
1574 ([],old_names) iso_files
in
1575 Data.in_iso
:= false;
1576 existing_isos
@(List.concat
(List.rev res))
1578 (* None = dependency not satisfied
1579 Some dep = dependency satisfied or unknown and dep has virts optimized
1581 let eval_depend dep virt
=
1584 Ast.Dep req
| Ast.EverDep req
->
1585 if List.mem req virt
1587 if List.mem req
!Flag.defined_virtual_rules
1591 | Ast.AntiDep antireq
| Ast.NeverDep antireq
->
1592 if List.mem antireq virt
1594 if not
(List.mem antireq
!Flag.defined_virtual_rules
)
1598 | Ast.AndDep
(d1
,d2
) ->
1599 (match (loop d1
, loop d2
) with
1600 (None
,_
) | (_
,None
) -> None
1601 | (Some
Ast.NoDep
,x) | (x,Some
Ast.NoDep
) -> x
1602 | (Some
x,Some y
) -> Some
(Ast.AndDep
(x,y
)))
1603 | Ast.OrDep
(d1
,d2
) ->
1604 (match (loop d1
, loop d2
) with
1606 | (Some
Ast.NoDep
,x) | (x,Some
Ast.NoDep
) -> Some
Ast.NoDep
1607 | (None
,x) | (x,None
) -> x
1608 | (Some
x,Some y
) -> Some
(Ast.OrDep
(x,y
)))
1609 | Ast.NoDep
| Ast.FailDep
-> Some dep
1615 let rec parse_loop file =
1616 Lexer_cocci.include_init
();
1617 let table = Common.full_charpos_to_pos
file in
1618 Common.with_open_infile
file (fun channel
->
1619 let lexbuf = Lexing.from_channel channel
in
1620 let get_tokens = tokens_all table file false lexbuf in
1621 Data.in_prolog
:= true;
1622 let initial_tokens = get_tokens [PC.TArobArob
;PC.TArob
] in
1623 Data.in_prolog
:= false;
1625 match initial_tokens with
1627 (match List.rev data
with
1628 ((PC.TArobArob
as x),_
)::_
| ((PC.TArob
as x),_
)::_
->
1629 let include_and_iso_files =
1630 parse_one "include and iso file names" PC.include_main
file data
in
1632 let (include_files
,iso_files
,virt
) =
1634 (function (include_files
,iso_files
,virt
) ->
1636 Data.Include s
-> (s
::include_files
,iso_files
,virt
)
1637 | Data.Iso s
-> (include_files
,s
::iso_files
,virt
)
1638 | Data.Virt l
-> (include_files
,iso_files
,l
@virt
))
1639 ([],[],[]) include_and_iso_files in
1641 List.iter
(function x -> Hashtbl.add
Lexer_cocci.rule_names
x ())
1644 let (extra_iso_files
, extra_rules
, extra_virt
, extra_metas
) =
1645 let rec loop = function
1647 | (a
,b
,c
,d
)::rest ->
1648 let (x,y
,z
,zz
) = loop rest in
1649 (a
::x,b
::y
,c
::z
,d
@zz
) in
1650 loop (List.map
parse_loop include_files
) in
1652 let parse_cocci_rule ruletype old_metas
1653 (rule_name
, dependencies
, iso
, dropiso
, exists
, is_expression
) =
1654 let dropiso = !Flag_parsing_cocci.disabled_isos
@ dropiso in
1655 Ast0.rule_name
:= rule_name
;
1656 Data.inheritable_positions
:=
1657 rule_name
:: !Data.inheritable_positions
;
1659 (* get metavariable declarations *)
1660 let (metavars, inherited_metavars
) =
1661 get_metavars PC.meta_main
table file lexbuf in
1662 Hashtbl.add
Data.all_metadecls rule_name
metavars;
1663 Hashtbl.add
Lexer_cocci.rule_names rule_name
();
1664 Hashtbl.add
Lexer_cocci.all_metavariables rule_name
1666 (fun key
v rest -> (key
,v)::rest)
1667 Lexer_cocci.metavariables
[]);
1669 (* get transformation rules *)
1670 let (more
, tokens) = get_tokens [PC.TArobArob
; PC.TArob
] in
1671 let (minus_tokens
, _
) = split_token_stream tokens in
1672 let (_
, plus_tokens
) =
1673 split_token_stream (minus_to_nothing tokens) in
1676 print_tokens "minus tokens" minus_tokens;
1677 print_tokens "plus tokens" plus_tokens;
1680 let minus_tokens = consume_minus_positions minus_tokens in
1681 let minus_tokens = prepare_tokens minus_tokens in
1682 let plus_tokens = prepare_tokens plus_tokens in
1685 print_tokens "minus tokens" minus_tokens;
1686 print_tokens "plus tokens" plus_tokens;
1690 process_pragmas None
[]
1691 (fix (function x -> drop_double_dots (drop_empty_or x))
1692 (drop_when plus_tokens)) in
1694 print_tokens "plus tokens" plus_tokens;
1695 Printf.printf "before minus parse\n";
1699 then parse_one "minus" PC.minus_exp_main
file minus_tokens
1700 else parse_one "minus" PC.minus_main
file minus_tokens in
1702 Unparse_ast0.unparse minus_res;
1703 Printf.printf "before plus parse\n";
1706 (* put ignore_patch_or_match with * case, which is less
1708 if !Flag.sgrep_mode2
or !D.ignore_patch_or_match
1709 then (* not actually used for anything, except context_neg *)
1711 (Iso_pattern.rebuild_mcode None
).VT0.rebuilder_rec_top_level
1715 then parse_one "plus" PC.plus_exp_main
file plus_tokens
1716 else parse_one "plus" PC.plus_main
file plus_tokens in
1718 Unparse_ast0.unparse plus_res;
1719 Printf.printf "after plus parse\n";
1722 (if not
!Flag.sgrep_mode2
&&
1723 (any_modif minus_res or any_modif plus_res) &&
1724 not
(dependencies
= Ast.FailDep
)
1725 then Data.inheritable_positions
:= []);
1727 Check_meta.check_meta rule_name old_metas inherited_metavars
1728 metavars minus_res plus_res;
1730 (more
, Ast0.CocciRule
((minus_res, metavars,
1731 (iso
, dropiso, dependencies
, rule_name
, exists
)),
1732 (plus_res, metavars), ruletype
), metavars, tokens) in
1734 let rec collect_script_tokens = function
1735 [(PC.EOF
,_
)] | [(PC.TArobArob
,_
)] | [(PC.TArob
,_
)] -> ""
1736 | (PC.TScriptData
(s
),_
)::xs
-> s^
(collect_script_tokens xs
)
1740 Printf.printf
"%s\n" (token2c x))
1742 failwith
"Malformed script rule" in
1744 let parse_script_rule name language old_metas deps
=
1745 let get_tokens = tokens_script_all table file false lexbuf in
1747 (* meta-variables *)
1751 get_script_metavars PC.script_meta_main
table file lexbuf) in
1752 let (metavars,script_metavars
) =
1754 (function (metavars,script_metavars
) ->
1756 (script_var
,Some
(parent
,var
)) ->
1757 ((script_var
,parent
,var
) :: metavars, script_metavars
)
1758 | ((Some script_var
,None
),None
) ->
1759 (metavars, (name,script_var
) :: script_metavars
)
1760 | _
-> failwith
"not possible")
1762 let metavars = List.rev metavars in
1763 let script_metavars = List.rev script_metavars in
1765 Hashtbl.add
Data.all_metadecls
name
1766 (List.map
(function x -> Ast.MetaIdDecl
(Ast.NONE
,x))
1768 Hashtbl.add
Lexer_cocci.rule_names
name ();
1769 (*TODOHashtbl.add Lexer_cocci.all_metavariables name script_metavars;*)
1772 let exists_in old_metas (py,(r,m)) =
1774 let test (rr,mr) x =
1775 let (ro,vo) = Ast.get_meta_name x in
1776 ro = rr && vo = mr in
1777 List.exists (test (r,m)) old_metas in
1781 let meta2c (r,n) = Printf.sprintf "%s.%s" r n in
1782 if not (exists_in old_metas x) then
1785 "Script references unknown meta-variable: %s"
1790 let (more
, tokens) = get_tokens [PC.TArobArob
; PC.TArob
] in
1791 let data = collect_script_tokens tokens in
1793 Ast0.ScriptRule
(name, language
, deps
, metavars,
1794 script_metavars, data),
1797 let parse_if_script_rule k
name language _ deps
=
1798 let get_tokens = tokens_script_all table file false lexbuf in
1801 let (more
, tokens) = get_tokens [PC.TArobArob
; PC.TArob
] in
1802 let data = collect_script_tokens tokens in
1803 (more
,k
(name, language
, deps
, data),[],tokens) in
1805 let parse_iscript_rule =
1806 parse_if_script_rule
1807 (function (name,language
,deps
,data) ->
1808 Ast0.InitialScriptRule
(name,language
,deps
,data)) in
1810 let parse_fscript_rule =
1811 parse_if_script_rule
1812 (function (name,language
,deps
,data) ->
1813 Ast0.FinalScriptRule
(name,language
,deps
,data)) in
1815 let do_parse_script_rule fn name l old_metas deps
=
1816 match eval_depend deps virt
with
1817 Some deps
-> fn name l old_metas deps
1818 | None
-> fn name l old_metas
Ast.FailDep
in
1820 let parse_rule old_metas starts_with_name
=
1822 get_rule_name PC.rule_name starts_with_name
get_tokens file
1825 Ast.CocciRulename
(Some s
, dep
, b
, c
, d
, e
) ->
1826 (match eval_depend dep virt
with
1828 parse_cocci_rule Ast.Normal old_metas
(s
,dep
,b
,c
,d
,e
)
1830 D.ignore_patch_or_match
:= true;
1832 parse_cocci_rule Ast.Normal old_metas
1833 (s
, Ast.FailDep
, b
, c
, d
, e
) in
1834 D.ignore_patch_or_match
:= false;
1836 | Ast.GeneratedRulename
(Some s
, dep
, b
, c
, d
, e
) ->
1837 (match eval_depend dep virt
with
1839 Data.in_generating
:= true;
1841 parse_cocci_rule Ast.Generated old_metas
1843 Data.in_generating
:= false;
1846 D.ignore_patch_or_match
:= true;
1847 Data.in_generating
:= true;
1849 parse_cocci_rule Ast.Generated old_metas
1850 (s
, Ast.FailDep
, b
, c
, d
, e
) in
1851 D.ignore_patch_or_match
:= false;
1852 Data.in_generating
:= false;
1854 | Ast.ScriptRulename
(Some s
,l
,deps
) ->
1855 do_parse_script_rule parse_script_rule s l old_metas deps
1856 | Ast.InitialScriptRulename
(Some s
,l
,deps
) ->
1857 do_parse_script_rule parse_iscript_rule s l old_metas deps
1858 | Ast.FinalScriptRulename
(Some s
,l
,deps
) ->
1859 do_parse_script_rule parse_fscript_rule s l old_metas deps
1860 | _
-> failwith
"Malformed rule name" in
1862 let rec loop old_metas starts_with_name
=
1863 (!Data.init_rule
)();
1865 let gen_starts_with_name more
tokens =
1867 (match List.hd
(List.rev tokens) with
1868 (PC.TArobArob
,_
) -> false
1869 | (PC.TArob
,_
) -> true
1870 | _
-> failwith
"unexpected token")
1873 let (more
, rule
, metavars, tokens) =
1874 parse_rule old_metas starts_with_name
in
1875 let all_metas = metavars @ old_metas
in
1878 let (all_rules
,all_metas) =
1879 loop all_metas (gen_starts_with_name more
tokens) in
1880 (rule
::all_rules
,all_metas)
1881 else ([rule
],all_metas) in
1883 let (all_rules
,all_metas) =
1884 loop extra_metas
(x = PC.TArob
) in
1887 (function prev
-> function cur -> Common.union_set
cur prev
)
1888 iso_files extra_iso_files
,
1889 (* included rules first *)
1890 List.fold_left
(function prev
-> function cur -> cur@prev
)
1891 all_rules
(List.rev extra_rules
),
1892 List.fold_left
(@) virt extra_virt
(*no dups allowed*),
1893 (all_metas : 'a list
))
1894 | _
-> failwith
"unexpected code before the first rule\n")
1895 | (false,[(PC.TArobArob
,_
)]) | (false,[(PC.TArob
,_
)]) ->
1896 ([],([] : Ast0.parsed_rule list
),[] (*virtual rules*), [] (*all metas*))
1897 | _
-> failwith
"unexpected code before the first rule\n" in
1901 (* parse to ast0 and then convert to ast *)
1902 let process file isofile verbose
=
1903 let extra_path = Filename.dirname
file in
1904 let (iso_files
, rules
, virt
, _metas
) = parse file in
1909 | Some iso_file
-> parse_iso_files [] [Common.Left iso_file
] "" in
1910 let global_isos = parse_iso_files std_isos iso_files
extra_path in
1911 let rules = Unitary_ast0.do_unitary
rules in
1915 Ast0.ScriptRule
(a
,b
,c
,d
,fv
,e
) ->
1916 [([],Ast.ScriptRule
(a
,b
,c
,d
,fv
,e
))]
1917 | Ast0.InitialScriptRule
(a
,b
,c
,d
) ->
1918 [([],Ast.InitialScriptRule
(a
,b
,c
,d
))]
1919 | Ast0.FinalScriptRule
(a
,b
,c
,d
) ->
1920 [([],Ast.FinalScriptRule
(a
,b
,c
,d
))]
1923 (iso
, dropiso, dependencies
, rule_name
, exists
)),
1924 (plus
, metavars),ruletype
) ->
1926 parse_iso_files global_isos
1927 (List.map
(function x -> Common.Left
x) iso
)
1930 (* check that dropped isos are actually available *)
1933 List.map
(function (_
,_
,nm
) -> nm
) chosen_isos in
1934 let local_iso_names = reserved_names @ iso_names in
1937 (function dropped
->
1938 not
(List.mem dropped
local_iso_names))
1941 ("invalid iso name " ^
bad_dropped ^
" in " ^ rule_name
)
1942 with Not_found
-> ());
1943 if List.mem
"all" dropiso
1945 if List.length
dropiso = 1
1947 else failwith
"disable all should only be by itself"
1948 else (* drop those isos *)
1950 (function (_
,_
,nm
) -> not
(List.mem nm
dropiso))
1952 List.iter
Iso_compile.process chosen_isos;
1954 match reserved_names with
1959 List.filter
(function x -> List.mem
x dropiso) others
)
1962 "bad list of reserved names - all must be at start" in
1963 let minus = Test_exps.process minus in
1964 let minus = Compute_lines.compute_lines
false minus in
1965 let plus = Compute_lines.compute_lines
false plus in
1967 (* only relevant to Flag.make_hrule *)
1968 (* doesn't handle multiple minirules properly, but since
1969 we don't really handle them in lots of other ways, it
1970 doesn't seem very important *)
1974 [match Ast0.unwrap p
with
1976 (match List.map
Ast0.unwrap
(Ast0.undots c
) with
1977 [Ast0.Exp e
] -> true | _
-> false)
1979 let minus = Arity.minus_arity
minus in
1980 let ((metavars,minus),function_prototypes
) =
1981 Function_prototypes.process
1982 rule_name
metavars dropped_isos minus plus ruletype
in
1983 let plus = Adjust_pragmas.process plus in
1984 (* warning! context_neg side-effects its arguments *)
1985 let (m
,p
) = List.split (Context_neg.context_neg
minus plus) in
1986 Type_infer.type_infer p
;
1987 (if not
!Flag.sgrep_mode2
1988 then Insert_plus.insert_plus m p
(chosen_isos = []));
1989 Type_infer.type_infer
minus;
1990 let (extra_meta
, minus) =
1991 match (chosen_isos,ruletype
) with
1992 (* separate case for [] because applying isos puts
1993 some restrictions on the -+ code *)
1994 ([],_
) | (_
,Ast.Generated
) -> ([],minus)
1995 | _
-> Iso_pattern.apply_isos
chosen_isos minus rule_name
in
1996 (* after iso, because iso can intro ... *)
1997 let minus = Adjacency.compute_adjacency
minus in
1998 let minus = Comm_assoc.comm_assoc
minus rule_name
dropiso in
2000 if !Flag.sgrep_mode2
then minus
2001 else Single_statement.single_statement
minus in
2002 let minus = Simple_assignments.simple_assignments
minus in
2004 Ast0toast.ast0toast rule_name dependencies
dropped_isos
2005 exists
minus is_exp ruletype
in
2007 match function_prototypes
with
2008 None
-> [(extra_meta
@ metavars, minus_ast)]
2009 | Some mv_fp
-> [(extra_meta
@ metavars, minus_ast); mv_fp
])
2010 (* Ast0.CocciRule ((minus, metavarsm, (iso, dropiso, dependencies, rule_name, exists)), (plus, metavars))*)
2013 let parsed = List.concat
parsed in
2014 let parsed = Safe_for_multi_decls.safe_for_multi_decls
parsed in
2015 let disjd = Disjdistr.disj
parsed in
2017 let (metavars,code
,fvs
,neg_pos
,ua
,pos
) = Free_vars.free_vars
disjd in
2018 if !Flag_parsing_cocci.show_SP
2019 then List.iter
Pretty_print_cocci.unparse code
;
2022 Common.profile_code
"get_glimpse_constants" (* for glimpse *)
2023 (fun () -> Get_constants2.get_constants code neg_pos
) in
2025 (metavars,code
,fvs
,neg_pos
,ua
,pos
,search_tokens)