/*****************************************************************************/
/*                                                                           */
/*                           OCO SOURCE MATERIALS                            */
/*                             IBM CONFIDENTIAL                              */
/*                                    OR                                     */
/*                        IBM CONFIDENTIAL RESTRICTED                        */
/*            WHEN COMBINED WITH THE AGGREGATED OCO SOURCE MODULES           */
/*                           FOR THIS PROGRAM PRODUCT                        */
/*                                                                           */
/*   VisualAge Generator Server for OS/2, AIX, HP-UX, SUN, Windows NT, and   */
/*                      SCO OpenServer  -  Version 4.1                       */
/*                    (C) COPYRIGHT IBM CORP. 1994, 2000                     */
/*                                                                           */
/*****************************************************************************/
/*****************************************************************************/
/*                                                                           */
/*    Date     Userid          Description of problem                        */
/*                                                                           */
/*  04/09/98   koch       F8559   -  Add support for MVS open edit.       @A1*/
/*  08/19/98   proffer    F4070   -  Add support for Sun                     */
/*  05/27/99   proffer    F10913  -  Add Version 4.0 support                 */
/*  08/07/99   Lui        F11712  -  Add Unicode support                  @A2*/
/*  01/19/00   proffer    F12650  -  Add support for SCO Openserver          */
/*                                                                           */
/*****************************************************************************/

#ifndef FCWCMN_H
#  define FCWCMN_H

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream.h>

#include "fcwdbcs.h"

#ifndef min
# define min(a, b)  (((a) < (b)) ? (a) : (b))
#endif

#ifndef max
# define max(a, b)  (((a) > (b)) ? (a) : (b))
#endif

#if defined FCW_UNIX || defined FCW_MVS /* @A1 */
#define CRLFSIZE     1
#else
#define CRLFSIZE     2
#endif

// *********************************************************************
// Boolean portable implementation
// *********************************************************************

enum BoolState { False=0, True=1 };

class Bool
{
  private:
    BoolState state;

  public:
    Bool() { state = False; }
    Bool(BoolState st) { state = st; }
    Bool(int st) { state = st ? True : False; }
    operator int() { return state == True ? 1 : 0; }
    Bool& operator = (const Bool& st) { state = st.state; return *this; }
    int operator == (const Bool& st) { return state == st.state; }
    int operator == (BoolState st) { return state == st; }
//  Bool operator || (Bool st) { return int(*this) || int(st); }
//  Bool operator && (Bool st) { return int(*this) && int(st); }
    Bool operator !() { return state ? False : True; }
};

// *********************************************************************
// Internal portable string class implementation
// *********************************************************************
class FCWString;

class str
{
   friend class FCWString;

   protected:
      str(int l=0) :
         size(max(l, 100)),  // 100 is an arbitary amount
         len(l),
         count(1)
      {
         s = new char[size+1];
         s[len]=0;
      }

      str(str& o) :
         size(o.size),
         len(o.len),
         count(1)
      {
         s = new char[size+1];
         memcpy(s, o.s, len+1);
      }

      ~str()
      {
         delete [] s;
      }


      int   count;
      int   size;
      int   len;
      char* s;

      str&  operator ++(int)
      {
         count++;
         return *this;
      }
      str&  operator --(int)
      {
         count--;
         if (!count)
            delete this;
         return *this;
      }

      void re_alloc(int l)
      {
         char* ptmp = new char[l+1];
         memcpy(ptmp, s, len+1);  // include null
         delete [] s;
         s = ptmp;
         size = l;
      }
};


class FCWString
{
  private:

    str* pStr;

    void makeunique()
    {
       if (pStr->count > 1)
       {
          str* ptmp = new str(*pStr);
          (*pStr)--;
          pStr = ptmp;
       }
    }

  public:
    FCWString()
    {
       pStr = new str;
    }

    FCWString(char* s)
    {
       pStr = new str((s) ? strlen(s) : 0);
       if (s)
          strcpy(pStr->s, s);
       else
          pStr->s[0] = 0;
    }

    FCWString(char c)
    {
       pStr = new str(sizeof(c));
       pStr->s[0] = c;
       pStr->s[1] = 0;
    }

