#ifndef _RPNPROC_H_INCLUDED
#define _RPNPROC_H_INCLUDED


#ifdef __cplusplus
extern "C" {
#endif



/*============================================================================*\
                                    INSTRUKCE
\*============================================================================*/


/*----------------------------------------------------------------------------*\
                            ZAKLADNI TYPY INSTRUKCI
\*----------------------------------------------------------------------------*/


// Generator jmen
//
#define  RPNPROC_NAMES(p)                                       \
{                                                               \
/* RPN stack                                                */  \
    p##_ENTER,          /* lift up, LIFT_FLAG=0             */  \
    p##_SWAP,           /* exchange X<->Y                   */  \
    p##_RDN,            /* roll down                        */  \
    p##_RUP,            /* roll up                          */  \
    p##_CLX,            /* X=0, LIFT_FLAG=0                 */  \
    p##_LASTX,          /* X=LASTx,                         */  \
    p##_IMOP,           /* X=immediate_operand              */  \
/* Stack operations (2 ops)                                 */  \
    p##_ADD,            /* X=Y+X                            */  \
    p##_SUB,            /* X=Y-X                            */  \
    p##_MUL,            /* X=Y*X                            */  \
    p##_DIV,            /* X=Y/X                            */  \
    p##_RMD,            /* X=Y%X                            */  \
    p##_OR,             /* X=Y|X                            */  \
    p##_XOR,            /* X=Y^X                            */  \
    p##_AND,            /* X=Y&X                            */  \
    p##_SLN,            /* X=Y<<X                           */  \
    p##_SRN,            /* X=Y>>X                           */  \
    p##_RLN,            /* X=Y rotate_left X                */  \
    p##_RRN,            /* X=Y rotate_right X               */  \
    p##_SB,             /* X=Y|1<<X                         */  \
    p##_CB,             /* X=Y&~(1<<X)                      */  \
    p##_BIT,            /* X=(Y&1<<X)!=0                    */  \
/* Stack operations (1 op)                                  */  \
    p##_CHS,            /* X=-X                             */  \
    p##_NOT,            /* X=~X                             */  \
    p##_SL1,            /* X=Y<<1                           */  \
    p##_SR1,            /* X=Y>>1                           */  \
    p##_RL1,            /* X=Y rotate_left 1                */  \
    p##_RR1,            /* X=Y rotate_right 1               */  \
    p##_MASKL,          /* X=(1<<X)-1<<wide-X               */  \
    p##_MASKR,          /* X=(1<<X)-1                       */  \
    p##_CONVB,          /* byte...                          */  \
    p##_CONVW,          /* ...word extension                */  \
/* Variables handling                                       */  \
    p##_STO,            /* variable=X (store)               */  \
    p##_STOADD,         /* variable+=X                      */  \
    p##_STOSUB,         /* variable-=X                      */  \
    p##_STOMUL,         /* variable*=X                      */  \
    p##_STODIV,         /* variable/=X                      */  \
    p##_RCL,            /* X=variable (recall)              */  \
    p##_RCLADD,         /* X+=variable                      */  \
    p##_RCLSUB,         /* X-=variable                      */  \
    p##_RCLMUL,         /* X*=variable                      */  \
    p##_RCLDIV,         /* X/=variable                      */  \
    p##_XCH,            /* exchange X<->varialbe            */  \
/* Branching                                                */  \
    p##_LBL,            /* label                            */  \
    p##_GTO,            /* go to                            */  \
    p##_XEQ,            /* execute (go sub)                 */  \
    p##_RTN,            /* return                           */  \
    p##_DSE,            /* decrement, skip if equal         */  \
    p##_ISG,            /* increment, skip if great         */  \
    p##_EQ,             /* X==Y                             */  \
    p##_NE,             /* X!=Y                             */  \
    p##_LT,             /* X<Y                              */  \
    p##_LE,             /* X<=Y                             */  \
    p##_GT,             /* X>Y                              */  \
    p##_GE,             /* X>=Y                             */  \
/* Directives                                               */  \
    p##_STOP,           /* stop execute job                 */  \
    p##_PSE,            /* pause, display intermediate data */  \
    p##_WIDE,           /* bit wide                         */  \
    p##_SGN,            /* signed                           */  \
    p##_UNS,            /* unsigned                         */  \
    p##_JOB,            /* link to continued job            */  \
    p##_END             /* end of job                       */  \
}


// Delky jednotlivych instrukci
//
#define  RPNPROC_ILEN_SIMPLE    sizeof(rpnproccode_t)
#define  RPNPROC_ILEN_PARAM     (sizeof(rpnproccode_t) + sizeof(rpnprocparam_t))
//
#define  RPNPROC_ILEN_ENTER     RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_SWAP      RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_RDN       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_RUP       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_CLX       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_LASTX     RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_IMOP      (sizeof(rpnproccode_t) + sizeof(rpnprocvalue_t))
#define  RPNPROC_ILEN_ADD       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_SUB       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_MUL       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_DIV       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_RMD       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_OR        RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_XOR       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_AND       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_SLN       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_SRN       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_RLN       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_RRN       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_SB        RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_CB        RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_BIT       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_CHS       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_NOT       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_SL1       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_SR1       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_RL1       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_RR1       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_MASKL     RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_MASKR     RPNPROC_ILEN_SIMPLE 
#define  RPNPROC_ILEN_CONVB     RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_CONVW     RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_STO       RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_STOADD    RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_STOSUB    RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_STOMUL    RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_STODIV    RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_RCL       RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_RCLADD    RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_RCLSUB    RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_RCLMUL    RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_RCLDIV    RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_XCH       RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_LBL       RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_GTO       RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_XEQ       RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_RTN       RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_DSE       RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_ISG       RPNPROC_ILEN_PARAM
#define  RPNPROC_ILEN_EQ        RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_NE        RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_LT        RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_LE        RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_GT        RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_GE        RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_STOP      RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_PSE       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_WIDE      RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_SGN       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_UNS       RPNPROC_ILEN_SIMPLE
#define  RPNPROC_ILEN_JOB       (sizeof(rpnproccode_t) + sizeof(rpnprocjobp_t))
#define  RPNPROC_ILEN_END       RPNPROC_ILEN_SIMPLE


// Textove podoby instrukci
//
#define  RPNPROC_TEXT_NONE      ""
//
#define  RPNPROC_TEXT_ENTER     "ENTER"
#define  RPNPROC_TEXT_SWAP      "x<>y"
#define  RPNPROC_TEXT_RDN       "Rdn"
#define  RPNPROC_TEXT_RUP       "Rup"
#define  RPNPROC_TEXT_CLX       "CLx"
#define  RPNPROC_TEXT_LASTX     "LASTx"
#define  RPNPROC_TEXT_IMOP      RPNPROC_TEXT_NONE
#define  RPNPROC_TEXT_ADD       "+"
#define  RPNPROC_TEXT_SUB       "-"
#define  RPNPROC_TEXT_MUL       "*"
#define  RPNPROC_TEXT_DIV       "/"
#define  RPNPROC_TEXT_RMD       "RMD"
#define  RPNPROC_TEXT_OR        "OR"
#define  RPNPROC_TEXT_XOR       "XOR"
#define  RPNPROC_TEXT_AND       "AND"
#define  RPNPROC_TEXT_SLN       "SLn"
#define  RPNPROC_TEXT_SRN       "SRn"
#define  RPNPROC_TEXT_RLN       "RLn"
#define  RPNPROC_TEXT_RRN       "RRn"
#define  RPNPROC_TEXT_SB        "SB"
#define  RPNPROC_TEXT_CB        "CB"
#define  RPNPROC_TEXT_BIT       "B?"
#define  RPNPROC_TEXT_CHS       "CHS"
#define  RPNPROC_TEXT_NOT       "NOT"
#define  RPNPROC_TEXT_SL1       "SL"
#define  RPNPROC_TEXT_SR1       "SR"
#define  RPNPROC_TEXT_RL1       "RL"
#define  RPNPROC_TEXT_RR1       "RR"
#define  RPNPROC_TEXT_MASKL     "MASKL"
#define  RPNPROC_TEXT_MASKR     "MASKR"
#define  RPNPROC_TEXT_CONVB     "CONVB"
#define  RPNPROC_TEXT_CONVW     "CONVW"
#define  RPNPROC_TEXT_STO       "STO"
#define  RPNPROC_TEXT_STOADD    "STO+"
#define  RPNPROC_TEXT_STOSUB    "STO-"
#define  RPNPROC_TEXT_STOMUL    "STO*"
#define  RPNPROC_TEXT_STODIV    "STO/"
#define  RPNPROC_TEXT_RCL       "RCL"
#define  RPNPROC_TEXT_RCLADD    "RCL+"
#define  RPNPROC_TEXT_RCLSUB    "RCL-"
#define  RPNPROC_TEXT_RCLMUL    "RCL*"
#define  RPNPROC_TEXT_RCLDIV    "RCL/"
#define  RPNPROC_TEXT_XCH       "x<>"
#define  RPNPROC_TEXT_LBL       "LBL"
#define  RPNPROC_TEXT_GTO       "GTO"
#define  RPNPROC_TEXT_XEQ       "XEQ"
#define  RPNPROC_TEXT_RTN       "RTN"
#define  RPNPROC_TEXT_DSE       "DSE"
#define  RPNPROC_TEXT_ISG       "ISG"
#define  RPNPROC_TEXT_EQ        "x=="
#define  RPNPROC_TEXT_NE        "x!="
#define  RPNPROC_TEXT_LT        "x<"
#define  RPNPROC_TEXT_LE        "x<="
#define  RPNPROC_TEXT_GT        "x>"
#define  RPNPROC_TEXT_GE        "x>="
#define  RPNPROC_TEXT_STOP      "STOP"
#define  RPNPROC_TEXT_PSE       "PSE"
#define  RPNPROC_TEXT_WIDE      "WIDE"
#define  RPNPROC_TEXT_SGN       "SGN"
#define  RPNPROC_TEXT_UNS       "UNS"
#define  RPNPROC_TEXT_JOB       RPNPROC_TEXT_NONE
#define  RPNPROC_TEXT_END       RPNPROC_TEXT_NONE


// Vygenerovany vycet instrukci
//
enum RPNPROC_NAMES(RPNPROC_TYPE);
//
#define  RPNPROC_TYPE_ISOK(t)   ((unsigned)(t) <= RPNPROC_TYPE_END)


/*----------------------------------------------------------------------------*\
                            ROZSIRENI TYPU INSTRUKCI
\*----------------------------------------------------------------------------*/


// Spolecna macra
//
#define _RPNPROC_XTYPE_SHIFT    6
#define _RPNPROC_XTYPE_MASK     (~((1 << _RPNPROC_XTYPE_SHIFT) - 1))
#define  RPNPROC_XTYPE_MAKE(v)  ((v) << _RPNPROC_XTYPE_SHIFT)


// "Immediate operand": RPNPROC_TYPE_WIDE...
// ...muze obsahovat 3 ciselne udaje (viz "LCN")...
//
#define  RPNPROC_XTYPE_IMOPLCN  1
//
#define  RPNPROC_CHAR_IMOPLCN   ','                 // ...takto oddelelne
#define  RPNPROC_XTYPE_ISLCN(x) (x)


// Bit wide: RPNPROC_TYPE_WIDE
//
#define  RPNPROC_XTYPE_BYTE     0
#define  RPNPROC_XTYPE_WORD     1
#define  RPNPROC_XTYPE_DWORD    2
#define  RPNPROC_CHRS_WIDE      {'B', 'W', 'D', '\0'}
// (instruction type extension --> bit wide)
#define  RPNPROC_XTYPE_X2W(x)   (1 << (x))          // bytes (1, 2, 4)
#define  RPNPROC_XTYPE_W2B(w)   ((w) * 8)           // bits  (8, 16, 32)


// Indirect: RPNPROC_TYPE_STO*, RPNPROC_TYPE_RCL*, RPNPROC_TYPE_XCH,
//           RPNPROC_TYPE_DSE,  RPNPROC_TYPE_ISG,
//           RPNPROC_TYPE_GTO,  RPNPROC_TYPE_XEQ
#define  RPNPROC_XTYPE_DIR      0                   // direct
#define  RPNPROC_XTYPE_IND      1                   // indirect
#define  RPNPROC_CHAR_IND       '@'
#define  RPNPROC_XTYPE_ISIND(x) (x)


// Compare: RPNPROC_TYPE_EQ, RPNPROC_TYPE_NE, RPNPROC_TYPE_LT,
//          RPNPROC_TYPE_LE, RPNPROC_TYPE_GT, RPNPROC_TYPE_GE
#define  RPNPROC_XTYPE_ZERO     0                   // compare with zero
#define  RPNPROC_XTYPE_YREG     1                   // compare with Y reg
#define  RPNPROC_CHRS_CMP       {'0', 'y', '\0', '\0'}



/*----------------------------------------------------------------------------*\
                        KOMPLETNI SORTIMENT INSTRUKCI
\*----------------------------------------------------------------------------*/


// Kod instrukce je vytvoren ze dvou hodnot
//
#define  RPNPROC_CODE_TYPE(c)   ((c) & ~_RPNPROC_XTYPE_MASK)
#define  RPNPROC_CODE_XTYPE(c)  ((c) >> _RPNPROC_XTYPE_SHIFT  &     \
                                _RPNPROC_XTYPE_MASK >> _RPNPROC_XTYPE_SHIFT)
