@@ -89,6 +89,20 @@ function is_macro_constants(toks)
8989 end
9090end
9191
92+ function is_macro_constants_with_conv (toks)
93+ if toks. size == 5 &&
94+ toks[1 ]. kind == CXToken_Identifier &&
95+ toks[2 ]. kind == CXToken_Identifier &&
96+ toks[3 ]. kind == CXToken_Punctuation &&
97+ toks[4 ]. kind == CXToken_Literal &&
98+ toks[5 ]. kind == CXToken_Punctuation
99+ # `#define CONSTANT_LITERALS_CONV CLONG ( 1 )`
100+ return true
101+ else
102+ return false
103+ end
104+ end
105+
92106function is_macro_naive_alias (toks)
93107 if toks. size == 2 &&
94108 toks[1 ]. kind == CXToken_Identifier &&
@@ -181,6 +195,39 @@ function is_macro_binary_operator(toks)
181195 end
182196end
183197
198+ function is_macro_naive_arithmetic (toks)
199+ toks[1 ]. kind != CXToken_Identifier && return false
200+ toks. size < 4 && return false
201+
202+ # only allows `Identifier`, `Literal`, `Punctuation`(C_OPERATORS and brackets)
203+ is_naive = all (toks) do tok
204+ if tok. kind == CXToken_Punctuation
205+ return tok. text ∈ C_OPERATORS || tok. text == " (" || tok. text == " )"
206+ elseif tok. kind == CXToken_Identifier
207+ return ! startswith (tok. text, " __" ) # ignore compiler defs
208+ else
209+ return true
210+ end
211+ end
212+
213+ # if there is no binary operator, skip
214+ all (x-> x. text ∉ C_OPERATORS, toks) && return false
215+
216+ # try to parse the expression
217+ if is_naive
218+ try
219+ txts = [tok. kind == CXToken_Literal ? literally (tok) : tok. text for tok in collect (toks)[2 : end ]]
220+ str = reduce (add_spaces_for_macros, txts)
221+ Meta. parse (str)
222+ return true
223+ catch err
224+ # pass
225+ end
226+ end
227+
228+ return false
229+ end
230+
184231function add_spaces_for_macros (lhs, rhs)
185232 if startswith (rhs, " (" ) # handle function call
186233 if endswith (lhs, " ?" ) || endswith (lhs, " :" ) # handle trinary operator
@@ -253,9 +300,11 @@ function macro_emit!(dag::ExprDAG, node::ExprNode{MacroDefault}, options::Dict)
253300 cursor = node. cursor
254301 tokens = tokenize (cursor)
255302
256- if ! ignore_pure_def && is_macro_pure_definition (tokens)
257- sym = make_symbol_safe (tokens[1 ]. text)
258- push! (node. exprs, Expr (:const , Expr (:(= ), sym, :nothing )))
303+ if is_macro_pure_definition (tokens)
304+ if ! ignore_pure_def
305+ sym = make_symbol_safe (tokens[1 ]. text)
306+ push! (node. exprs, Expr (:const , Expr (:(= ), sym, :nothing )))
307+ end
259308 return dag
260309 end
261310
@@ -268,6 +317,16 @@ function macro_emit!(dag::ExprDAG, node::ExprNode{MacroDefault}, options::Dict)
268317 return dag
269318 end
270319
320+ if is_macro_constants_with_conv (tokens)
321+ literal_tok = tokens[4 ]
322+ literals = literally (literal_tok)
323+ sym = make_symbol_safe (tokens[1 ]. text)
324+ csym = make_symbol_safe (tokens[2 ]. text)
325+ literal_sym = Meta. parse (literals)
326+ push! (node. exprs, Expr (:const , Expr (:(= ), sym, Expr (:call , csym, literal_sym))))
327+ return dag
328+ end
329+
271330 if is_macro_naive_alias (tokens)
272331 lhs, rhs = tokens
273332 lhs_sym = make_symbol_safe (lhs. text)
@@ -312,6 +371,24 @@ function macro_emit!(dag::ExprDAG, node::ExprNode{MacroDefault}, options::Dict)
312371 return dag
313372 end
314373
374+ if is_macro_naive_arithmetic (tokens)
375+ sym = make_symbol_safe (tokens[1 ]. text)
376+ txts = Vector {String} (undef, length (tokens)- 1 )
377+ for (i, tok) in enumerate (collect (tokens)[2 : end ])
378+ if tok. kind == CXToken_Literal
379+ txts[i] = literally (tok)
380+ elseif tok. kind == CXToken_Punctuation && tok. text ∈ C_OPERATORS
381+ txts[i] = tok. text == " /" ? " ÷" :
382+ tok. text == " ^" ? " ⊻" : tok. text
383+ else
384+ txts[i] = tok. text
385+ end
386+ end
387+ str = reduce (add_spaces_for_macros, txts)
388+ push! (node. exprs, Expr (:const , Expr (:(= ), sym, Meta. parse (str))))
389+ return dag
390+ end
391+
315392 # for all the other cases, we just blindly use Julia's Meta.parse to parse the C code.
316393 if tokens. size > 1 && tokens[1 ]. kind == CXToken_Identifier && mode == " aggressive"
317394 sym = make_symbol_safe (tokens[1 ]. text)
0 commit comments