    FCWString(char* s, unsigned l, char pad = ' ')
    {
       pStr = new str(l);
       if (l)
       {
          int strl = (s) ? strlen(s) : 0;
          if (strl)
             strncpy(pStr->s, s, l);
          if (strl < l)
             memset(&(pStr->s[strl]), pad, l - strl);
       }
       pStr->s[l] = 0;
    }

    FCWString(char* s, unsigned l, wchar_t pad)
    {
       pStr = new str(l);
       if (l)
       {
          int strl = (s) ? strlen(s) : 0;
          if (strl)
             fcw_strncpy(pStr->s, s, l);
          if (strl < l)
          {
             char* p = &(pStr->s[strl]);
             for (int j = (l - strl)/2; j; j--)
             {
                wctomb(p, pad);
                p += MB_CUR_MAX;
             }
          }
       }
       *((short*)&(pStr->s[l])) = 0;
    }

    FCWString(int n)
    {
       char x[10];
       sprintf (x, "%d", n);
       pStr = new str(strlen(x));
       strcpy(pStr->s, x);
    }

    FCWString(FCWString const& s)
    {
       pStr = s.pStr;
       (*pStr)++;
    }

    ~FCWString()
    {
       (*pStr)--;
    }

//HP  operator char*()
//  {
//     makeunique();
//     return pStr->s;
//  }

    operator char*() const
    {
       return pStr->s;
    }

    int operator == (char* s) const
    {
       if (pStr->len != strlen(s))
          return 0;
       else if (pStr->s == s)
          return 1;
       else if (s)
          return (!memcmp(pStr->s, s, pStr->len));
       else
          return 0;
    }

    int operator != ( char* s) const
    {
       return !( *this == s );
    }

    int operator == (FCWString const& s) const
    {
       if (pStr == s.pStr)
          return 1;
       if (pStr->len != s.pStr->len)
          return 0;
       else
          return (!memcmp(pStr->s, s.pStr->s, pStr->len));
    }

    int operator != (FCWString const& s) const
    {
       return !( *this == s );
    }

    FCWString& operator = (FCWString const& s)
    {
       if ( pStr != s.pStr )
       {
          (*pStr)--;
          pStr = s.pStr;
          (*pStr)++;
       }
       return *this;
    }

    FCWString& operator = (char* s)
    {
       (*pStr)--;
       pStr = new str((s) ? strlen(s) : 0);
       if (s)
          strcpy(pStr->s, s);
       else
          pStr->s[0] = 0;
       return *this;
    }

    char& operator [] (int i)
    {
       makeunique();
       return pStr->s[i];   // extend if i>len ?
    }

    int Length() const
    {
       return pStr->len;
    }

    // indx is zero based
    FCWString  SubString(int indx, int length, char pad=' ') const
    {
       FCWString t(NULL, length, pad);
       if (indx < pStr->len)
       {
          int mlen = min(length, pStr->len - indx);
          memcpy(t.pStr->s, &(pStr->s[indx]), mlen);
       }
       return t;
    }

    FCWString& StripLeading(char ch=' ')
    {
       makeunique();
       if (pStr->count > 1)
       {
          str* ptmp = new str(*pStr);
          (*pStr)--;
          pStr = ptmp;
       }
       int i;
       for (i=0; i < pStr->len && pStr->s[i] == ch; i++);
       if (i)
       {
          pStr->len -= i;
          if (pStr->len)
             memcpy(pStr->s, &(pStr->s[i]), pStr->len);
          pStr->s[pStr->len] = 0;
       }
       return *this;
    }

    FCWString& StripLeading(FCWString const& s)
    {
       makeunique();
       int i, j;
       for (i=0; i < pStr->len; i++)
       {
          for (j=0; j < s.pStr->len; j++)
             if (pStr->s[i] == s.pStr->s[j])
                break;
          if (j == s.pStr->len)
             break;
       }

       if (i)
       {
          pStr->len -= i;
          if (pStr->len)
             memcpy(pStr->s, &(pStr->s[i]), pStr->len);
          pStr->s[pStr->len] = 0;
       }
       return *this;
    }

