Limitation of CINT

  Cint accepts most of K&R and ANSI C/C++ language construct but not perfect. 
 In fact, Cint is not aimed to be a 100% ANSI/ISO compliant C/C++ language
 processor. It rather is a portable script language environment which is
 close enough to the standard C++. This document describes major differences
 from the standard. 

# General information:

 + How to workaround Cint limitation
   If you have unsupported features in your source code, that part must be 
  escaped by "#ifndef __CINT__" for cint and "#ifndef __MAKECINT__" for
  makecint. The macro __CINT__ is defined both in cint and makecint.
  __MAKECINT__ is defined only in makecint.

 + Simple expression recommended
   Because ANSI/ISO C++ standard is a huge document, it is impractical to 
  describe every details of differences in this document.  Only major 
  differences and cautions are described. To avoid unnecessary confusion,
  please use simple expression whenever possible. 


# Scope:

 + Function scope
   Variables can be declared in global or function scope.
   Unlike ANSI, local variable has function scope. If a local variable is 
  once declared in a function, it will be alive until execution gets out 
  from the function even if it is declared within sub-block. In ANSI C, local 
  variables have block scope.

	void func()
	{
	  int i;
	  for(i=0;i<10;i++) {
	    int n;      /* block scope */
	    printf("n=%d\\n",n++);
	  }
	  /* n is still alive here in cint, n should be already
	  dead in ANSI C */ 
	}

 + In function typedef and class declaration/definition 
   You can not define a new type in a function neither with typedef or
  class/struct declaration.

        void func() {
          typedef int int32;       // BAD in cint
          class A { /* ... */ };   // BAD in cint
        }


# Fundamental types
 + long long , unsigned long long
   'long long' is supported by an optional library which can be compiled
  in lib/longlong. There are some platforms which can not compile this
  library. 'long long' is implemented as a wrapper class G__longlong with
  limited capability.
   'unsigned long long' is simply handled as 'long long'. Cint will not
  distinguish between 'long long' and 'unsigned long long'.

 + bool
   'bool' is supposed to be a fundamental type in C++ standard. But in 
  Cint, bool is defined as enum in $CINTSYSDIR/include/bool.h. boo.h is
  automatically loaded by cint when it sees declaration using bool. In
  most cases, it works without problem. 
   There is a known problem, however, if you check bool with ERTTI API.


        #include <ertti.h>
        #include <iostream.h>
        int main() {
          G__TypeInfo t("bool");
          if(t.Property()&G__BIT_ISFUNDAMENTAL) {
            // this is supposed to be true, but not in cint
            cout << "bool is a fundamental type" << endl;
          }
          if(t.Property()&G__BIT_ISENUM) {
            // cint takes this case
            cout << "bool is an enum" << endl;
          }
          return(0);
        }


# Pointer declaration
   When declaring pointer, space character is needed somewhere in the 
  declaration. For example,

       int* p1;   // OK
       int *p2;   // OK
       int * p3;  // OK
       int*p3;    // Cint parsing limitation, space character needed

  This is Cint limitation. For pointer to pointer, cint may not understand
  too many levels of redirection. If you have many levels of pointer 
  redirection, it is recommended to have space character between type name
  and '*'.

       int ****p4; // OK
       int**** p5; // Cint parsing limitation
   

# Class/struct alignment:
   Each C/C++ compiler or interpreter has unique class/struct alignment 
  and padding rule. When class or struct is precompiled, cint mirrors 
  compiler's alignment. Alignment of precompiled class/struct is identical
  to compiler you use.
  If class or struct is interpreted, cint uses very conservative alignment
  and padding rule which may not match to other C/C++ processing system.


# bit-field:
   Bit-fields in precompiled class and struct can not be accessed from the
  interpreter. 


