#!/bin/bash
tmpfile=$(mktemp)
trap 'rm "$tmpfile"; history -w; echo' EXIT
HISTFILE=~/.ccalc_history
HISTSIZE=500
history -r
while read -p "> " -e expr; do
  [[ "$expr" =~ ^[[:space:]]*$ ]] && continue
  history -s -- "$expr"
  g++ -w -Wfatal-errors -o "$tmpfile" -xc++ - << EOF && "$tmpfile"
  #include <iostream>
  #include <cstdint>
  #include <cmath>
  #include <typeinfo>
  #if __GNUC__
  #include <cxxabi.h>
  #endif

  using namespace std;

  #define STR(x) #x

  template<class T>
  void print(T x, typename std::enable_if_t<is_integral<T>::value>* = 0) {
    if (sizeof (T) == 1)
      cout << "'" << x << "'\n  = " << +x << "\n  = 0x" << hex
           << +(unsigned char)x << '\n';
    else
      cout << x << "\n  = 0x" << hex << x << '\n';
  }

  template<class T>
  void print(T x, typename std::enable_if_t<is_floating_point<T>::value>* = 0) {
    cout << x << '\n';
    if (isfinite(x))
      cout << "  = " << hexfloat << x << '\n';
  }

  template<class T>
  void print(T x, typename std::enable_if_t<!is_arithmetic<T>::value>* = 0) {
    cout << '"' << x << '"' << '\n';
  }

  int main() {
    cout << "  = ";
    print($expr);
  #if __GNUC__
    cout << "  Typ: " << abi::__cxa_demangle(typeid($expr).name(), 0, 0, 0) << '\n';
  #else
    cout << "  Typ-ID: " << typeid($expr).name() << '\n';
  #endif
    return 0;
  }
EOF
done