    FCWString& StripLeading(wchar_t wch)
    {
       short wc;
       wctomb((char*)&wc, wch);
       makeunique();
       short *p;
       for (p=(short*)pStr->s; p < (short*)&(pStr->s[pStr->len]) && *p == wc; p++);
       if (p != (short*)pStr->s)
       {
          pStr->len = (char*)p - pStr->s;
          if (pStr->len)
             fcw_memcpy(pStr->s, p, pStr->len);
          *((short*)&(pStr->s[pStr->len])) = 0;
       }
       return *this;
    }

    FCWString& StripTrailing(char ch=' ')
    {
       makeunique();
       int i;
       for (i=pStr->len; i && pStr->s[i-1] == ch; i--);

       pStr->len = i;
       pStr->s[pStr->len] = 0;

       return *this;
    }

    FCWString& StripTrailing(FCWString const& s)
    {
       makeunique();
       int i;
       for (i=pStr->len; i ; i--)
       {
          int j;
          for (j=0; j < s.pStr->len; j++)
             if (pStr->s[i-1] == s.pStr->s[j])
                break;
          if (j == s.pStr->len)
             break;
       }

       pStr->len = i;
       pStr->s[pStr->len] = 0;

       return *this;
    }

    FCWString& StripTrailing(wchar_t wch)
    {
       short wc;
       wctomb((char*)&wc, wch);
       makeunique();
       short *p;
       for (p=(short*)&(pStr->s[pStr->len-2]); p >= (short*)pStr->s && *p == wc; p--);
       p++;

       pStr->len = (char*)p - pStr->s;
       *((short*)&(pStr->s[pStr->len])) = 0;

       return *this;
    }

    FCWString& Strip(char ch=' ')
    {
       StripTrailing(ch);
       StripLeading(ch);

       return *this;
    }

    FCWString& Strip(FCWString const &s)
    {
       StripTrailing(s);
       StripLeading(s);

       return *this;
    }

    FCWString& Strip(wchar_t wch)
    {
       StripTrailing(wch);
       StripLeading(wch);

       return *this;
    }

    FCWString& RightJustify(int l, char pad=' ')
    {
       Strip();

       if (l <= pStr->len)
          pStr->len = l;
       else
          *this = FCWString((char*)NULL, l-pStr->len, pad) + *this;

       pStr->s[pStr->len] = 0;

       return *this;
    }

    FCWString& LeftJustify(int l, char pad=' ')
    {
       Strip();

       if (l <= pStr->len)
          pStr->len = l;
       else
          *this += FCWString((char*)NULL, l-pStr->len, pad);

       pStr->s[pStr->len] = 0;

       return *this;
    }

    // startpos and returned value are 0 based
    // A -1 is returned for not found
    int IndexOf(char ch, int startpos = 0) const
    {
       for (int i=startpos; i < pStr->len; i++)
          if (pStr->s[i] == ch)
             return i;

       return -1;
    }

    // startpos and returned value are 0 based
    // A -1 is returned for not found
    int IndexOf(char* s, int startpos = 0) const
    {
       int slen = (s) ? strlen(s) : 0;
       for (int i=startpos; slen && i < pStr->len-slen+1; i++)
          if (!memcmp(&(pStr->s[i]), s, slen))
             return i;

       return -1;
    }

    // startpos and returned value are 0 based
    // A -1 is returned for not found
    int IndexOfAnyBut(char* s, int startpos = 0) const
    {
       int i;
       for (i=startpos; s && i < pStr->len; i++)
       {
          int j;
          for (j=0; s[j]; j++)
             if (pStr->s[i] == s[j])
                break;
          if (j == strlen(s))
             return i;         // the ith character was not found in s
       }
       return -1;
    }

    // startpos and returned value are 0 based
    // A -1 is returned for not found
    int IndexOfAnyOf(char* s, int startpos = 0) const
    {
       for (int i=startpos; s && i < pStr->len; i++)
       {
          for (int j=0; s[j]; j++)
             if (pStr->s[i] == s[j])
                return i;
       }
       return -1;
    }

    // startpos is 0 based
    FCWString& Remove(int startpos, int length = 1)
    {
       makeunique();
       if (startpos >=0 && startpos < pStr->len)
       {
          if (length > (pStr->len - startpos))
             length = pStr->len - startpos;
          memcpy(&(pStr->s[startpos]), &(pStr->s[startpos+length]), pStr->len-startpos-length+1);
          pStr->len -= length;
          pStr->s[pStr->len] = 0;
       }
       return *this;
    }