# Variable argument:
   Variable argument is supported from Cint 5.14.69.  <stdarg.h> must be
  included to use variable argument. Cint accepts both form of declaration.
 
       void foo1(char *fmt, ...);
       void foo2(char *fmt ...);

  Above declarations are handled identically. Function is mached only by name.
  Types and number of arguments are not used as function mathcing criteria.

 + Calling interpreted function with variable arguments
   A function with variable arguments can be interpreted by the Cint 
  interpreter. For doing this, va_list, va_start, va_arg and va_end 
  can be used. For example,

       #include <stdio.h>
       #include <stdarg.h>
       void foo2(char *fmt ...) {
         va_list ap;
         va_start(ap, argn);
         for(int i=0;i<argn;i++) {
	   double d = va_arg(ap,double);
           printf("%g ",d);
         }
         printf("\n");
         va_end(ap);
       }

 + Calling compiled function with variable arguments
   Argument values for variable arguments must be put into function call 
  stack. For each computer platform, specific byte layout must be emulated 
  by Cint. Because byte layout is not publicly informed, this capability 
  may not be portable to all platforms. At this moment, this capbility is
  only supported for Intel architecture(Linux & Win32), HP-UX and Solaris. 
  Support for PowerPC looks quite difficult, if not possible.
  Need more investigation for other platforms.

 + ANSI C library functions
  In order to suport variable argument, cint needs to know stack layout
  which is machine dependent and not known.

   Cint supports following library functions as special cases. Please note
  that scanf function has limitation in number of arguments.

        ostream& ostream::format(char *format ...); 
        int fprintf(FILE *fp,char *format ...);
        int printf(char *format ...);
        int sprintf(char* string,char *format ...);
        int fscanf(FILE *fp,char *format ...);     // only upto 12 arguments
        int scanf(char *format ...);               //         "
        int sscanf(char *string,char *format ...); //         "


# switch statement and default: label
   Cint requires default: label to appear at the end of switch statement.
  If you put case label after default: ,  switch statement does not work
  properly. For example,

        int n = 1;

        switch(n) {
        case 0: 
          printf("zero\n");
	  break;
        case 1: 
          printf("one\n");    // 'one' is printed both with cint and g++
	  break;
        default: 
          printf("many\n");
	  break;
        }

        switch(n) {
        case 0: 
          printf("zero\n");
	  break;
        default: 
          printf("many\n");  // Cint prints 'many'
	  break;
        case 1: 
          printf("one\n");   // But g++ prints 'one' 
	  break;
        }


# Library function:

 + ANSI C library function
   Most of ANSI C standard library functions are built in. However, following 
  ones are not supported.

	int setjmp(jmp_buf environment)
	void longjmp(jmp_buf environment,int rval)
	typename *va_arg(va_list listptr,typename)
	void va_end(va_list listptr)
	void va_start(va_list listptr,type rightparm)
	int vfprintf(FILE *fp,const char *format, va_list arguments)
	int vprintf(const char *format, va_list arguments)
	int vsprintf(char *string,const char *format, va_list arguments)

 + Optional POSIX, Win32, TCP/IP libraries
   Cint does not contain non ANSI functions by default. But you can use them
  by building optional libraries. Small subset of POSIX, Win32 and TCP/IP 
  libraries can be build under lib/posix, lib/win32api and  lib/socket
  directory. Please read README.txt in each directory.

 + STL
   Cint source package comes with an old STL (HP reference implementation) 
  which is in stl directory. You can interpret string, vector and list 
  containers and several generic algorithms.
   Small subset of precompiled STL containers can be built under lib/dll_stl 
  directory. Read lib/dll_stl/README.txt and run setup script there. You
  can precompile STL containers by yourself too. Simple example is in
  demo/makecint/stl directory.  STL dummy headers are in lib/prec_stl
  directory.
   Please understand that there are many limitations for using STL on Cint.
  STL is so complex that it is very difficult to document all limitations.

# Operator:

 + Power operator
   Power operator '@' is the original extension. It can be used both 
  integer and floating point. This extension is made for convenience of
  scientific application.  

  Before cint5.15.25, '**' notation was also used as power operator. This
  extension has been eliminated in order to avoid confusions in following 
  expression.
  
     int a=1,b=2,c;
     int *p = &b;
     c = a**b; // Use parenthesis a*(*b), although completely legal


 + sizeof
   Sizeof must be used with '()'.  If size of and its' operand is separated
  by space , without '()', cint will not produce correct result.

   Cint returns 0 for sizeof unnamed union if it is precompiled. If the
  code is interpreted, Cint can return appropriate number.


 + '.*' and '->*' 
   Pointer to member access operator '.*' and '->*' are newly supported from
  cint5.14.9. You need to define G__PTR2MEMFUNC macro in platform dependency
  file in order to turn this feature on. Use of pointer to member access
  operator is not recommended because it is premature.


 + Unsupported operators
   Sequencing operator ',' is not supported. Operation of ',' is hard coded
  in Cint core and can not be modified by operator overloading. Also,
  expression like 'expr1,expr2,expr3' does not work properly.