#define  RPNPROC_NCODE(t, x)    (RPNPROC_TYPE_##t |                 \
                                 RPNPROC_XTYPE_MAKE(RPNPROC_XTYPE_##x))
#define  RPNPROC_CODE(t, x)     ((t) | RPNPROC_XTYPE_MAKE(x))


// Seznam kodu instrukci
//
#define  RPNPROC_CODE_ENTER     RPNPROC_TYPE_ENTER
#define  RPNPROC_CODE_SWAP      RPNPROC_TYPE_SWAP
#define  RPNPROC_CODE_RDN       RPNPROC_TYPE_RDN
#define  RPNPROC_CODE_RUP       RPNPROC_TYPE_RUP
#define  RPNPROC_CODE_CLX       RPNPROC_TYPE_CLX
#define  RPNPROC_CODE_LASTX     RPNPROC_TYPE_LASTX
#define  RPNPROC_CODE_IMOP      RPNPROC_TYPE_IMOP
#define  RPNPROC_CODE_ADD       RPNPROC_TYPE_ADD
#define  RPNPROC_CODE_SUB       RPNPROC_TYPE_SUB
#define  RPNPROC_CODE_MUL       RPNPROC_TYPE_MUL
#define  RPNPROC_CODE_DIV       RPNPROC_TYPE_DIV
#define  RPNPROC_CODE_RMD       RPNPROC_TYPE_RMD
#define  RPNPROC_CODE_OR        RPNPROC_TYPE_OR
#define  RPNPROC_CODE_XOR       RPNPROC_TYPE_XOR
#define  RPNPROC_CODE_AND       RPNPROC_TYPE_AND
#define  RPNPROC_CODE_SLN       RPNPROC_TYPE_SLN
#define  RPNPROC_CODE_SRN       RPNPROC_TYPE_SRN
#define  RPNPROC_CODE_RLN       RPNPROC_TYPE_RLN
#define  RPNPROC_CODE_RRN       RPNPROC_TYPE_RRN
#define  RPNPROC_CODE_SB        RPNPROC_TYPE_SB
#define  RPNPROC_CODE_CB        RPNPROC_TYPE_CB
#define  RPNPROC_CODE_BIT       RPNPROC_TYPE_BIT
#define  RPNPROC_CODE_CHS       RPNPROC_TYPE_CHS
#define  RPNPROC_CODE_NOT       RPNPROC_TYPE_NOT
#define  RPNPROC_CODE_SL1       RPNPROC_TYPE_SL1
#define  RPNPROC_CODE_SR1       RPNPROC_TYPE_SR1
#define  RPNPROC_CODE_RL1       RPNPROC_TYPE_RL1
#define  RPNPROC_CODE_RR1       RPNPROC_TYPE_RR1
#define  RPNPROC_CODE_MASKL     RPNPROC_TYPE_MASKL
#define  RPNPROC_CODE_MASKR     RPNPROC_TYPE_MASKR
#define  RPNPROC_CODE_CONVB     RPNPROC_TYPE_CONVB
#define  RPNPROC_CODE_CONVW     RPNPROC_TYPE_CONVW
#define  RPNPROC_CODE_STO       RPNPROC_TYPE_STO
#define  RPNPROC_CODE_STOADD    RPNPROC_TYPE_STOADD
#define  RPNPROC_CODE_STOSUB    RPNPROC_TYPE_STOSUB
#define  RPNPROC_CODE_STOMUL    RPNPROC_TYPE_STOMUL
#define  RPNPROC_CODE_STODIV    RPNPROC_TYPE_STODIV
#define  RPNPROC_CODE_RCL       RPNPROC_TYPE_RCL
#define  RPNPROC_CODE_RCLADD    RPNPROC_TYPE_RCLADD
#define  RPNPROC_CODE_RCLSUB    RPNPROC_TYPE_RCLSUB
#define  RPNPROC_CODE_RCLMUL    RPNPROC_TYPE_RCLMUL
#define  RPNPROC_CODE_RCLDIV    RPNPROC_TYPE_RCLDIV
#define  RPNPROC_CODE_XCH       RPNPROC_TYPE_XCH
#define  RPNPROC_CODE_ISTO      RPNPROC_NCODE(STO,   IND)
#define  RPNPROC_CODE_ISTADD    RPNPROC_NCODE(STADD, IND)
#define  RPNPROC_CODE_ISTSUB    RPNPROC_NCODE(STSUB, IND)
#define  RPNPROC_CODE_ISTMUL    RPNPROC_NCODE(STMUL, IND)
#define  RPNPROC_CODE_ISTDIV    RPNPROC_NCODE(STDIV, IND)
#define  RPNPROC_CODE_IRCL      RPNPROC_NCODE(RCL,   IND)
#define  RPNPROC_CODE_IRCADD    RPNPROC_NCODE(RCADD, IND)
#define  RPNPROC_CODE_IRCSUB    RPNPROC_NCODE(RCSUB, IND)
#define  RPNPROC_CODE_IRCMUL    RPNPROC_NCODE(RCMUL, IND)
#define  RPNPROC_CODE_IRCDIV    RPNPROC_NCODE(RCDIV, IND)
#define  RPNPROC_CODE_IXCH      RPNPROC_NCODE(XCH,  IND)
#define  RPNPROC_CODE_LBL       RPNPROC_TYPE_LBL
#define  RPNPROC_CODE_GTO       RPNPROC_TYPE_GTO
#define  RPNPROC_CODE_XEQ       RPNPROC_TYPE_XEQ
#define  RPNPROC_CODE_IGTO      RPNPROC_NCODE(GTO,   IND)
#define  RPNPROC_CODE_IXEQ      RPNPROC_NCODE(XEQ,   IND)
#define  RPNPROC_CODE_RTN       RPNPROC_TYPE_RTN
#define  RPNPROC_CODE_DSE       RPNPROC_TYPE_DSE
#define  RPNPROC_CODE_ISG       RPNPROC_TYPE_ISG
#define  RPNPROC_CODE_IDSE      RPNPROC_NCODE(DSE,   IND)
#define  RPNPROC_CODE_IISG      RPNPROC_NCODE(ISG,   IND)
#define  RPNPROC_CODE_EQ0       RPNPROC_NCODE(EQ,    ZERO)
#define  RPNPROC_CODE_NE0       RPNPROC_NCODE(NE,    ZERO)
#define  RPNPROC_CODE_LT0       RPNPROC_NCODE(LT,    ZERO)
#define  RPNPROC_CODE_LE0       RPNPROC_NCODE(LE,    ZERO)
#define  RPNPROC_CODE_GT0       RPNPROC_NCODE(GT,    ZERO)
#define  RPNPROC_CODE_GE0       RPNPROC_NCODE(GE,    ZERO)
#define  RPNPROC_CODE_EQY       RPNPROC_NCODE(EQ,    YREG)
#define  RPNPROC_CODE_NEY       RPNPROC_NCODE(NE,    YREG)
#define  RPNPROC_CODE_LTY       RPNPROC_NCODE(LT,    YREG)
#define  RPNPROC_CODE_LEY       RPNPROC_NCODE(LE,    YREG)
#define  RPNPROC_CODE_GTY       RPNPROC_NCODE(GT,    YREG)
#define  RPNPROC_CODE_GEY       RPNPROC_NCODE(GE,    YREG)
#define  RPNPROC_CODE_STOP      RPNPROC_TYPE_STOP
#define  RPNPROC_CODE_PSE       RPNPROC_TYPE_PSE
#define  RPNPROC_CODE_WIDEB     RPNPROC_NCODE(WIDE,  BYTE)
#define  RPNPROC_CODE_WIDEW     RPNPROC_NCODE(WIDE,  WORD)
#define  RPNPROC_CODE_WIDED     RPNPROC_NCODE(WIDE,  DWORD)
#define  RPNPROC_CODE_SGN       RPNPROC_TYPE_SGN
#define  RPNPROC_CODE_UNS       RPNPROC_TYPE_UNS
#define  RPNPROC_CODE_JOB       RPNPROC_TYPE_JOB
#define  RPNPROC_CODE_END       RPNPROC_TYPE_END



/*----------------------------------------------------------------------------*\
            INSTRUKCE PRO REALIZACI PROGRAMOVE SMYCKY: "DSE" & "ISG"
\*----------------------------------------------------------------------------*/


// Loop-Control Number ("c"=counter, "f"=final, "i"=increment)
//
#define _RPNPROC_LCN_SHIFT_CNT  0
#define _RPNPROC_LCN_MASK_CNT   0xFFFF
#define _RPNPROC_LCN_SHIFT_FNL  16
#define _RPNPROC_LCN_MASK_FNL   0x00FF
#define _RPNPROC_LCN_SHIFT_INC  24
#define _RPNPROC_LCN_MASK_INC   0x00FF
//
#define _RPNPROC_LCN_MAKE(k, v) (((v) & _RPNPROC_LCN_MASK_##k) <<       \
                                                    _RPNPROC_LCN_SHIFT_##k)
#define  RPNPROC_LCN_GET(k, a)  ((a) >> _RPNPROC_LCN_SHIFT_##k  &       \
                                                    _RPNPROC_LCN_MASK_##k)
#define  RPNPROC_LCN_SET(k, a, v)                                       \
                                ((a) & ~_RPNPROC_LCN_MAKE(k, ~0) |      \
                                                    _RPNPROC_LCN_MAKE(k, (v)))
//
#define  RPNPROC_LCN(c, f, i)   (_RPNPROC_LCN_MAKE(CNT, c) |            \
                                 _RPNPROC_LCN_MAKE(FNL, f) |            \
                                 _RPNPROC_LCN_MAKE(INC, i))