    // startpos is 0 based
    int OccurencesOf(char ch, int startpos = 0) const
    {
       int count = 0;
       for (int i=startpos; i < pStr->len; i++)
          if (pStr->s[i] == ch)
             count++;

       return count;
    }

    // startpos is 0 based
    int OccurencesOf(FCWString& str, int startpos = 0) const
    {
       int count = 0;
       for (int i=startpos; i < pStr->len; i+=str.Length())
          if (!strncmp(&(pStr->s[i]), str, str.Length()))
             count++;

       return count;
    }

    // startpos is 0 based
    FCWString& Insert(char* s, int startpos)
    {
       makeunique();
       if (s && strlen(s) && startpos < pStr->len)
       {
          if (pStr->size < pStr->len+strlen(s))
             pStr->re_alloc(pStr->len+strlen(s));

          int tar=pStr->len+strlen(s)-1;
          int src=pStr->len-1;
          for (; src >= startpos; tar--, src--)
             pStr->s[tar] = pStr->s[src];

          memcpy(&(pStr->s[startpos]), s, strlen(s));
          pStr->len += strlen(s);
          pStr->s[pStr->len] = 0;
       }

       return *this;
    }

    // startpos is 0 based
    FCWString& Replace(char* target, char* replacement, int startpos=0)
    {
       if (target && replacement && strlen(target) && strlen(replacement))
       {
          for (int index = IndexOf(target, startpos);
               index>=0;
               index = IndexOf(target, index))
          {
             Remove(index, strlen(target));
             Insert(replacement, index);
          }
       }
       return *this;
    }

    FCWString& operator += (char *s)               // FCWString concatenation
    {
       makeunique();
       if (s && strlen(s))
       {
          if (pStr->size < pStr->len + strlen(s))
             pStr->re_alloc(pStr->len+strlen(s));

          strcpy( &(pStr->s[pStr->len]), s );
          pStr->len += strlen(s);
          pStr->s[pStr->len] = 0;
       }

       return *this;
    }

    FCWString& operator += (long l)
    {
       makeunique();
       char x[10];

       sprintf (x, "%ld", l);
       *this += x;

       return *this;
    }

    FCWString& operator +=  (FCWString const& s)
    {
       makeunique();
       if (pStr->size < pStr->len + s.pStr->len)
          pStr->re_alloc(pStr->len+s.pStr->len);

       memcpy( &(pStr->s[pStr->len]), s.pStr->s, s.pStr->len);
       pStr->len += s.pStr->len;
       pStr->s[pStr->len] = 0;

       return *this;
    }

    FCWString&  operator +=(char c)              /* FCWString concatenation*/
    {
       makeunique();
       if (pStr->size < pStr->len +1)
          pStr->re_alloc(pStr->len+1);

       pStr->s[pStr->len] = c;
       pStr->len++;
       pStr->s[pStr->len] = 0;

       return *this;
    }

    int AsInt()
    {
        return atoi(pStr->s);
    }

    FCWString  operator + (char *s)    /* FCWString concatenation          */
    {
       FCWString t(*this);
       t += s;

       return t;
    }

    FCWString operator + (FCWString const & s)
    {
       FCWString t(*this);
       t += s;

       return t;
    }

    FCWString operator + ( char c)
    {
       FCWString t(*this);
       t += c;

       return t;
    }

    friend ostream & operator << ( ostream & aStream,
                                   const FCWString & aString )
    {
      return aStream << (const char*) aString;
    }

};

// ---------------------------------------------------------------------
// Data item types...
// ---------------------------------------------------------------------
enum ItemType{ tSQLCHA=1,     tSQLBIN2=2,  tSQLBIN4=3,
               tSQLPACK=4,    tSQLHEX=5,   tSQLDBCS=6,
               tCHA=7,        tBIN2=8,     tBIN4=9,
               tBIN8=10,      tPACK=11,    tPACF=12,
               tNUM=13,       tNUMC=14,    tDBCS=15,
               tHEX=16,       tMIX=17,     tMAPCHA=18,             /* @6653*/
               tMAPNUM=19,    tMAPMIX=20,  tMAPDBCS=21,
               tMAP=22,       tRECORD=23,  tEZEDLPSB=24,
               tUIRBIN2=25,   tUIRBIN4=26, tUIRBIN8=27,
               tUIRCHA=28,    tUIRDBCS=29, tUIRHEX=30,
               tUIRNUM=31,    tUIRNUMC=32, tUIRPACK=33,
               tUIRPACF=34,   tUNICODE=35, tTBLUNICODE=36,           /* @A2*/
               tSQLUNICODE=37, tUIRUNICODE=38, tUIRMIX=39
               };

