home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / MISC / LO241SRV.ZIP / LRPN.C < prev    next >
C/C++ Source or Header  |  1998-05-17  |  16KB  |  608 lines

  1.  
  2. // LoraBBS Version 2.41 Free Edition
  3. // Copyright (C) 1987-98 Marco Maccaferri
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 2 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. /*
  20. ** RPN Engine for LoraBBS 2.3x
  21. **
  22. ** Scritto da Riccardo De Agostini
  23. **
  24. ** NOTA: Questo file e` stato scritto con un Tab size di 4 caratteri.
  25. */
  26.  
  27. /*
  28. ** HEADER UTILIZZATI
  29. */
  30. #include <stdio.h>
  31. #include <limits.h>
  32.  
  33. #include "lsetup.h"
  34. #include "sched.h"
  35. #include "msgapi.h"
  36. #include "externs.h"
  37. #include "prototyp.h"
  38. #include "lrpn.h"
  39.  
  40. extern int ansi_attr;
  41. extern char vx, vy;
  42.  
  43. /*
  44. ** COSTANTI
  45. */
  46. #define _FALSE   0
  47. #define _TRUE    1
  48. #define MAX_STP  (RPN_STACKSIZE - 1)
  49.  
  50. static const long  flagval[32] =  {
  51.     0x80000000L,    /* Flag 0 */
  52.     0x40000000L,    /* Flag 1 */
  53.     0x20000000L,    /* Flag 2 */
  54.     0x10000000L,    /* Flag 3 */
  55.     0x08000000L,    /* Flag 4 */
  56.     0x04000000L,    /* Flag 5 */
  57.     0x02000000L,    /* Flag 6 */
  58.     0x01000000L,    /* Flag 7 */
  59.     0x00800000L,    /* Flag 8 */
  60.     0x00400000L,    /* Flag 9 */
  61.     0x00200000L,    /* Flag A */
  62.     0x00100000L,    /* Flag B */
  63.     0x00080000L,    /* Flag C */
  64.     0x00040000L,    /* Flag D */
  65.     0x00020000L,    /* Flag E */
  66.     0x00010000L,    /* Flag F */
  67.     0x00008000L,    /* Flag G */
  68.     0x00004000L,    /* Flag H */
  69.     0x00002000L,    /* Flag I */
  70.     0x00001000L,    /* Flag J */
  71.     0x00000800L,    /* Flag K */
  72.     0x00000400L,    /* Flag L */
  73.     0x00000200L,    /* Flag M */
  74.     0x00000100L,    /* Flag N */
  75.     0x00000080L,    /* Flag O */
  76.     0x00000040L,    /* Flag P */
  77.     0x00000020L,    /* Flag Q */
  78.     0x00000010L,    /* Flag R */
  79.     0x00000008L,    /* Flag S */
  80.     0x00000004L,    /* Flag T */
  81.     0x00000002L,    /* Flag U */
  82.     0x00000001L        /* Flag V */
  83. };
  84.  
  85. /*
  86. ** DATI PRIVATI DEL MODULO
  87. */
  88. static short        uvar[RPN_NVAR];            /* Variabili utente             */
  89. static short        stack[RPN_STACKSIZE];    /* Stack                        */
  90. static short        stp;                    /* Stack pointer                */
  91. static short        acc;                    /* Accumulatore                 */
  92. static bool         acc_reset;                /* TRUE = La prossima cifra     */
  93.                                             /*  resettera` l'accumulatore   */
  94. /*
  95. ** PROTOTIPI DELLE FUNZIONI PRIVATE DEL MODULO
  96. */
  97. short get_usr(short);
  98. void set_usr(short, short);
  99.  
  100. /*
  101. ** MACRO
  102. */
  103. #define PUSH(x)    if (stp < MAX_STP) stp++; stack[stp] = (x)
  104. #define POP()      (stp < 0 ? 0 : stack[stp--])
  105. #define ABS(x)     ((x) < 0 ? -(x) : (x))
  106.  
  107. /*==========================================================================*/
  108.  
  109. /*
  110. ** Funzione  : rpnInit
  111. ** Scopo     : Inizializza RPN Engine
  112. ** Parametri : u - Il puntatore ad una struct _usr che definisce i dati
  113. **                 dell'utente
  114. ** Ritorna   :
  115. ** Note      : - Questa funzione DEVE essere chiamata prima di utilizzare
  116. **               una qualsiasi altra funzione di RPN Engine, nonche` ogni
  117. **               volta si desideri, per qualsiasi motivo, reinizializzare
  118. **               lo stack e le variabili utente.
  119. */
  120. void rpnInit (void)
  121. {
  122.     register short  i;
  123.     register short  *p;
  124.  
  125.     /*
  126.     ** Inizializza il puntatore allo stack
  127.     */
  128.     stp = -1;
  129.     /*
  130.     ** Inizializza le variabili utente
  131.     */
  132.     for (i = 0, p = uvar; i < RPN_NVAR; i++, *(p++) = 0);
  133. }
  134.  
  135. /*
  136. ** Funzione  : rpnProcessChar
  137. ** Scopo     : Processa un singolo carattere
  138. ** Parametri : c - Il carattere in questione
  139. ** Ritorna   :
  140. ** Note      : - La funzione non ritorna alcun codice di errore
  141. **             - I caratteri non riconosciuti vengono ignorati, cosi` come
  142. **               le indirezioni illecite su variabili o campi del
  143. **               record utente
  144. **             - Anche se eventuali stack overflow o underflow sono gestiti
  145. **               in modo da non incasinare il sistema, occorre fare
  146. **               attenzione in fase di sviluppo delle schermate; ad esempio,
  147. **               se si vogliono passare dei parametri tramite lo stack ad una
  148. **               schermata e questa non e` presente su disco, lo stack
  149. **               conterra` valori "in piu`" e alla lunga l'overflow sara`
  150. **               assicurato
  151. **
  152. */
  153. void rpnProcessChar(int c)
  154. {
  155.     short tmp;
  156.     long ltmp;
  157.  
  158.     /*
  159.     ** Cifre da 0 a 9
  160.     */
  161.     if ((c >= '0') && (c <= '9')) {
  162.         if (acc_reset) {
  163.             PUSH(acc);
  164.             acc = 0;
  165.             acc_reset = FALSE;
  166.         }
  167.         /*
  168.         ** Un modo come un altro per evitare l'overflow
  169.         */
  170.         ltmp = (long)acc * 10 + c - '0';
  171.         acc =  ltmp > 32767L ? 32767 : ltmp & 0xFFFF;
  172.         return;
  173.     }
  174.     switch (c) {
  175.         /*
  176.         ** Interazione diretta con lo stack
  177.         */
  178.         case ',':       /* Inserimento accumulatore nello stack                     */
  179.         PUSH(acc);
  180.         acc = 0;
  181.         acc_reset = FALSE;
  182.         break;
  183.     case '@':    /* Estrazione valore dallo stack nell'accumulatore          */
  184.         acc = POP();
  185.         acc_reset = TRUE;
  186.         break;
  187.     case '\"':    /* Scambio tra l'accumulatore e lo stack                    */
  188.         if (stp < 0) {
  189.             acc = 0;
  190.         } else {
  191.             tmp = acc;
  192.             acc = stack[stp];
  193.             stack[stp] = tmp;
  194.         }
  195.         acc_reset = TRUE;
  196.         break;
  197.     /*
  198.     ** Operatori matematici binari
  199.     ** (qui per stack si intende, per brevita`, l'ultimo elemento inserito)
  200.     */
  201.     case '+':    /* Addizione tra l'accumulatore e lo stack                  */
  202.         acc += POP();
  203.         acc_reset = TRUE;
  204.         break;
  205.     case '-':    /* Sottrazione dell'accumulatore dallo stack                */
  206.         acc = POP() - acc;
  207.         acc_reset = TRUE;
  208.         break;
  209.     case '*':    /* Moltiplicazione dello stack per l'accumulatore           */
  210.         acc = ((long)acc * POP()) & 0xFFFF;
  211.         acc_reset = TRUE;
  212.         break;
  213.     case '/':    /* Divisione tra lo stack e l'accumulatore                  */
  214.         if (acc == 0) {
  215.             acc = POP() < 0 ? SHRT_MIN : SHRT_MAX;
  216.         } else {
  217.             acc = POP() / acc;
  218.         }
  219.         acc_reset = TRUE;
  220.         break;
  221.     case '%':    /* Resto della divisione tra lo stack e l'accumulatore      */
  222.         if (acc == 0) {
  223.             (void)POP();
  224.         } else {
  225.             acc = POP() % acc;
  226.         }
  227.         acc_reset = TRUE;
  228.         break;
  229.     case 'L':    /* Shift a sinistra                                         */
  230.         acc = POP() << ABS(acc);
  231.         acc_reset = TRUE;
  232.         break;
  233.     case 'R':    /* Shift a destra                                           */
  234.         tmp = ABS(acc);
  235.         if (tmp) {
  236.             acc = (POP() >> 1) & 0x7FFF;
  237.             acc >>= --tmp;
  238.         } else {
  239.             (void)POP();
  240.                 }
  241.                 acc_reset = TRUE;
  242.         break;
  243.     /*
  244.     ** Operatori matematici unari
  245.     */
  246.     case '_':    /* Cambio segno dell'accumulatore                           */
  247.         acc = -acc;
  248.         acc_reset = TRUE;
  249.         break;
  250.     case '\'':    /* Valore assoluto dell'accumulatore                        */
  251.         acc = ABS(acc);
  252.         acc_reset = TRUE;
  253.         break;
  254.     case '$':    /* Segno dell'accumulatore (-1 se < 0, 0 se 0, 1 se > 0)    */
  255.         if (acc) {
  256.             acc = (acc < 0) ? -1 : 1;
  257.         }
  258.         acc_reset = TRUE;
  259.         break;
  260.     /*
  261.     ** Operatori logici e bitwise binari
  262.     */
  263.     case '&':    /* Bitwise AND                                              */
  264.         acc &= POP();
  265.         acc_reset = TRUE;
  266.         break;
  267.     case '|':    /* Bitwise OR                                               */
  268.         acc |= POP();
  269.         acc_reset = TRUE;
  270.         break;
  271.     case '^':    /* Bitwise XOR                                              */
  272.         acc ^= POP();
  273.         acc_reset = TRUE;
  274.         break;
  275.     /*
  276.     ** Operatori logici e bitwise unari
  277.     */
  278.     case '#':    /* Converte l'accumulatore in un valore booleano            */
  279.         acc = acc ? _TRUE : _FALSE;
  280.     case '~':    /* Inversione dei bit dell'accumulatore                     */
  281.         acc = ~acc;
  282.         acc_reset = TRUE;
  283.         break;
  284.     case '!':    /* Negazione logica dell'accumulatore                       */
  285.         acc = acc ? _TRUE : _FALSE;
  286.         acc_reset = TRUE;
  287.         break;
  288.     /*
  289.     ** Operatori di confronto
  290.     */
  291.     case '=':    /* 1 se stk == acc                                          */
  292.         acc = (POP() == acc) ? _TRUE : _FALSE;
  293.     case '<':    /* 1 se stk < acc                                           */
  294.         acc = (POP() < acc) ? _TRUE : _FALSE;
  295.     case '>':    /* 1 se stk > acc                                           */
  296.         acc = (POP() > acc) ? _TRUE : _FALSE;
  297.     /*
  298.     ** Operatori vari
  299.     */
  300.     case 'W':    /* Costruzione word (stk -> byte alto, acc -> byte basso)   */
  301.         acc = (POP() << 8) | (acc & 0x00FF);
  302.         acc_reset = TRUE;
  303.         break;
  304.     case 'w':    /* Split word (byte alto -> stk, byte basso -> acc)         */
  305.         PUSH((acc >> 8) & 0x00FF);
  306.         acc &= 0x00FF;
  307.         acc_reset = TRUE;
  308.         break;
  309.     /*
  310.     ** Interazione con le variabili
  311.     */
  312.     case 'V':    /* Carica variabile : acc <-- V[acc]                        */
  313.         if ((acc >= 0) && (acc < RPN_NVAR)) {
  314.             acc = uvar[acc];
  315.         } else {
  316.             acc = 0;
  317.         }
  318.         acc_reset = TRUE;
  319.         break;
  320.     case 'v':    /* Memorizza variabile : stack --> V[acc]                   */
  321.         tmp = POP();
  322.         if ((acc >= 0) && (acc < RPN_NVAR)) {
  323.             uvar[acc] = tmp;
  324.         }
  325.         acc_reset = TRUE;
  326.         break;
  327.     /*
  328.     ** Interazione con i flag dell'utente
  329.     */
  330.     case 'F':    /* Carica flag : acc = flag[acc] ? _TRUE : _FALSE           */
  331.         if ((acc >= 0) && (acc < 32)) {
  332.                         acc = (usr.flags & flagval[acc]) ? _TRUE : _FALSE;
  333.         } else {
  334.             acc = 0;
  335.         }
  336.         acc_reset = TRUE;
  337.         break;
  338.     case 'f':    /* flag[acc] = stack ? 1 : 0                                */
  339.         tmp = POP();
  340.         if ((acc >= 0) && (acc < 32)) {
  341.             if (tmp) {
  342.                                 usr.flags |= flagval[acc];
  343.             } else {
  344.                                 usr.flags &= ~flagval[acc];
  345.             }
  346.         }
  347.         acc_reset = TRUE;
  348.         break;
  349.     /*
  350.     ** Interazione con i contatori utente
  351.     */
  352.     case 'C':    /* acc <-- C[acc]                                           */
  353.         if ((acc >= 0) && (acc < MAXCOUNTER)) {
  354.                         acc = usr.counter[--acc];
  355.         } else {
  356.             acc = 0;
  357.         }
  358.         acc_reset = TRUE;
  359.         break;
  360.         case 'c':       /* C[acc] <-- stack                                         */
  361.             tmp = POP();
  362.             if ((acc >= 0) && (acc < MAXCOUNTER)) {
  363.                 if (tmp < 0)
  364.                     usr.counter[--acc] = 0;
  365.                 else if (tmp > 255)
  366.                     usr.counter[--acc] = tmp;
  367.                 else
  368.                     usr.counter[--acc] = tmp;
  369.             }
  370.             acc_reset = TRUE;
  371.             break;
  372.     /*
  373.     ** Interazione con i dati del record utente
  374.     */
  375.         case 'U':       /* Carica un campo del record utente : acc <-- U[acc]       */
  376.             acc = get_usr(acc);
  377.             acc_reset = TRUE;
  378.             break;
  379.         case 'u':       /* Memorizza in record utente : U[acc] <-- stack            */
  380.             set_usr(acc, POP());
  381.             acc_reset = TRUE;
  382.             break;
  383.         /*
  384.         ** Posizione cursore
  385.         */
  386.         case 'P':
  387.             acc = (vy << 8) | vx;
  388.          acc_reset = TRUE;
  389.          break;
  390.       case 'p':
  391.          cpos ((acc >> 8) & 0x00FF, acc & 0x00FF);
  392.          acc_reset = TRUE;
  393.          break;
  394.       /*
  395.       ** Attributo di colore
  396.       */
  397.       case 'A':
  398.          acc = ansi_attr;
  399.          acc_reset = TRUE;
  400.          break;
  401.       case 'a':
  402.          change_attr (acc & 0x00FF);
  403.          acc_reset = TRUE;
  404.          break;
  405.       /*
  406.       ** I caratteri sconosciuti vengono ignorati
  407.       */
  408.       default:
  409.          break;
  410.    }
  411. }
  412.  
  413. char *rpnProcessString (char *p)
  414. {
  415.     while (*p && *p >= 32 && *p != 0x0A && *p != 0x0D && *p != 'E')
  416.         rpnProcessChar (*p++);
  417.     if (*p != 'E') p--;                   // E significa Exit, non riportare p
  418.    return (p);
  419. }
  420.  
  421. /*
  422. ** Funzione  : get_usr
  423. ** Scopo     : Legge un campo del record utente
  424. ** Parametri : field - Identificativo campo
  425. ** Ritorna   : Il valore del campo richiesto o 0 in caso di errore
  426. ** Note      :
  427. */
  428. short get_usr(short field)
  429. {
  430.     register short  val;
  431.  
  432.     switch (field) {
  433.     case USR_IBMSET:
  434.                 val = (usr.ibmset) ? _TRUE : _FALSE;
  435.         break;
  436.     case USR_FORMFEED:
  437.                 val = (usr.formfeed) ? _TRUE : _FALSE;
  438.         break;
  439.     case USR_COLOR:
  440.                 val = (usr.color) ? _TRUE : _FALSE;
  441.         break;
  442.     case USR_ANSI:
  443.                 val = (usr.ansi) ? _TRUE : _FALSE;
  444.         break;
  445.     case USR_AVATAR:
  446.                 val = (usr.avatar) ? _TRUE : _FALSE;
  447.         break;
  448.     case USR_TABS:
  449.                 val = (usr.tabs) ? _TRUE : _FALSE;
  450.         break;
  451.     case USR_MORE:
  452.                 val = (usr.more) ? _TRUE : _FALSE;
  453.         break;
  454.     case USR_HOTKEY:
  455.                 val = (usr.hotkey) ? _TRUE : _FALSE;
  456.         break;
  457.     case USR_SCANMAIL:
  458.                 val = (usr.scanmail) ? _TRUE : _FALSE;
  459.         break;
  460.     case USR_FULLREAD:
  461.                 val = (usr.full_read) ? _TRUE : _FALSE;
  462.         break;
  463.     case USR_USELORE:
  464.                 val = (usr.use_lore) ? _TRUE : _FALSE;
  465.         break;
  466.     case USR_KLUDGE:
  467.                 val = (usr.kludge) ? _TRUE : _FALSE;
  468.         break;
  469.     case USR_HIDDEN:
  470.                 val = (usr.usrhidden) ? _TRUE : _FALSE;
  471.         break;
  472.     case USR_NOKILL:
  473.                 val = (usr.nokill) ? _TRUE : _FALSE;
  474.         break;
  475.     case USR_NERD:
  476.                 val = (usr.nerd) ? _TRUE : _FALSE;
  477.         break;
  478.     case USR_XFERPRIOR:
  479.                 val = (usr.xfer_prior) ? _TRUE : _FALSE;
  480.         break;
  481.     case USR_LANGUAGE:
  482.                 val = usr.language;
  483.         break;
  484.     case USR_LEN:
  485.                 val = usr.len;
  486.         break;
  487.     case USR_WIDTH:
  488.                 val = usr.width;
  489.         break;
  490.     case USR_PROTOCOL:
  491.                 val = usr.protocol;
  492.         break;
  493.     case USR_ARCHIVER:
  494.                 val = usr.archiver;
  495.         break;
  496.     case USR_MSGSIG:
  497.                 val = usr.msg_sig;
  498.         break;
  499.     case USR_FILESIG:
  500.                 val = usr.file_sig;
  501.         break;
  502.     case USR_PRIV:
  503.                 val = usr.priv >> 4;
  504.         break;
  505.     case USR_CREDIT:
  506.                 val = usr.credit;
  507.         break;
  508.     default:
  509.         val = 0;
  510.         break;
  511.     }
  512.     return val;
  513. }
  514.  
  515. /*
  516. ** Funzione  : set_usr
  517. ** Scopo     : Modifica un campo del record utente
  518. ** Parametri : field - Identificativo campo
  519. **             val   - Valore da assegnare al campo
  520. ** Ritorna   :
  521. ** Note      : Per i campi numerici manca ancora il controllo di validita`
  522. **             del valore da assegnare
  523. */
  524. void set_usr(short field, short val)
  525. {
  526.     switch (field) {
  527.     case USR_IBMSET:
  528.                 usr.ibmset = val ? 1 : 0;
  529.         break;
  530.     case USR_FORMFEED:
  531.                 usr.formfeed = val ? 1 : 0;
  532.         break;
  533.     case USR_COLOR:
  534.                 usr.color = val ? 1 : 0;
  535.         break;
  536.     case USR_ANSI:
  537.                 usr.ansi = val ? 1 : 0;
  538.         break;
  539.     case USR_AVATAR:
  540.                 usr.avatar = val ? 1 : 0;
  541.         break;
  542.     case USR_TABS:
  543.                 usr.tabs = val ? 1 : 0;
  544.         break;
  545.     case USR_MORE:
  546.                 usr.more = val ? 1 : 0;
  547.         break;
  548.     case USR_HOTKEY:
  549.                 usr.hotkey = val ? 1 : 0;
  550.         break;
  551.     case USR_SCANMAIL:
  552.                 usr.scanmail = val ? 1 : 0;
  553.         break;
  554.     case USR_FULLREAD:
  555.                 usr.full_read = val ? 1 : 0;
  556.         break;
  557.     case USR_USELORE:
  558.                 usr.use_lore = val ? 1 : 0;
  559.         break;
  560.     case USR_KLUDGE:
  561.                 usr.kludge = val ? 1 : 0;
  562.         break;
  563.     case USR_HIDDEN:
  564.                 usr.usrhidden = val ? 1 : 0;
  565.         break;
  566.     case USR_NOKILL:
  567.                 usr.nokill = val ? 1 : 0;
  568.         break;
  569.     case USR_NERD:
  570.                 usr.nerd = val ? 1 : 0;
  571.         break;
  572.     case USR_XFERPRIOR:
  573.                 usr.xfer_prior = val ? 1 : 0;
  574.         break;
  575.     case USR_LANGUAGE:
  576.                 usr.language = val;
  577.         break;
  578.     case USR_LEN:
  579.                 usr.len = val;
  580.         break;
  581.     case USR_WIDTH:
  582.                 usr.width = val;
  583.         break;
  584.     case USR_PROTOCOL:
  585.                 usr.protocol = val;
  586.         break;
  587.     case USR_ARCHIVER:
  588.                 usr.archiver = val;
  589.         break;
  590.     case USR_MSGSIG:
  591.                 usr.msg_sig = val;
  592.         break;
  593.     case USR_FILESIG:
  594.                 usr.file_sig = val;
  595.         break;
  596.     case USR_PRIV:
  597.                 usr.priv = val << 4;
  598.         break;
  599.     case USR_CREDIT:
  600.                 usr.credit = val;
  601.         break;
  602.     default:
  603.         break;
  604.     }
  605. }
  606.  
  607. /* Fine del file LRPN.C */
  608.