/*============================================================================*\
                                    TYPY
\*============================================================================*/


// Kod instrukce
//
typedef unsigned char           rpnproccode_t;


// Parametr instrukce
//
#define  RPNPROC_PARAM_LIMIT    1000
//
typedef unsigned short          rpnprocparam_t;


// Hodnota vypoctu
//
typedef unsigned long           rpnprocvalue_t;


// Program (job) (pointer)
//
typedef rpnproccode_t           *rpnprocjobp_t;


// Handle
//
typedef struct rpnprochndls     *rpnprochndp_t;


// Hodnoty pro trasovani programu
//
#define  RPNPROC_LBLIDX_INVAL   (-1)
#define  RPNPROC_LBLIDX_ISOK(i) ((i) >= 0)
//
typedef struct
{
    int             lblidx;     // cislo navesti
    unsigned        lineno;     // cislo radku (pocitano od aktualniho navesti)
} rpnproctrace_t;
//
typedef struct
{
    rpnproctrace_t  tracev;
    rpnprocjobp_t   curjobp;    // aktualni pozice v programu
} rpnproctrcjob_t;




/*----------------------------------------------------------------------------*\
                            VYTVORENI PROGRAMU STATICKY
\*----------------------------------------------------------------------------*/


// Tvary instrukci ukladanych do statickeho pole "rpnprocjobt_t"
//
#define  RPNPROC_ST_ENTER       RPNPROC_CODE_ENTER
#define  RPNPROC_ST_SWAP        RPNPROC_CODE_SWAP
#define  RPNPROC_ST_RDN         RPNPROC_CODE_RDN
#define  RPNPROC_ST_RUP         RPNPROC_CODE_RUP
#define  RPNPROC_ST_CLX         RPNPROC_CODE_CLX
#define  RPNPROC_ST_LASTX       RPNPROC_CODE_LASTX
#define  RPNPROC_ST_IMOP(i)     RPNPROC_ST_32BIT(IMOP,   (i))
#define  RPNPROC_ST_ADD         RPNPROC_CODE_ADD
#define  RPNPROC_ST_SUB         RPNPROC_CODE_SUB
#define  RPNPROC_ST_MUL         RPNPROC_CODE_MUL
#define  RPNPROC_ST_DIV         RPNPROC_CODE_DIV
#define  RPNPROC_ST_RMD         RPNPROC_CODE_RMD
#define  RPNPROC_ST_OR          RPNPROC_CODE_OR
#define  RPNPROC_ST_XOR         RPNPROC_CODE_XOR
#define  RPNPROC_ST_AND         RPNPROC_CODE_AND
#define  RPNPROC_ST_SLN         RPNPROC_CODE_SLN
#define  RPNPROC_ST_SRN         RPNPROC_CODE_SRN
#define  RPNPROC_ST_RLN         RPNPROC_CODE_RLN
#define  RPNPROC_ST_RRN         RPNPROC_CODE_RRN
#define  RPNPROC_ST_SB          RPNPROC_CODE_SB
#define  RPNPROC_ST_CB          RPNPROC_CODE_CB
#define  RPNPROC_ST_BIT         RPNPROC_CODE_BIT
#define  RPNPROC_ST_CHS         RPNPROC_CODE_CHS
#define  RPNPROC_ST_NOT         RPNPROC_CODE_NOT
#define  RPNPROC_ST_SL1         RPNPROC_CODE_SL1
#define  RPNPROC_ST_SR1         RPNPROC_CODE_SR1
#define  RPNPROC_ST_RL1         RPNPROC_CODE_RL1
#define  RPNPROC_ST_RR1         RPNPROC_CODE_RR1
#define  RPNPROC_ST_MASKL       RPNPROC_CODE_MASKL
#define  RPNPROC_ST_MASKR       RPNPROC_CODE_MASKR
#define  RPNPROC_ST_CONVB       RPNPROC_CODE_CONVB
#define  RPNPROC_ST_CONVW       RPNPROC_CODE_CONVW
#define  RPNPROC_ST_STO(p)      RPNPROC_ST_PARAM(STO
#define  RPNPROC_ST_STOADD(p)   RPNPROC_ST_PARAM(STOADD, (p))
#define  RPNPROC_ST_STOSUB(p)   RPNPROC_ST_PARAM(STOSUB, (p))
#define  RPNPROC_ST_STOMUL(p)   RPNPROC_ST_PARAM(STOMUL, (p))
#define  RPNPROC_ST_STODIV(p)   RPNPROC_ST_PARAM(STODIV, (p))
#define  RPNPROC_ST_RCL(p)      RPNPROC_ST_PARAM(RCL,    (p))
#define  RPNPROC_ST_RCLADD(p)   RPNPROC_ST_PARAM(RCLADD, (p))
#define  RPNPROC_ST_RCLSUB(p)   RPNPROC_ST_PARAM(RCLSUB, (p))
#define  RPNPROC_ST_RCLMUL(p)   RPNPROC_ST_PARAM(RCLMUL, (p))
#define  RPNPROC_ST_RCLDIV(p)   RPNPROC_ST_PARAM(RCLDIV, (p))
#define  RPNPROC_ST_XCH(p)      RPNPROC_ST_PARAM(XCH,   (p))
#define  RPNPROC_ST_ISTO(p)     RPNPROC_ST_PARAM(ISTO,   (p))
#define  RPNPROC_ST_ISTADD(p)   RPNPROC_ST_PARAM(ISTADD, (p))
#define  RPNPROC_ST_ISTSUB(p)   RPNPROC_ST_PARAM(ISTSUB, (p))
#define  RPNPROC_ST_ISTMUL(p)   RPNPROC_ST_PARAM(ISTMUL, (p))
#define  RPNPROC_ST_ISTDIV(p)   RPNPROC_ST_PARAM(ISTDIV, (p))
#define  RPNPROC_ST_IRCL(p)     RPNPROC_ST_PARAM(IRCL,   (p))
#define  RPNPROC_ST_IRCADD(p)   RPNPROC_ST_PARAM(IRCADD, (p))
#define  RPNPROC_ST_IRCSUB(p)   RPNPROC_ST_PARAM(IRCSUB, (p))
#define  RPNPROC_ST_IRCMUL(p)   RPNPROC_ST_PARAM(IRCMUL, (p))
#define  RPNPROC_ST_IRCDIV(p)   RPNPROC_ST_PARAM(IRCDIV, (p))
#define  RPNPROC_ST_IXCH(p)     RPNPROC_ST_PARAM(IXCH,  (p))
#define  RPNPROC_ST_LBL(p)      RPNPROC_ST_PARAM(LBL,    (p))
#define  RPNPROC_ST_GTO(p)      RPNPROC_ST_PARAM(GTO,    (p))
#define  RPNPROC_ST_XEQ(p)      RPNPROC_ST_PARAM(XEQ,    (p))
#define  RPNPROC_ST_IGTO(p)     RPNPROC_ST_PARAM(IGTO,   (p))
#define  RPNPROC_ST_IXEQ(p)     RPNPROC_ST_PARAM(IXEQ,   (p))
#define  RPNPROC_ST_RTN         RPNPROC_CODE_RTN
#define  RPNPROC_ST_DSE(p)      RPNPROC_ST_PARAM(DSE,    (p))
#define  RPNPROC_ST_ISG(p)      RPNPROC_ST_PARAM(ISG,    (p))
#define  RPNPROC_ST_IDSE(p)     RPNPROC_ST_PARAM(IDSE,   (p))
#define  RPNPROC_ST_IISG(p)     RPNPROC_ST_PARAM(IISG,   (p))
#define  RPNPROC_ST_EQ0         RPNPROC_CODE_EQ0
#define  RPNPROC_ST_NE0         RPNPROC_CODE_NE0
#define  RPNPROC_ST_LT0         RPNPROC_CODE_LT0
#define  RPNPROC_ST_LE0         RPNPROC_CODE_LE0
#define  RPNPROC_ST_GT0         RPNPROC_CODE_GT0
#define  RPNPROC_ST_GE0         RPNPROC_CODE_GE0
#define  RPNPROC_ST_EQY         RPNPROC_CODE_EQY
#define  RPNPROC_ST_NEY         RPNPROC_CODE_NEY
#define  RPNPROC_ST_LTY         RPNPROC_CODE_LTY
#define  RPNPROC_ST_LEY         RPNPROC_CODE_LEY
#define  RPNPROC_ST_GTY         RPNPROC_CODE_GTY
#define  RPNPROC_ST_GEY         RPNPROC_CODE_GEY
#define  RPNPROC_ST_STOP        RPNPROC_CODE_STOP
#define  RPNPROC_ST_PSE         RPNPROC_CODE_PSE
#define  RPNPROC_ST_WIDEB       RPNPROC_CODE_WIDEB
#define  RPNPROC_ST_WIDEW       RPNPROC_CODE_WIDEW
#define  RPNPROC_ST_WIDED       RPNPROC_CODE_WIDED
#define  RPNPROC_ST_SGN         RPNPROC_CODE_SGN
#define  RPNPROC_ST_UNS         RPNPROC_CODE_UNS
#define  RPNPROC_ST_JOB(d)      RPNPROC_ST_32BIT(JOB,    (d))
#define  RPNPROC_ST_END         RPNPROC_CODE_END


