@@ -139,6 +139,9 @@ def trace_print(*args):
139
139
#: Symbols to ignore, usually special macros
140
140
ignoreSymbols = ["Q_OBJECT" ]
141
141
142
+ _BRACE_REASON_OTHER = 0
143
+ _BRACE_REASON_NS = 1
144
+ _BRACE_REASON_EXTERN = 2
142
145
143
146
# Track what was added in what order and at what depth
144
147
parseHistory = []
@@ -1506,6 +1509,11 @@ def cur_namespace(self, add_double_colon=False):
1506
1509
i += 1
1507
1510
return rtn
1508
1511
1512
+ def cur_linkage (self ):
1513
+ if len (self .linkage_stack ):
1514
+ return self .linkage_stack [- 1 ]
1515
+ return ""
1516
+
1509
1517
def guess_ctypes_type (self , string ):
1510
1518
pointers = string .count ("*" )
1511
1519
string = string .replace ("*" , "" )
@@ -2372,6 +2380,7 @@ def _evaluate_method_stack(self):
2372
2380
self ._get_location (self .nameStack ),
2373
2381
)
2374
2382
newMethod ["parent" ] = None
2383
+ newMethod ["linkage" ] = self .cur_linkage ()
2375
2384
self .functions .append (newMethod )
2376
2385
2377
2386
# Reset template once it has been used
@@ -2524,6 +2533,7 @@ def _evaluate_property_stack(self, clearStack=True, addToVar=None):
2524
2533
self ._get_location (self .nameStack ),
2525
2534
)
2526
2535
newVar ["namespace" ] = self .current_namespace ()
2536
+ newVar ["linkage" ] = self .cur_linkage ()
2527
2537
if self .curClass :
2528
2538
klass = self .classes [self .curClass ]
2529
2539
klass ["properties" ][self .curAccessSpecifier ].append (newVar )
@@ -2542,6 +2552,7 @@ def _evaluate_property_stack(self, clearStack=True, addToVar=None):
2542
2552
self ._get_location (self .nameStack ),
2543
2553
)
2544
2554
newVar ["namespace" ] = self .cur_namespace (False )
2555
+ newVar ["linkage" ] = self .cur_linkage ()
2545
2556
if addToVar :
2546
2557
newVar .update (addToVar )
2547
2558
self .variables .append (newVar )
@@ -2600,6 +2611,7 @@ def _evaluate_class_stack(self):
2600
2611
)
2601
2612
self .curTemplate = None
2602
2613
newClass ["declaration_method" ] = self .nameStack [0 ]
2614
+ newClass ["linkage" ] = self .cur_linkage ()
2603
2615
self .classes_order .append (newClass ) # good idea to save ordering
2604
2616
self .stack = [] # fixes if class declared with ';' in closing brace
2605
2617
self .stmtTokens = []
@@ -2782,6 +2794,7 @@ def __init__(
2782
2794
self .curAccessSpecifier = "private" # private is default
2783
2795
self .curTemplate = None
2784
2796
self .accessSpecifierStack = []
2797
+ self .linkage_stack = []
2785
2798
debug_print (
2786
2799
"curAccessSpecifier changed/defaulted to %s" , self .curAccessSpecifier
2787
2800
)
@@ -2828,16 +2841,6 @@ def __init__(
2828
2841
new_m += "\n " * (num_newlines )
2829
2842
headerFileStr = headerFileStr .replace (m , new_m )
2830
2843
2831
- # Filter out Extern "C" statements. These are order dependent
2832
- matches = re .findall (
2833
- re .compile (r'extern[\t ]+"[Cc]"[\t \n\r]*{' , re .DOTALL ), headerFileStr
2834
- )
2835
- for m in matches :
2836
- # Keep the newlines so that linecount doesnt break
2837
- num_newlines = len ([a for a in m if a == "\n " ])
2838
- headerFileStr = headerFileStr .replace (m , "\n " * num_newlines )
2839
- headerFileStr = re .sub (r'extern[ ]+"[Cc]"[ ]*' , "" , headerFileStr )
2840
-
2841
2844
# Filter out any ignore symbols that end with "()" to account for #define magic functions
2842
2845
for ignore in ignoreSymbols :
2843
2846
if not ignore .endswith ("()" ):
@@ -2876,6 +2879,8 @@ def __init__(
2876
2879
)
2877
2880
2878
2881
self .braceDepth = 0
2882
+ self .braceReason = []
2883
+ self .lastBraceReason = _BRACE_REASON_OTHER
2879
2884
2880
2885
lex = Lexer (self .headerFileName )
2881
2886
lex .input (headerFileStr )
@@ -2948,23 +2953,20 @@ def __init__(
2948
2953
continue
2949
2954
2950
2955
if parenDepth == 0 and tok .type == "{" :
2956
+ self .lastBraceReason = _BRACE_REASON_OTHER
2951
2957
if len (self .nameStack ) >= 2 and is_namespace (
2952
2958
self .nameStack
2953
2959
): # namespace {} with no name used in boost, this sets default?
2954
- if (
2955
- self .nameStack [1 ]
2956
- == "__IGNORED_NAMESPACE__CppHeaderParser__"
2957
- ): # Used in filtering extern "C"
2958
- self .nameStack [1 ] = ""
2959
2960
self .nameSpaces .append ("" .join (self .nameStack [1 :]))
2960
2961
ns = self .cur_namespace ()
2961
2962
self .stack = []
2962
2963
self .stmtTokens = []
2963
2964
if ns not in self .namespaces :
2964
2965
self .namespaces .append (ns )
2966
+ self .lastBraceReason = _BRACE_REASON_NS
2965
2967
# Detect special condition of macro magic before class declaration so we
2966
2968
# can filter it out
2967
- if "class" in self .nameStack and self .nameStack [0 ] != "class" :
2969
+ elif "class" in self .nameStack and self .nameStack [0 ] != "class" :
2968
2970
classLocationNS = self .nameStack .index ("class" )
2969
2971
classLocationS = self .stack .index ("class" )
2970
2972
if (
@@ -2997,14 +2999,20 @@ def __init__(
2997
2999
self .stmtTokens = []
2998
3000
if not self .braceHandled :
2999
3001
self .braceDepth += 1
3002
+ self .braceReason .append (self .lastBraceReason )
3000
3003
3001
3004
elif parenDepth == 0 and tok .type == "}" :
3002
3005
if self .braceDepth == 0 :
3003
3006
continue
3004
- if self .braceDepth == len (self .nameSpaces ):
3005
- tmp = self .nameSpaces .pop ()
3007
+ reason = self .braceReason .pop ()
3008
+ if reason == _BRACE_REASON_NS :
3009
+ self .nameSpaces .pop ()
3006
3010
self .stack = [] # clear stack when namespace ends?
3007
3011
self .stmtTokens = []
3012
+ elif reason == _BRACE_REASON_EXTERN :
3013
+ self .linkage_stack .pop ()
3014
+ self .stack = [] # clear stack when linkage ends?
3015
+ self .stmtTokens = []
3008
3016
else :
3009
3017
self ._evaluate_stack ()
3010
3018
self .braceDepth -= 1
@@ -3368,8 +3376,10 @@ def _evaluate_stack(self, token=None):
3368
3376
pass
3369
3377
elif len (self .nameStack ) == 2 and self .nameStack [0 ] == "extern" :
3370
3378
debug_print ("trace extern" )
3379
+ self .linkage_stack .append (self .nameStack [1 ].strip ('"' ))
3371
3380
self .stack = []
3372
3381
self .stmtTokens = []
3382
+ self .lastBraceReason = _BRACE_REASON_EXTERN
3373
3383
elif (
3374
3384
len (self .nameStack ) == 2 and self .nameStack [0 ] == "friend"
3375
3385
): # friend class declaration
@@ -3677,12 +3687,14 @@ def _parse_enum(self):
3677
3687
def _install_enum (self , newEnum , instancesData ):
3678
3688
if len (self .curClass ):
3679
3689
newEnum ["namespace" ] = self .cur_namespace (False )
3690
+ newEnum ["linkage" ] = self .cur_linkage ()
3680
3691
klass = self .classes [self .curClass ]
3681
3692
klass ["enums" ][self .curAccessSpecifier ].append (newEnum )
3682
3693
if self .curAccessSpecifier == "public" and "name" in newEnum :
3683
3694
klass ._public_enums [newEnum ["name" ]] = newEnum
3684
3695
else :
3685
3696
newEnum ["namespace" ] = self .cur_namespace (True )
3697
+ newEnum ["linkage" ] = self .cur_linkage ()
3686
3698
self .enums .append (newEnum )
3687
3699
if "name" in newEnum and newEnum ["name" ]:
3688
3700
self .global_enums [newEnum ["name" ]] = newEnum
0 commit comments