// --------------------------------------------------------------------
//            FCW process options for File/SQL
// --------------------------------------------------------------------
                                                //   used to be ...
const  int  INQUIRY_OPR  =  1;                  // 0x0001;
const  int  SETINQ_OPR   =  2;                  // 0x0002;
const  int  UPDATE_OPR   =  3;                  // 0x0004;
const  int  SETUPD_OPR   =  4;                  // 0x0008;
const  int  SCAN_OPR     =  5;                  // 0x0010;
const  int  ADD_OPR      =  6;                  // 0x0020;
const  int  REPLACE_OPR  =  7;                  // 0x0040;
const  int  DELETE_OPR   =  8;                  // 0x0080;
const  int  CLOSE_OPR    =  9;                  // 0x0100;
const  int  SQLEXEC_OPR  =  10;                 // 0x0200;

// --------------------------------------------------------------------
//            FCW File/SQL I/O status
// --------------------------------------------------------------------

const short rcNRF =  0x0001;
const short rcDUP =  0x0002;
const short rcUNQ =  0x0004;
const short rcDED =  0x0008;

const short rcHRD =  0x0010;
const short rcEOF =  0x0020;
const short rcERR =  0x0040;                                   // @7775

// *********************************************************************
// overflow values
// *********************************************************************
enum OverflowType { NO_OVERFLOW=0, MAX_OVERFLOW=1, USER_OVERFLOW=2 };

// ---------------------------------------------------------------------
//  global constants
// ---------------------------------------------------------------------
const int LENGTH_TABLE_NAME = 7;
const int LENGTH_ITEM_NAME = 32;

const int JULIAN_FORMAT = 0;
const int GREGORIAN_FORMAT = 1;
const int JULIAN_SHORT_FORMAT = 2;
const int GREGORIAN_SHORT_FORMAT = 3;

const int LENGTH_DB_NAME        = 18;

const int CONV_NORMAL           = 0;
const int CONV_REMOTE_CREATX    = 1;

#define   BUILD_DESCRIPTOR      "BUILDESC"

// -------------------------------------------------------------------
//    Macro for Generator
// -------------------------------------------------------------------
#define   FCWReturn          { PrcPop(); return; }

#define   FCWRTN()           { PrcPop(); return; }
#define   FCWCLOS()          { CtlMode=cm_End; PrcPop(); return; }
#define   FCWFLO()           { CtlMode=cm_ezeFlow; PrcPop(); return; }

#define   EZERTN()           { PrcPop(); return; }
#define   EZECLOS()          { CtlMode=cm_End; PrcPop(); return; }
#define   EZEFLO()           { CtlMode=cm_ezeFlow; PrcPop(); return; }

#define   EZEREPLY           EZEReply()
     /* -------------------------------------------------------------------*/
                        /* Rununit initialization and termination interface*/
     /* -------------------------------------------------------------------*/
enum  InitType { CICS, Native, CICSWebTrans, WebTrans };
enum  TermType { NormalExit, ErrorExit, SegmentExit, XferExit };
extern "C" void  RunUnitTerm( TermType ttype=ErrorExit );
extern "C" void  RunUnitInit( InitType itype=Native );
extern "C" void  WebtControl( );
void   SysCallRCLConstructors(void* addr);
void   SysCallRCLDestructors();

class TraceFile;
extern "C" TraceFile& Trace( );

// -------------------------------------------------------------------
//  main entry inlines into Workgroup Services
// -------------------------------------------------------------------
extern "C" int FCWRun (int argc, char* argv[]);