// Macra pro ukladani instrukci
//
#ifdef   RPNPROC_ENDIAN_BIG
#define _RPNPROC_ST_SHIFT_4TH   0
#define _RPNPROC_ST_SHIFT_3RD   8
#define _RPNPROC_ST_SHIFT_2ND   16
#define _RPNPROC_ST_SHIFT_1ST   24
#else
#define _RPNPROC_ST_SHIFT_1ST   0
#define _RPNPROC_ST_SHIFT_2ND   8
#define _RPNPROC_ST_SHIFT_3RD   16
#define _RPNPROC_ST_SHIFT_4TH   24
#endif
#define _RPNPROC_ST_BYTE(s, v)  (v) >> _RPNPROC_ST_SHIFT_##s  &  0xFF
#define  RPNPROC_ST_PARAM(c, p) RPNPROC_CODE_##c,   _RPNPROC_ST_BYTE(1ST, p), \
                                                    _RPNPROC_ST_BYTE(2ND, p),
#define  RPNPROC_ST_32BIT(c, i) RPNPROC_CODE_##c,   _RPNPROC_ST_BYTE(1ST, i), \
                                                    _RPNPROC_ST_BYTE(2ND, i), \
                                                    _RPNPROC_ST_BYTE(3RD, i), \
                                                    _RPNPROC_ST_BYTE(4TH, i)


