2121#include <clang-c/Index.h>
2222#include <string.h>
2323#include <stdlib.h>
24+ #include <inttypes.h>
2425
2526/*
2627 * The basic idea of the token parser is to "stack" ordered tokens
@@ -1542,6 +1543,103 @@ static enum CXChildVisitResult callback(CXCursor cursor, CXCursor parent,
15421543 return CXChildVisit_Continue ;
15431544}
15441545
1546+ static double eval_expr (CXToken * tokens , unsigned * n , unsigned last );
1547+
1548+ static double eval_prim (CXToken * tokens , unsigned * n , unsigned last ) {
1549+ CXString s ;
1550+ const char * str ;
1551+ if (* n > last ) {
1552+ fprintf (stderr , "Unable to parse an expression primary, no more tokens\n" );
1553+ exit (1 );
1554+ }
1555+ s = clang_getTokenSpelling (TU , tokens [* n ]);
1556+ str = clang_getCString (s );
1557+ if (!strcmp (str , "-" )) {
1558+ (* n )++ ;
1559+ clang_disposeString (s );
1560+ return - eval_prim (tokens , n , last );
1561+ } else if (!strcmp (str , "(" )) {
1562+ double d ;
1563+ (* n )++ ;
1564+ clang_disposeString (s );
1565+ d = eval_expr (tokens , n , last );
1566+ if (* n >= last ) {
1567+ fprintf (stderr , "No right parenthesis found\n" );
1568+ exit (1 );
1569+ }
1570+ s = clang_getTokenSpelling (TU , tokens [* n ]);
1571+ str = clang_getCString (s );
1572+ if (!strcmp (str , ")" )) {
1573+ clang_disposeString (s );
1574+ (* n )++ ;
1575+ } else {
1576+ fprintf (stderr , "No right parenthesis found\n" );
1577+ exit (1 );
1578+ }
1579+ return d ;
1580+ } else {
1581+ char * end ;
1582+ double d = strtod (str , & end );
1583+ if (* end != '\0' ) {
1584+ fprintf (stderr , "Unable to parse %s as expression primary\n" , str );
1585+ exit (1 );
1586+ }
1587+ (* n )++ ;
1588+ clang_disposeString (s );
1589+ return d ;
1590+ }
1591+ }
1592+
1593+ static double eval_term (CXToken * tokens , unsigned * n , unsigned last ) {
1594+ double left = eval_prim (tokens , n , last );
1595+ while (* n <= last ) {
1596+ CXString s = clang_getTokenSpelling (TU , tokens [* n ]);
1597+ const char * str = clang_getCString (s );
1598+ if (!strcmp (str , "*" )) {
1599+ (* n )++ ;
1600+ left *= eval_prim (tokens , n , last );
1601+ } else if (!strcmp (str , "/" )) {
1602+ (* n )++ ;
1603+ left /= eval_prim (tokens , n , last );
1604+ } else {
1605+ clang_disposeString (s );
1606+ return left ;
1607+ }
1608+ clang_disposeString (s );
1609+ }
1610+ return left ;
1611+ }
1612+
1613+ static double eval_expr (CXToken * tokens , unsigned * n , unsigned last ) {
1614+ double left = eval_term (tokens , n , last );
1615+ while (* n <= last ) {
1616+ CXString s = clang_getTokenSpelling (TU , tokens [* n ]);
1617+ const char * str = clang_getCString (s );
1618+ if (!strcmp (str , "-" )) {
1619+ (* n )++ ;
1620+ left -= eval_term (tokens , n , last );
1621+ } else if (!strcmp (str , "+" )) {
1622+ (* n )++ ;
1623+ left += eval_term (tokens , n , last );
1624+ } else {
1625+ clang_disposeString (s );
1626+ return left ;
1627+ }
1628+ clang_disposeString (s );
1629+ }
1630+ return left ;
1631+ }
1632+
1633+ static double eval_tokens (CXToken * tokens , unsigned first , unsigned last ) {
1634+ unsigned n = first ;
1635+ double d = eval_expr (tokens , & n , last );
1636+ if (n <= last ) {
1637+ fprintf (stderr , "Unable to parse tokens as expression\n" );
1638+ exit (1 );
1639+ }
1640+ return d ;
1641+ }
1642+
15451643static void get_token_position (CXToken token , unsigned * lnum ,
15461644 unsigned * pos , unsigned * off )
15471645{
@@ -1804,6 +1902,10 @@ static void replace_struct_array(unsigned *_saidx, unsigned *_clidx,
18041902 CXToken * tokens , unsigned n_tokens )
18051903{
18061904 unsigned saidx = * _saidx , off , i , n = * _n , j ;
1905+ StructArrayList * sal = & struct_array_lists [saidx ];
1906+ StructDeclaration * decl = sal -> struct_decl_idx != (unsigned ) -1 ?
1907+ & structs [sal -> struct_decl_idx ] : NULL ;
1908+ int is_union = decl ? decl -> is_union : 0 ;
18071909
18081910 // we assume here the indenting for the first opening token,
18091911 // i.e. the '{', is already taken care of
@@ -1817,7 +1919,9 @@ static void replace_struct_array(unsigned *_saidx, unsigned *_clidx,
18171919 unsigned expr_off_s , expr_off_e , val_idx , val_off_s , val_off_e , saidx2 ,
18181920 indent_token_end , next_indent_token_start , val_token_start ,
18191921 val_token_end ;
1922+ int print_normal = 1 ;
18201923 CXString spelling ;
1924+ StructMember * member = decl ? & decl -> entries [j ] : NULL ;
18211925
18221926 val_idx = find_value_index (& struct_array_lists [saidx ], j );
18231927
@@ -1826,6 +1930,8 @@ static void replace_struct_array(unsigned *_saidx, unsigned *_clidx,
18261930 if (val_idx == (unsigned ) -1 ) {
18271931 unsigned depth = struct_array_lists [saidx ].array_depth ;
18281932 unsigned idx = struct_array_lists [saidx ].struct_decl_idx ;
1933+ if (is_union ) // Don't print the filler zeros for unions
1934+ continue ;
18291935 if (depth > 1 ) {
18301936 print_literal_text ("{ 0 }" , lnum , cpos );
18311937 } else if (depth == 1 ) {
@@ -1861,8 +1967,44 @@ static void replace_struct_array(unsigned *_saidx, unsigned *_clidx,
18611967 // adjust position
18621968 get_token_position (tokens [val_token_start ], lnum , cpos , & off );
18631969
1970+ if (is_union && j != 0 ) {
1971+ StructMember * first_member = & decl -> entries [0 ];
1972+ if ((!strcmp (first_member -> type , "double" ) ||
1973+ !strcmp (first_member -> type , "float" )) && !first_member -> n_ptrs ) {
1974+ fprintf (stderr , "Can't convert type %s to %s for union\n" ,
1975+ member -> type , first_member -> type );
1976+ exit (1 );
1977+ }
1978+ if (first_member -> n_ptrs )
1979+ print_literal_text ("(void*) " , lnum , cpos );
1980+ if (member -> n_ptrs )
1981+ print_literal_text ("(intptr_t) " , lnum , cpos );
1982+
1983+ if ((!strcmp (member -> type , "double" ) ||
1984+ !strcmp (member -> type , "float" )) && !member -> n_ptrs ) {
1985+ // Convert a literal floating pointer number (not a pointer to
1986+ // one of them) to its binary representation
1987+ union {
1988+ uint64_t i ;
1989+ double f ;
1990+ } if64 ;
1991+ char buf [20 ];
1992+ if64 .f = eval_tokens (tokens , val_token_start , val_token_end );
1993+ if (!strcmp (member -> type , "float" )) {
1994+ union {
1995+ uint32_t i ;
1996+ float f ;
1997+ } if32 ;
1998+ if32 .f = if64 .f ;
1999+ if64 .i = if32 .i ;
2000+ }
2001+ snprintf (buf , sizeof (buf ), "%#" PRIx64 , if64 .i );
2002+ print_literal_text (buf , lnum , cpos );
2003+ print_normal = 0 ;
2004+ }
2005+ }
18642006 // print values out of order
1865- for (n = val_token_start ; n <= val_token_end ; n ++ ) {
2007+ for (n = val_token_start ; n <= val_token_end && print_normal ; n ++ ) {
18662008 print_token_wrapper (tokens , n_tokens , & n , lnum , cpos ,
18672009 & saidx2 , _clidx , off );
18682010 if (n != val_token_end )
@@ -1885,6 +2027,9 @@ static void replace_struct_array(unsigned *_saidx, unsigned *_clidx,
18852027 struct_array_lists [saidx ].value_offset .end );
18862028 }
18872029
2030+ if (is_union ) // Unions should be initialized by only one element
2031+ break ;
2032+
18882033 for (; n < indent_token_end ; n ++ ) {
18892034 print_token (tokens [n ], lnum , cpos );
18902035 indent_for_token (tokens [n + 1 ], lnum , cpos , & off );
0 commit comments