// This implements the C(x,y) and S(x) macros which works like ETP's & operator
// and automatic conversion to string, respectively.

#include <tigcclib.h>

extern size_t cant_print_this_type;

#define __strsize(__v,__t) \
  (__builtin_choose_expr(__builtin_types_compatible_p(__t,char *) \
                         ||__builtin_types_compatible_p(__t,signed char *) \
                         ||__builtin_types_compatible_p(__t,unsigned char *) \
                         ||__builtin_types_compatible_p(__t,const char *) \
                         ||__builtin_types_compatible_p(__t,const signed char *) \
                         ||__builtin_types_compatible_p(__t,const unsigned char *) \
                         ||__builtin_types_compatible_p(__t,char []) \
                         ||__builtin_types_compatible_p(__t,signed char []) \
                         ||__builtin_types_compatible_p(__t,unsigned char []) \
                         ||__builtin_types_compatible_p(__t,const char []) \
                         ||__builtin_types_compatible_p(__t,const signed char []) \
                         ||__builtin_types_compatible_p(__t,const unsigned char []) \
                         ,strlen((const char *)(unsigned long)__v), \
   __builtin_choose_expr(__builtin_types_compatible_p(__t,char) \
                         ||__builtin_types_compatible_p(__t,signed char) \
                         ||__builtin_types_compatible_p(__t,unsigned char),1UL, \
   __builtin_choose_expr(__builtin_types_compatible_p(__t,unsigned short) \
                         ||__builtin_types_compatible_p(__t,unsigned int),5UL, \
   __builtin_choose_expr(__builtin_types_compatible_p(__t,short) \
                         ||__builtin_types_compatible_p(__t,int),6UL, \
   __builtin_choose_expr(__builtin_types_compatible_p(__t,unsigned long),10UL, \
   __builtin_choose_expr(__builtin_types_compatible_p(__t,long),11UL, \
   __builtin_choose_expr(__builtin_types_compatible_p(__t,float) \
                         ||__builtin_types_compatible_p(__t,double) \
                         ||__builtin_types_compatible_p(__t,long double),29UL, \
   cant_print_this_type))))))))

#define __strfmt(__t) \
  (__builtin_choose_expr(__builtin_types_compatible_p(__t,char *) \
                         ||__builtin_types_compatible_p(__t,signed char *) \
                         ||__builtin_types_compatible_p(__t,unsigned char *) \
                         ||__builtin_types_compatible_p(__t,const char *) \
                         ||__builtin_types_compatible_p(__t,const signed char *) \
                         ||__builtin_types_compatible_p(__t,const unsigned char *) \
                         ||__builtin_types_compatible_p(__t,char []) \
                         ||__builtin_types_compatible_p(__t,signed char []) \
                         ||__builtin_types_compatible_p(__t,unsigned char []) \
                         ||__builtin_types_compatible_p(__t,const char []) \
                         ||__builtin_types_compatible_p(__t,const signed char []) \
                         ||__builtin_types_compatible_p(__t,const unsigned char []),"%s", \
   __builtin_choose_expr(__builtin_types_compatible_p(__t,char) \
                         ||__builtin_types_compatible_p(__t,signed char) \
                         ||__builtin_types_compatible_p(__t,unsigned char),"%c", \
   __builtin_choose_expr(__builtin_types_compatible_p(__t,unsigned short) \
                         ||__builtin_types_compatible_p(__t,unsigned int),"%u", \
   __builtin_choose_expr(__builtin_types_compatible_p(__t,short) \
                         ||__builtin_types_compatible_p(__t,int),"%d", \
   __builtin_choose_expr(__builtin_types_compatible_p(__t,unsigned long),"%lu", \
   __builtin_choose_expr(__builtin_types_compatible_p(__t,long),"%ld", \
   __builtin_choose_expr(__builtin_types_compatible_p(__t,float) \
                         ||__builtin_types_compatible_p(__t,double) \
                         ||__builtin_types_compatible_p(__t,long double),"%g", \
   ""))))))))

#define S(__val) ({ \
  __typeof__((__val)+0) __v=__val; \
  char *__result=__builtin_alloca(__strsize(__v,__typeof__((__val)))+1); \
  sprintf(__result,__strfmt(__typeof__((__val))),__v); \
__result;})