// Program (job) (pole pro staticke pouziti)
//
typedef rpnproccode_t           rpnprocjobt_t[];



/*============================================================================*\
                        MEZNI HODNOTY (VELIKOSTI POLI)
\*============================================================================*/


#define  RPNPROC_SIZE_STACK     4       // velikost RPN stacku
#define  RPNPROC_SIZE_RTN       32      // pocet urovni navratovych adres



/*============================================================================*\
                                PROTOTYPY FUNKCI
\*============================================================================*/


// Navratove hodnoty callback funkci
//
#define  RPNPROC_CB_CONT        0       // pokracovat v cinnosti
#define  RPNPROC_CB_BREAK       (-1)    // zastavit provadeni


/*----------------------------------------------------------------------------*\
                                PROVADENI PROGRAMU
\*----------------------------------------------------------------------------*/


// Vytvoreni struktury promennych teto vrstvy - pointer na tuto je "handle".
//
#define  Rpnprocinit(f, v, l)   rpnproc_initial(f(rpnproc_memsize((v), (l))),  \
                                                                  (v), (l))
#define  Rpnprocinitpgmonly(f)  Rpnprocinit(f, 0,   0)
#define  Rpnprocinitvar(f, v)   Rpnprocinit(f, (v), 0)
#define  Rpnprocinitlbl(f, l)   Rpnprocinit(f, 0,   (l))
#define  Rpnprocinitlimit(f)    Rpnprocinit(f, ~0,  ~0)
//
extern unsigned                 rpnproc_memsize(unsigned __varnum,
                                                unsigned __lblnum);