# Array declaration
  Cint supports array declaration. There are original enhancements and 
 recommendations.

 + constness of array dimension
   Variable dimension is not allowed in C/C++. Cint has special capability to
  allow it only in interactive command and '{ ... }' style macro.

     void f() {
       int n=5;
       float a[n]; // this is error now
     }

     $ cint
     cint> .
     cint> int n=5;
     cint> float a[n];  // this is allowed, special extension

 + constness of array dimension - recommendation
   Constness is not enough for valid array dimension. C/C++ requests
  array dimension to be defined in following ways.

     int g() { return 5; }
     #define n0 5          // GOOD: macro             recommended
     int n1=5;             // BAD : non-const static
     static int n2=5;      // BAD : non-const file-scope static
     const int n3=5;       // GOOD: static const      recommended
     const int n4=g();     // BAD : static const initialized for process
     void f() {
       int n5=5;           // BAD : non-const
       static int n6=5;    // BAD : non-const static
       const int n7=5;     // GOOD: static const      not recommended
       static const n8=5;  // GOOD: static const      not recommended
       const int n9=g();   // BAD : non-static const
       float a[n?];
     }

   Looks pretty inconsistent, but this is C++. All of above behaviors are
   implemented in cint5.14.5. Having array dimension constant in local 
   scope works properly, but it complicates the situation. It has to 
   be "static const" anyway , it is recommended to declare it in global
   scope.

 + constness and staticness of array
   Following code works on cint. But if you try to be safe, const or
  static array in local scope is not recommended.

    const int nx=5;
    const float ax[5]={1,2,3,4,5};           // Recommend this
    void f() {
      const int n=5;                         // not recommended
      float a1[n];                           // This is fine
      const float a2[n] = {1,2,3,4,5};       // not recommended
      static float a3[n];                    // not recommended
      static const float a4[n]={1,2,3,4,5};  // not recommended
    }

# Preprocessor statements:

   Cint has limitations in handling define macros in default mode. Following
  limitations applies. You can avoid following limitations by using
  preprocessor prior to interpretation by -p or +P,-P command line option.
  Read also cint(1) for use of -p and +P,-P options.

 + Macro definition:
   The biggest syntax limitation of cint is associated with define macro.
  Cint can only handle simple define macros. Some complex use of macros
  has to be handled by separate preprocessor by -p or +P,-P options.

	#define	  ON    1       /* Fine */
	#define  f(x)  (x-1)    /* OK, but not recommended */
	#define  bool  int      /* OK, but not recommended */
	#define  DECL_B  int b  /* May not work */ 


# Operator overloading

 + Unsupported operators for overloading
   Following operators can not be overloaded.

	new , delete , unary &

   The operator new is already overloaded in cint as follows. So, you don't
  need to overload new anyway in the interpreter environment. This is already
  done for both interpreted and precompiled classes.

       void* operator new(size_t size,void* arena) {return(arena);}

 + Explicit operator function call
   Operator function can not be called explicitly by name because of parse rule
  limitation. 

	complex a=complex(1,5),b=complex(-1,3.1),c=complex(0,0);
	c = operator+(a,b);  // BAD operator function can not be called
			     // explicitly.
	c = a+b;  // OK


# operator= overloading

   In Cint, if you define operator= for a class, class that is derived 
  from it must have operator=. In ANSI/ISO standard, this is not necessary.

       class A {
        public:
         A& operator=(const A& x);
       };

       class B : public A {
        public:
         B& operator=(const B& x); // this is needed in cint
       };