#define __strfmt2(__t1,__t2) \
  (__builtin_choose_expr(__builtin_types_compatible_p(__t1,char *) \
                         ||__builtin_types_compatible_p(__t1,signed char *) \
                         ||__builtin_types_compatible_p(__t1,unsigned char *) \
                         ||__builtin_types_compatible_p(__t1,const char *) \
                         ||__builtin_types_compatible_p(__t1,const signed char *) \
                         ||__builtin_types_compatible_p(__t1,const unsigned char *) \
                         ||__builtin_types_compatible_p(__t1,char []) \
                         ||__builtin_types_compatible_p(__t1,signed char []) \
                         ||__builtin_types_compatible_p(__t1,unsigned char []) \
                         ||__builtin_types_compatible_p(__t1,const char []) \
                         ||__builtin_types_compatible_p(__t1,const signed char []) \
                         ||__builtin_types_compatible_p(__t1,const unsigned char []), \
    (__builtin_choose_expr(__builtin_types_compatible_p(__t2,char *) \
                           ||__builtin_types_compatible_p(__t2,signed char *) \
                           ||__builtin_types_compatible_p(__t2,unsigned char *) \
                           ||__builtin_types_compatible_p(__t2,const char *) \
                           ||__builtin_types_compatible_p(__t2,const signed char *) \
                           ||__builtin_types_compatible_p(__t2,const unsigned char *) \
                           ||__builtin_types_compatible_p(__t2,char []) \
                           ||__builtin_types_compatible_p(__t2,signed char []) \
                           ||__builtin_types_compatible_p(__t2,unsigned char []) \
                           ||__builtin_types_compatible_p(__t2,const char []) \
                           ||__builtin_types_compatible_p(__t2,const signed char []) \
                           ||__builtin_types_compatible_p(__t2,const unsigned char []),"%s%s", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,char) \
                           ||__builtin_types_compatible_p(__t2,signed char) \
                           ||__builtin_types_compatible_p(__t2,unsigned char),"%s%c", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,unsigned short) \
                           ||__builtin_types_compatible_p(__t2,unsigned int),"%s%u", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,short) \
                           ||__builtin_types_compatible_p(__t2,int),"%s%d", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,unsigned long),"%s%lu", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,long),"%s%ld", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,float) \
                           ||__builtin_types_compatible_p(__t2,double) \
                           ||__builtin_types_compatible_p(__t2,long double),"%s%g", \
     "")))))))), \
   __builtin_choose_expr(__builtin_types_compatible_p(__t1,char) \
                         ||__builtin_types_compatible_p(__t1,signed char) \
                         ||__builtin_types_compatible_p(__t1,unsigned char), \
    (__builtin_choose_expr(__builtin_types_compatible_p(__t2,char *) \
                           ||__builtin_types_compatible_p(__t2,signed char *) \
                           ||__builtin_types_compatible_p(__t2,unsigned char *) \
                           ||__builtin_types_compatible_p(__t2,const char *) \
                           ||__builtin_types_compatible_p(__t2,const signed char *) \
                           ||__builtin_types_compatible_p(__t2,const unsigned char *) \
                           ||__builtin_types_compatible_p(__t2,char []) \
                           ||__builtin_types_compatible_p(__t2,signed char []) \
                           ||__builtin_types_compatible_p(__t2,unsigned char []) \
                           ||__builtin_types_compatible_p(__t2,const char []) \
                           ||__builtin_types_compatible_p(__t2,const signed char []) \
                           ||__builtin_types_compatible_p(__t2,const unsigned char []),"%c%s", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,char) \
                           ||__builtin_types_compatible_p(__t2,signed char) \
                           ||__builtin_types_compatible_p(__t2,unsigned char),"%c%c", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,unsigned short) \
                           ||__builtin_types_compatible_p(__t2,unsigned int),"%c%u", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,short) \
                           ||__builtin_types_compatible_p(__t2,int),"%c%d", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,unsigned long),"%c%lu", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,long),"%c%ld", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,float) \
                           ||__builtin_types_compatible_p(__t2,double) \
                           ||__builtin_types_compatible_p(__t2,long double),"%c%g", \
     "")))))))), \
   __builtin_choose_expr(__builtin_types_compatible_p(__t1,unsigned short) \
                         ||__builtin_types_compatible_p(__t1,unsigned int), \
    (__builtin_choose_expr(__builtin_types_compatible_p(__t2,char *) \
                           ||__builtin_types_compatible_p(__t2,signed char *) \
                           ||__builtin_types_compatible_p(__t2,unsigned char *) \
                           ||__builtin_types_compatible_p(__t2,const char *) \
                           ||__builtin_types_compatible_p(__t2,const signed char *) \
                           ||__builtin_types_compatible_p(__t2,const unsigned char *) \
                           ||__builtin_types_compatible_p(__t2,char []) \
                           ||__builtin_types_compatible_p(__t2,signed char []) \
                           ||__builtin_types_compatible_p(__t2,unsigned char []) \
                           ||__builtin_types_compatible_p(__t2,const char []) \
                           ||__builtin_types_compatible_p(__t2,const signed char []) \
                           ||__builtin_types_compatible_p(__t2,const unsigned char []),"%u%s", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,char) \
                           ||__builtin_types_compatible_p(__t2,signed char) \
                           ||__builtin_types_compatible_p(__t2,unsigned char),"%u%c", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,unsigned short) \
                           ||__builtin_types_compatible_p(__t2,unsigned int),"%u%u", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,short) \
                           ||__builtin_types_compatible_p(__t2,int),"%u%d", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,unsigned long),"%u%lu", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,long),"%u%ld", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,float) \
                           ||__builtin_types_compatible_p(__t2,double) \
                           ||__builtin_types_compatible_p(__t2,long double),"%u%g", \
     "")))))))), \
   __builtin_choose_expr(__builtin_types_compatible_p(__t1,short) \
                         ||__builtin_types_compatible_p(__t1,int), \
    (__builtin_choose_expr(__builtin_types_compatible_p(__t2,char *) \
                           ||__builtin_types_compatible_p(__t2,signed char *) \
                           ||__builtin_types_compatible_p(__t2,unsigned char *) \
                           ||__builtin_types_compatible_p(__t2,const char *) \
                           ||__builtin_types_compatible_p(__t2,const signed char *) \
                           ||__builtin_types_compatible_p(__t2,const unsigned char *) \
                           ||__builtin_types_compatible_p(__t2,char []) \
                           ||__builtin_types_compatible_p(__t2,signed char []) \
                           ||__builtin_types_compatible_p(__t2,unsigned char []) \
                           ||__builtin_types_compatible_p(__t2,const char []) \
                           ||__builtin_types_compatible_p(__t2,const signed char []) \
                           ||__builtin_types_compatible_p(__t2,const unsigned char []),"%d%s", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,char) \
                           ||__builtin_types_compatible_p(__t2,signed char) \
                           ||__builtin_types_compatible_p(__t2,unsigned char),"%d%c", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,unsigned short) \
                           ||__builtin_types_compatible_p(__t2,unsigned int),"%d%u", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,short) \
                           ||__builtin_types_compatible_p(__t2,int),"%d%d", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,unsigned long),"%d%lu", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,long),"%d%ld", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,float) \
                           ||__builtin_types_compatible_p(__t2,double) \
                           ||__builtin_types_compatible_p(__t2,long double),"%d%g", \
     "")))))))), \
   __builtin_choose_expr(__builtin_types_compatible_p(__t1,unsigned long), \
    (__builtin_choose_expr(__builtin_types_compatible_p(__t2,char *) \
                           ||__builtin_types_compatible_p(__t2,signed char *) \
                           ||__builtin_types_compatible_p(__t2,unsigned char *) \
                           ||__builtin_types_compatible_p(__t2,const char *) \
                           ||__builtin_types_compatible_p(__t2,const signed char *) \
                           ||__builtin_types_compatible_p(__t2,const unsigned char *) \
                           ||__builtin_types_compatible_p(__t2,char []) \
                           ||__builtin_types_compatible_p(__t2,signed char []) \
                           ||__builtin_types_compatible_p(__t2,unsigned char []) \
                           ||__builtin_types_compatible_p(__t2,const char []) \
                           ||__builtin_types_compatible_p(__t2,const signed char []) \
                           ||__builtin_types_compatible_p(__t2,const unsigned char []),"%lu%s", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,char) \
                           ||__builtin_types_compatible_p(__t2,signed char) \
                           ||__builtin_types_compatible_p(__t2,unsigned char),"%lu%c", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,unsigned short) \
                           ||__builtin_types_compatible_p(__t2,unsigned int),"%lu%u", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,short) \
                           ||__builtin_types_compatible_p(__t2,int),"%lu%d", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,unsigned long),"%lu%lu", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,long),"%lu%ld", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,float) \
                           ||__builtin_types_compatible_p(__t2,double) \
                           ||__builtin_types_compatible_p(__t2,long double),"%lu%g", \
     "")))))))), \
   __builtin_choose_expr(__builtin_types_compatible_p(__t1,long), \
    (__builtin_choose_expr(__builtin_types_compatible_p(__t2,char *) \
                           ||__builtin_types_compatible_p(__t2,signed char *) \
                           ||__builtin_types_compatible_p(__t2,unsigned char *) \
                           ||__builtin_types_compatible_p(__t2,const char *) \
                           ||__builtin_types_compatible_p(__t2,const signed char *) \
                           ||__builtin_types_compatible_p(__t2,const unsigned char *) \
                           ||__builtin_types_compatible_p(__t2,char []) \
                           ||__builtin_types_compatible_p(__t2,signed char []) \
                           ||__builtin_types_compatible_p(__t2,unsigned char []) \
                           ||__builtin_types_compatible_p(__t2,const char []) \
                           ||__builtin_types_compatible_p(__t2,const signed char []) \
                           ||__builtin_types_compatible_p(__t2,const unsigned char []),"%ld%s", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,char) \
                           ||__builtin_types_compatible_p(__t2,signed char) \
                           ||__builtin_types_compatible_p(__t2,unsigned char),"%ld%c", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,unsigned short) \
                           ||__builtin_types_compatible_p(__t2,unsigned int),"%ld%u", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,short) \
                           ||__builtin_types_compatible_p(__t2,int),"%ld%d", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,unsigned long),"%ld%lu", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,long),"%ld%ld", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,float) \
                           ||__builtin_types_compatible_p(__t2,double) \
                           ||__builtin_types_compatible_p(__t2,long double),"%ld%g", \
     "")))))))), \
   __builtin_choose_expr(__builtin_types_compatible_p(__t1,float) \
                         ||__builtin_types_compatible_p(__t1,double) \
                         ||__builtin_types_compatible_p(__t1,long double), \
    (__builtin_choose_expr(__builtin_types_compatible_p(__t2,char *) \
                           ||__builtin_types_compatible_p(__t2,signed char *) \
                           ||__builtin_types_compatible_p(__t2,unsigned char *) \
                           ||__builtin_types_compatible_p(__t2,const char *) \
                           ||__builtin_types_compatible_p(__t2,const signed char *) \
                           ||__builtin_types_compatible_p(__t2,const unsigned char *) \
                           ||__builtin_types_compatible_p(__t2,char []) \
                           ||__builtin_types_compatible_p(__t2,signed char []) \
                           ||__builtin_types_compatible_p(__t2,unsigned char []) \
                           ||__builtin_types_compatible_p(__t2,const char []) \
                           ||__builtin_types_compatible_p(__t2,const signed char []) \
                           ||__builtin_types_compatible_p(__t2,const unsigned char []),"%g%s", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,char) \
                           ||__builtin_types_compatible_p(__t2,signed char) \
                           ||__builtin_types_compatible_p(__t2,unsigned char),"%g%c", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,unsigned short) \
                           ||__builtin_types_compatible_p(__t2,unsigned int),"%g%u", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,short) \
                           ||__builtin_types_compatible_p(__t2,int),"%g%d", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,unsigned long),"%g%lu", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,long),"%g%ld", \
     __builtin_choose_expr(__builtin_types_compatible_p(__t2,float) \
                           ||__builtin_types_compatible_p(__t2,double) \
                           ||__builtin_types_compatible_p(__t2,long double),"%g%g", \
     "")))))))), \
   ""))))))))

#define C(__val1,__val2) ({ \
  __typeof__((__val1)+0) __v1=__val1; \
  __typeof__((__val2)+0) __v2=__val2; \
  char *__result=__builtin_alloca(__strsize(__v1,__typeof__((__val1)))+__strsize(__v2,__typeof__((__val2)))+1); \
  sprintf(__result,__strfmt2(__typeof__((__val1)),__typeof__((__val2))),__v1,__v2); \
__result;})