extern rpnprochndp_t            rpnproc_initial(rpnprochndp_t,
                                                unsigned __varnum,
                                                unsigned __lblnum);


// Callback funkce (vraci "RPNPROC_CB_*")
//
// (rozliseni udalosti - hodnoty parametru "__execb")
enum
{
    RPNPROC_EXECB_TRACE = 0,    // before all instruction
    RPNPROC_EXECB_PSE,          // "pause", display intermediate data
    RPNPROC_EXECB_DIVBY0,       // divide by zero
    RPNPROC_EXECB_VARRNG,       // variable index out of range
    RPNPROC_EXECB_LBLRNG,       // label out of range
    RPNPROC_EXECB_LBLDUP,       // duplicated label
    RPNPROC_EXECB_LBLNEX,       // nonexistent label
    RPNPROC_EXECB_RTNOVF,       // return stack overflow
    RPNPROC_EXECB_ILLTYPE       // illegal instruction type
};
// (hodnoty vztazene k udalosti)
typedef struct
{
    rpnprocvalue_t  stackx;     // X registr RPN stacku
    rpnproctrcjob_t trcjobv;    // trasovani programu
} rpnprocexeval_t;
//
typedef int                     (*rpnprocexecb_t)(int  __execb,
                                                  rpnprocexeval_t *,
                                                  void *__userdata);