#if defined FCW_OS2
   #include <os2def.h>
   #define INCL_ERRORS
   #include <bseerr.h>
   #define INCL_DOSSEMAPHORES
   #include <bsedos.h>
   #if defined __IBMCPP__              /* if IBM C++ (OS2)                 */
      #define EXPORT
      #define SYSCALL _System

   #elif defined __BCPLUSPLUS__        /* if Borland C++ (OS2)             */
      #define EXPORT _export
      #define SYSCALL _stdcall
   #endif


#elif defined FCW_NT
   #include <windows.h>
   #define EXPORT
   #if defined FCW_VA_CPP
      #define SYSCALL __cdecl
   #else
      #define SYSCALL __cdecl        /* changed from __stdcall <ODBC> */
   #endif
   typedef int (SYSCALL *PFN)();

#elif defined FCW_UNIX || defined FCW_MVS /* @A1 */
   #define EXPORT
   #define SYSCALL
   #define _Optlink
   typedef unsigned long ULONG;
   typedef unsigned short USHORT;
   typedef unsigned char UCHAR;
   typedef int (*PFN)();
#endif

#include <cso2api.h>

typedef int (SYSCALL * PMAINAPP) (void);

extern "C"
{
typedef int (SYSCALL * PCALLAPP) ( ... );
}

// -------------------------------------------------------------------
// System independent call parameter list structure
// -------------------------------------------------------------------
#define FCWAPP    1
#define NONFCWAPP 0

struct FCWCallBlock
{
  int count;
  int callerFlag;
  struct
  {
    long  size;
    void* data;
  } parm[30];
};

typedef struct
{
  int   linktype;
  long  commsize;
  CMCOD BaseLinkage;
} FCWCICSLinkage;


// -------------------------------------------------------------------
// Call and Transfer options
// -------------------------------------------------------------------
#define OPT_FCW        0x00000000
#define OPT_NOREPLY    0x00000000
#define OPT_REPLY      0x00000001
#define OPT_NONFCW     0x00000002
#define OPT_NOMAPS     0x00000004
#define OPT_NOEXTEND   0x00000008
#define OPT_HIGHVALUES 0x00000010
#define OPT_AIXLOAD    0x00000020
#define OPT_APPLOAD    0x00000040
#define OPT_SYSLOAD    0x00000080

/*---------------------------------------------------------------------------*/
/* DLL handle types                                                          */
/*---------------------------------------------------------------------------*/
#if defined FCW_OS2
#define   APP_MODULE_TYPE     HMODULE
#define   FILE_MAP_HANDLE     PVOID

#elif defined FCW_NT
#define   APP_MODULE_TYPE     HMODULE
#define   FILE_MAP_HANDLE     HANDLE

#elif defined FCW_UNIX || defined FCW_MVS  /* @A1 */
typedef void* APP_MODULE_TYPE;
typedef void* FILE_MAP_HANDLE;
#endif

/***************************************************************************/
/* The TransInfo Structure and RunMode enum were moved from fcw.h          */
/* The Dll handle type section was moved from fcwsys.h                     */
/* These were moved because for NTCICS, the VAGEN application needed to    */
/* know about Transinfo and Runmode.                              D7557    */
/***************************************************************************/

/*-------------------------------------------------------------------------*/
/*  Transfer type information                                              */
/*-------------------------------------------------------------------------*/

enum TransType { dxfr, xfer, creatx, init };

struct TransInfo
{
  TransType       Type;
  FCWString       Appname;
  int             Options;
  char*           pBlock;
  TransInfo() :   pBlock(NULL), pMapBlock(NULL), pMapName(NULL) {};
  char*           pMapBlock;
  char*           pMapName;
  FILE_MAP_HANDLE pBlockHandle;
};

enum RunMode { normal, terminat, transfer, abend, segment, dxfer, xferwmap, xferwuir, xferwoap };

     /* -------------------------------------------------------------------*/
// Misc defines
// -------------------------------------------------------------------
#define ERROR_IN_CALLAPP 693
#define ERROR_IN_WEBAPP  899                                    // VG 4.0

enum InitKey   { key_dbms=1 };                                  // ODBC
enum InitValue { val_db2=1, val_odbc=2, val_oracle=4};

enum segType { segmented_Converse, segmented_Help, segmented_Message, segmented_UIR };

enum TimerControl { tc_start = 1, tc_stop = 2 };                // ODBC
extern "C" int TimeIt( TimerControl tc, char* msg );

#endif