# Templates

   Template works probably better than most of UNIX based C++ compilers, 
  but not as good as Windows based ones. Cint can run simple STL programs.
   Following limitations applies.

 + Explicit type conversion
   Explicit type conversion for template class can not be used because of 
  parsing limitation. Use typedef if you want to do so.

	// suppose you have 
	ary<double,100> a;
	a = ary<double,100>(3.14);  // can't handle this

 + Scope resolution operator
   Template class name can not be used with scope operator to resolve 
  ambiguity. Use typedef if you want to do so.


	intary10.ary<int,10>::disp(); // can't handle this


 + Member function template
   Member function template works in Cint with limitation. Member function
  template must be defined within a class definition as inline function.

	template<class T> class A {
	  T dat;
	 public:
          template<class E> A(E& x) { dat = x; }    // OK
	  template<class E> void Set(E& x) {dat=x;} // OK
	};


 + Partial template specialization
   Partial template specialization is not supported. For example,


	// this template is fine
	template <class Iterator>
	struct iterator_traits {
  	  typedef typename Iterator::iterator_category iterator_category;
  	  typedef typename Iterator::value_type        value_type;
  	  typedef typename Iterator::difference_type   difference_type;
  	  typedef typename Iterator::pointer           pointer;
  	  typedef typename Iterator::reference         reference;
	};

	// template partial specialization not supported
	template <class T>
	struct iterator_traits<T*> {
  	  typedef random_access_iterator_tag iterator_category;
  	  typedef T                          value_type;
  	  typedef ptrdiff_t                  difference_type;
  	  typedef T*                         pointer;
  	  typedef T&                         reference;
	};



# STL 
   Supporting templates and supporting STL are quite different subject. STL
  is a very complex template library which many compiler makers have trouble
  with. Cint supports STL in limited way.

 + Using precompiled STL containers
   vector, list, deque, map and string container classes can be precompiled
  if they are instantiated. Please refer to lib/prec_stl/README.txt and
  lib/dll_stl/README.txt for more detail.  It is recommended to use 
  precompiled STL containers rather than interpreting them.

 + Interpret STL containers
   Cint can interpret vector, string and some simple list container classes.
  But this is not recommended. It is very slow and has many troubles.
  Interpreted STL implementation is based on old 1994 HP reference 
  implementation.


# Reference member
   Reference type member is not supported

	class A {
	 private:
	  int& refa; // Limitation
	};


# Reference to pointer to pointer
   Reference to pointer to pointer is not supported

        int** &a; // Limitation


# Array reference
   Array reference is not supported by Cint.

	void func(int (&ary)[5]); // Limitation


# Function overloading
   Cint implements function overloading resolution. It behaves quite similar
  to what is defined in ANSI/ISO standard, but not 100% correct. If you find
  strange behavior, it is recommended to remove ambiguous function calls.
  Some of those limitations are described below.

 + Pointer to function as argument
   Cint has problem resolving function overloading with pointer to function
  as an argument. Suppose you have following functions,

	void f(int (*p2f)(double));
	void f(void *p);

  Cint may not resolve above functions correctly. This is due to Cint's 
  complication of handling pointer to interpreted function and pointer to
  compiled function. 
 

# Pointer to function
   It is recommended to avoid pointer to function in interpreted code whenever
  possible. Implementation of pointer to function is very slow. 

 + Mixing interpreted and compiled pointer to function
   In many cases, user wants to mix interpreted and compiled pointer to 
  function. Interpreted pointer to function is not compatible with compiled 
  pointer to function. There is a special trick to do so. Please refer 
  doc/ref.txt for the detail. Search for the item G__isinterpretedp2f and 
  read it carefully. Please limit use of such trick to where it is inevitable.


# Pointer to member
 + Pointer to member functioin
   Pointer to member function is newly supported from cint5.14.9. This feature
  is normally turned off. In order to activate, you need to define 
  G__PTR2MEMFUNC macro in platform dependency file and re-compile Cint.
   This feature is only experimental and not recommended for use in general.
   Interpreted pointer to member function and compiled pointer to member
  function are completely different objects. Mixing those concepts will cause
  fatal error.  For example, following code works as long as everything is
  interpreted. However, it will cause fatal error if you precompile g() 
  and interpret main().


     class A {
      public:
       void f() { }
     };

     typedef void (A::*A_p2mf)(void);

     void g(A *pa,A_p2mf x) { (pa->*x)(); }

     main() {
       A a;
       A_p2mf pf = &A::f;
       (a.*pf)();
     }

 + Pointer to data member
   Pointer to data member is not supported.