// Zjisteni adresy programu podle navesti
//
extern rpnprocjobp_t            rpnproc_getjob(rpnprochndp_t,
                                                int __lblidx);


// Nastaveni provadeneho programu (job)
//
extern int                      rpnproc_setjob(rpnprochndp_t,
                                               rpnprocjobp_t,
                                               rpnprocexecb_t,
                                               void *__userdata);



// Ziskani pointeru na promennou (pro vycteni nebo naplneni hodnotou)
//
extern rpnprocvalue_t           *rpnproc_variable(rpnprochndp_t,
                                                 unsigned __varidx,
                                                 int      __indf);


// Vstup hodnoty na RPN-stack
//
extern void                     rpnproc_enter(rpnprochndp_t, rpnprocvalue_t);


// Spusteni provadeni programu
//
extern rpnprocvalue_t           rpnproc_execute(rpnprochndp_t,
                                                int __lblidx,
                                                int __tracef);



/*============================================================================*\
                        TEXTOVA PODOBA PROGRAMU
\*============================================================================*/


// Delka jedne radky programu
//
#define  RPNPROC_LINE_SIZE      32



/*----------------------------------------------------------------------------*\
                    VYTVORENI PROGRAMU Z TEXTOVE PODOBY
\*----------------------------------------------------------------------------*/


// Seznam povolenych oddelovacu parametru od instrukce
//
#define  RPNPROC_MAKEJOB_CHRS  {037, 036, 035, 034, 033, 032, 031, 030,     \
                                027, 026, 025, 024, 023, 022, 021, 020,     \
                                017, 016, 015, 014, 013, 012, 011, 010,     \
                                007, 006, 005, 004, 003, 002, 001, 040, 000}



// Callback funkce (vraci "RPNPROC_CB_*")
//
// (rozliseni udalosti - hodnoty parametru "__execb")
enum
{
    RPNPROC_MKJCB_MEMJOB,           // pozadavek na prideleni pameti pro program
    RPNPROC_MKJCB_LINE              // pozadavek na (dalsi) radku programu
};
// (hodnoty vztazene k pozadavku)
//
typedef union
{
    struct
    {
        rpnprocjobp_t   jobp;       // pridelena pamet...
        int             size;       // ...a jeji velikost
    } memjob;
    char                linet[RPNPROC_LINE_SIZE];
                                    // vyzadana radka programu
} rpnprocmkjval_t;
//
typedef int             (*rpnprocmkjcb_t)(int  __mkjcb,
                                          rpnprocmkjval_t *,
                                          void *__userdata);


// Spusteni vytvareni programu
//
enum   {RPNPROC_MAKEJOB_OK = 0,
        RPNPROC_MAKEJOB_NUMBER,     // nesedi pocet parametru
        RPNPROC_MAKEJOB_INSTR,      // chyba pri urceni instrukce...
        RPNPROC_MAKEJOB_PARAM,      // ...nebo parametru
        RPNPROC_MAKEJOB_STORE,      // meznama velikost (wide) parametru
        RPNPROC_MAKEJOB_MEMORY};    // nebyl uspokojen pozadavek na pamet
//
extern int      rpnproc_makejob(unsigned *__varnump,
                                unsigned *__lblnump,
                                rpnprocmkjcb_t,
                                void     *__userdata);



/*----------------------------------------------------------------------------*\
                        VYPIS PROGRAMU V TEXTOVE PODOBE
\*----------------------------------------------------------------------------*/


// Hodnoty "rpnproclsjval_t.radix"
//
#define  RPNPROC_LIST_RADIX_UNS     10      // DEC unsigned
#define  RPNPROC_LIST_RADIX_SGN     (-10)   // DEC signed
#define  RPNPROC_LIST_RADIX_OCT     8
#define  RPNPROC_LIST_RADIX_HEX     16


// Hodnoty "rpnproclsjval_t.delim"
//
#define _RPNPROC_DELIM_SHIFT_NLBL   0       // znaky pro neexisujici navesti
#define _RPNPROC_DELIM_SHIFT_ADDR   8       // oddelovac navesti od cisla radku
#define _RPNPROC_DELIM_SHIFT_INSTR  16      // oddelovac instrukce od adresy
#define _RPNPROC_DELIM_SHIFT_PARAM  24      // oddelovac parametru od instrukce
#define _RPNPROC_DELIM_MAKE(k, c)   (((c) & 0x00FF) << _RPNPROC_DELIM_SHIFT_##k)
#define _RPNPROC_DELIM_GET(k, d)    ((d) >> _RPNPROC_DELIM_SHIFT_##k  &  0x00FF)
//
#define  RPNPROC_LIST_DELIM(n, a, i, p)                                 \
                                   (_RPNPROC_DELIM_MAKE(NLBL,  (n)) |   \
                                    _RPNPROC_DELIM_MAKE(ADDR,  (a)) |   \
                                    _RPNPROC_DELIM_MAKE(INSTR, (i)) |   \
                                    _RPNPROC_DELIM_MAKE(PARAM, (p)))
#define  RPNPROC_LIST_DELIM_DEFLT   RPNPROC_LIST_DELIM('#', ':', '\t', ' ')


// Callback funkce nabizenici radku programu (vraci "RPNPROC_CB_*")
//
typedef int     (*rpnproclsjcb_t)(char __linetxt[], void *__userdata);


// Spolecne hodnoty pro funkce "rpnproc_listjob()" a "rpnproc_listone()"
//
typedef struct
{
    int             radix;                  // RPNPROC_LIST_RADIX_*
    unsigned long   delim;                  // RPNPROC_LIST_DELIM*
    rpnproclsjcb_t  fncp;
    void            *userdata;
} rpnproclsjval_t;


// Spusteni vytvareni vypisu
//
extern int      rpnproc_listjob(rpnprocjobp_t, rpnproclsjval_t *);


// Vypis jedne instrukce (jedne radky)
//
extern int      rpnproc_listone(rpnproctrcjob_t *, rpnproclsjval_t *);


// Konstanty popisujici vypis
//
#define  RPNPROC_LIST_DIGITS_LBLIDX 3       // pocet mist navesti...
#define  RPNPROC_LIST_DIGITS_LINENO 4       // ...a cisla radku
#define  RPNPROC_LIST_DIGITS_PARAM  RPNPROC_LIST_DIGITS_LBLIDX
//
#define  RPNPROC_LIST_RADIX_LBLIDX  RPNPROC_LIST_RADIX_UNS
#define  RPNPROC_LIST_RADIX_LINENO  RPNPROC_LIST_RADIX_UNS
#define  RPNPROC_LIST_RADIX_PARAM   RPNPROC_LIST_RADIX_LBLIDX


#ifdef __cplusplus
}
#endif


#endif