# Exception handling
   Exception handling is implemented but with limitations. Object destruction
  may not be done properly in complex case. It is recommended not to use 
  Exception Handling in interpreted code. For example, if you interpret 
  following code, Cint will crash at ~A() because Cint can not handle
  object destruction if exception is thrown in a constructor.
  
     class A {
       int *d;
       int s;
      public:
       A(int sz) : s(sz) { 
         if(s<0) throw exception(); 
         d = new int[s];
       }
       ~A() { delete[] d; } // causes problem here
     };

     void f() {
       A a(3);
       A b(-1);  // exception is thrown
       A c(4);
     }

     int main() {
       try {
       }
       catch(exception& x) {
         printf("This is a std::exception '%s'\n",z.what()); 
       }
       return 0;
     }

   Workaround to this problem is to either precompile class A , or to
  change implementation of class A as follows.

     class A {
       int *d;
       int s;
      public:
       A(int sz) : s(0) { 
         if(s<0) throw exception(); 
         d = new int[sz];
         s = sz; // s is set at the end of the constructor 
       }
       ~A() {if(s) delete[] d;} // use s as a protection 
     };

   Exception thrown in compiled code can be caught by Cint if Cint is
  compiled with -DG__STD_EXCEPTION. Refer to platform/README.txt for more
  detail.


# namespace
   namespace is implemented with some limitation. 'namespace std' is ignored
  and it is merged with global scope. Using directive can not be used in
  global scope. Other than those, namespace works reasonably well.


# dynamic_cast, static_cast, reinterpret_cast, const_cast
   dynamic_cast, static_cast, reinterpret_cast and const_cast are parsed by
  cint but behave the same as C style '(T)v' casting.

	dynamic_cast<T>(v)       same as   (T)v
	static_cast<T>(v)        same as   (T)v
	reinterpret_cast<T>(v)   same as   (T)v
	const_cast<T>(v)         same as   (T)v


# RTTI
   RTTI library is implemented based on ANSI/ISO resolution proposal 95 spring.
  This specification may have been changed in final ANSI/ISO standard.


# Multi-Language
   Cint can handle multi-byte character sets in comment and string constant.
  Cint attempts to judge between S-JIS and EUC automatically. This algorithm 
  works for most cases, but not perfect. In S-JIS, half-size kana character 
  must not be used. There may be other corner cases that the algorithm 
  makes wrong judgment.
   Cint can not take JIS and Unicode.


# KNOWN BUGS

 + static class object

   There is a bug in CINT interpreter declaring static class object in a 
  function.


    func() {
      static InterpretedClass a;           // FIxed in 5.13.77
      static InterpretedClass b(initval);  // FIxed in 5.13.77
      static InterpretedClass b=initval;   // CINT BUG, CAUSES ERROR
      static CompiledClass d;              // FIxed in 5.13.77
      static CompiledClass e(initval);     // FIxed in 5.13.77
      static CompiledClass f=initval;      // FIxed in 5.13.77
      static int g;                        // Work fine
      static int h(1);                     // Work fine
      static int i=1;                      // Work fine
    }


# Special language extensions

   There are special language extension Cint allows for user's convenience.
  Those extensions are potentially illegal in standard C/C++. Please note
  that if you use Cint's unique extensions, the code will not work with 
  C/C++ compilers.

   - Direct comparison of string constants
       char *p = "abc";
       if(p=="abc")  printf("true\n");  // true

   - Using string constant in switch statement
       char *p="abc";
       switch(p) {
       case "abc": printf("match abc\n"); break;
       case "def": printf("match def\n"); break;
       default:    printf("unmatch\n"); break;
       }

   - Power operator
       double a = 2**3;  // power
       double b = 2@3;   // power

   - Dynamic array allocation with non const integer as an index
     (This is allowed only from command interface. If this appears in a
      source code, cint detects it as an error.)
       cint> int n=5;
       cint> float a[n];  

    (This list is not complete.)

# BUGS
   Report bugs and requirements to cint@pcroot.cern.ch. Bugs tend to 
  be fixed very quickly. Any kind of comments or messages will be appreciated.

# SEE ALSO
	doc/cint.txt doc/makecint.txt doc/bytecode.txt

# AUTHOR

  Masaharu Goto (cint@pcroot.cern.ch)
  Copyright (c) 1995~2002 Masaharu Goto