File:  [Coherent Logic Development] / freem / src / expr.c
Revision 1.4: download - view: text, annotated - select for diffs
Sun Mar 9 15:20:18 2025 UTC (7 months, 1 week ago) by snw
Branches: MAIN
CVS tags: HEAD
Begin formatting overhaul and REUSE compliance

    1: /*
    2:  *                            *
    3:  *                           * *
    4:  *                          *   *
    5:  *                     ***************
    6:  *                      * *       * *
    7:  *                       *  MUMPS  *
    8:  *                      * *       * *
    9:  *                     ***************
   10:  *                          *   *
   11:  *                           * *
   12:  *                            *
   13:  *
   14:  *   expr.c
   15:  *    expression parser
   16:  *
   17:  *  
   18:  *   Author: Serena Willis <snw@coherent-logic.com>
   19:  *    Copyright (C) 1998 MUG Deutschland
   20:  *    Copyright (C) 2020, 2023 Coherent Logic Development LLC
   21:  *
   22:  *
   23:  *   This file is part of FreeM.
   24:  *
   25:  *   FreeM is free software: you can redistribute it and/or modify
   26:  *   it under the terms of the GNU Affero Public License as published by
   27:  *   the Free Software Foundation, either version 3 of the License, or
   28:  *   (at your option) any later version.
   29:  *
   30:  *   FreeM is distributed in the hope that it will be useful,
   31:  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   32:  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   33:  *   GNU Affero Public License for more details.
   34:  *
   35:  *   You should have received a copy of the GNU Affero Public License
   36:  *   along with FreeM.  If not, see <https://www.gnu.org/licenses/>.
   37:  *
   38:  **/
   39: 
   40: #if !defined(__osf__)
   41: #include <sys/types.h>
   42: #endif
   43: #if !defined(__OpenBSD__) && !defined(__FreeBSD__)
   44: # include <sys/timeb.h>
   45: #endif
   46: #include <stdlib.h>
   47: #include <string.h>
   48: #include <ctype.h>
   49: 
   50: /* mumps expression evaluator */
   51: 
   52: #include "mpsdef.h"
   53: #include "transact.h"
   54: #include "merr.h"
   55: #include "mtok.h"
   56: #include "version.h"
   57: #if defined(HAVE_STDINT_H)
   58: # include <stdint.h>
   59: #endif
   60: #if !defined(__osf__) && !defined(_AIX)
   61: # define _XOPEN_SOURCE
   62: #endif
   63: 
   64: #if defined(USE_SYS_TIME_H) && !defined(MSDOS) && !defined(__osf__)
   65: # include <sys/time.h>
   66: #else
   67: # include <time.h> 
   68: #endif
   69: 
   70: #if defined(MSDOS) || defined(__linux__)
   71: # include <time.h>
   72:   char *strptime(const char *restrict s, const char *restrict format, struct tm *restrict tm);
   73: #endif
   74: 
   75: #include "mref.h"
   76: #include "journal.h"
   77: #include "datatypes.h"
   78: #include "objects.h"
   79: 
   80: #define OPERAND       1
   81: #define ARRAY         2
   82: #define FNUMBER       3
   83: #define REVERSE       4
   84: #define TRANSLATE     5
   85: #define QLENGTH       6
   86: #define QSUBSCRIPT    7
   87: #define TYPE          31
   88: #define INSTANCEOF    32
   89: 
   90: #define ZCRC          8
   91: #define ZDATA         9
   92: #define ZLSD         11
   93: #define ZNEXT        12
   94: #define ZPREVIOUS    17
   95: #define ZTRAP        18
   96: 
   97: #define SVNsystem    19
   98: #define SVNtimezone  20
   99: #define SVNtlevel    22
  100: #define SVNtrollback 23
  101: #define SVNecode     24
  102: #define SVNestack    25
  103: #define SVNetrap     26
  104: #define SVNstack     27
  105: #define SVNpdisplay   28
  106: #define SVNdialect    29
  107: #define SVNzut 30
  108: 
  109: #define OR                '!'
  110: #define MODULO            '#'
  111: #define DIVIDE            '/'
  112: #define AND               '&'
  113: #define NOT               '\''
  114: #define XOR               '~'
  115: #define MULTIPLY          '*'
  116: #define POWER             ' '
  117: #define PLUS              '+'
  118: #define MINUS             '-'
  119: #define LESS              '<'
  120: #define EQUAL             '='
  121: #define GREATER           '>'
  122: #define PATTERN           '?'
  123: #define INDIRECT          '@'
  124: #define CONTAINS          '['
  125: #define INTDIVIDE         '\\'
  126: #define FOLLOWS           ']'
  127: #define CONCATENATE       '_'
  128: #define SORTSAFTER        '.'
  129: #define EQFOLLOWS         ','
  130: #define EQSORTS           ';'
  131: #define MAXOP             ':'
  132: #define MINOP             '%'
  133: 
  134: #define GET               'Y'
  135: #define GETX              ':'
  136: 
  137: #if !defined(__OpenBSD__) && !defined(_AIX) && !defined(__osf__) && !defined(MSDOS) && !defined(__vax__)
  138: long    time ();
  139: #endif
  140: void cond_round (char *a, int digits);
  141: void zkey (char *a, long type);
  142: int levenshtein (char *word1, char *word2);
  143: time_t     horolog_to_unix (char *horo);
  144: extern int xecline(int typ);
  145: short      rbuf_slot_from_name(char *);
  146: 
  147: 
  148: short obj_field = FALSE;
  149: char object_instance[50];
  150: char object_class[50];
  151: 
  152: 
  153: /*
  154:  * expr():  expression parser
  155:  *  extyp:  type of expression; one of:
  156:  *          STRING
  157:  *          NAME
  158:  *          LABEL
  159:  *          OFFSET
  160:  *          ARGIND
  161:  */
  162: void expr (short extyp)
  163: {
  164:     char op_stck[PARDEPTH + 1]; /* operator/operandflag stack */
  165:     short spx;          /* stack pointer:             */
  166:     short zexflag;          /* z 'intrinsic' function flag */
  167:     int atyp, btyp;         /* DM/EUR currency types */
  168:     char *a;                /* pointer to current (left) argument */
  169:     char *b;                /* pointer to right hand argument     */
  170:     char tmp[256];
  171:     int refsx;          /* zref/zloc stack_counter  */
  172:     char *refsav[PARDEPTH];     /* zref/zloc stack          */
  173:     
  174: 
  175:     register int i = 0;
  176:     register int j = 0;
  177:     register int f = 0;
  178:     volatile int ch = 0;
  179:     
  180:     short   group;          /* flag to scan grouped patterns */
  181:     
  182: #ifdef DEBUG_NEWPTR
  183:     int loop;
  184: #endif
  185: 
  186:     refsx = 0;
  187: 
  188:     if (extyp == NAME) {
  189: 
  190:         f = *codptr;
  191:         varnam[0] = f;
  192:         
  193:         if ((f >= 'A' && f <= 'Z') || (f >= 'a' && f <= 'z') || f == '^' || f == '$' || f == '%') {
  194:             
  195:             i = 1;
  196:             
  197:             while (((ch = *++codptr) >= 'A' && ch <= 'Z') ||
  198:                    (ch >= 'a' && ch <= 'z') ||
  199:                    (ch >= '0' && ch <= '9' && (i > 1 || f != '^')) ||
  200:                    f == '^' &&
  201:                    (((ch == '%' || ch == '$') && i == 1) ||
  202:                     (ch == '|') ||
  203:                     (standard == 0 &&
  204:                      (ch == '.' ||
  205:                       (ch == '/' && i == 1) ||
  206:                       (((ch == '/' && varnam[i - 1] != '/') ||
  207:                         (ch == '%' && varnam[i - 1] == '/')) &&
  208:                        (varnam[1] == '.' || varnam[1] == '/'))))) || (f != '^') && (ch == '.')) {
  209:                 
  210:                 varnam[i++] = ch;
  211: 
  212:                 
  213:                 
  214:             }
  215: 
  216:             varnam[i] = EOL;            
  217:             
  218:             if (ch == '(') {        /* it's an array */
  219:                 
  220:                 op_stck[0] = 0;
  221:                 op_stck[1] = ARRAY;
  222:                 spx = 1;
  223:                 a = argptr;
  224:                 
  225:                 if ((argstck[1] = a) >= s) {
  226:                     
  227:                     char   *bak;
  228: 
  229:                     bak = partition;
  230: 
  231:                     if (getpmore () == 0) {
  232:                         merr_raise (STKOV);
  233:                         return;
  234:                     }
  235:                     
  236:                     a = a - bak + partition;
  237:                     b = b - bak + partition;
  238: 
  239:                 }
  240: 
  241:                 a += stcpy (a, varnam) + 1;
  242:                 
  243:                 arg = 1;
  244:                 codptr++;
  245:                 
  246:                 goto nextchr;
  247:             }
  248: 
  249:             codptr--;
  250: 
  251:             if (i == 1 && f == '^') {
  252:                 merr_raise (INVEXPR);
  253:             }
  254: 
  255:             return;
  256: 
  257:         }
  258: 
  259:         if (f != '@') {
  260:             merr_raise (INVREF);
  261:             return;
  262:         }
  263:     
  264:     }                   /* end if (extyp ==NAME) */
  265: 
  266:     arg = 0;
  267:     spx = 0;                /* initialisation */
  268:     op_stck[0] = 0;
  269:     a = argptr;
  270: 
  271:     nextchr:
  272:     ch = *codptr;
  273: 
  274:     if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '%') {
  275: 
  276: 
  277: scan_name:        
  278: 
  279:         varnam[0] = ch;
  280:         i = 1;
  281:         
  282:         if (ch == '^') {        /* global variable name */
  283: 
  284:             int vb_ct;
  285:             int qt_ct;
  286:             char lastch;
  287:             char nextch;
  288:             
  289:             vb_ct = 0;
  290:             qt_ct = 0;
  291:             
  292:             lastch = ' ';
  293:             
  294:             while (((ch = *++codptr) >= 'A' && ch <= 'Z') ||
  295:                    (ch >= 'a' && ch <= 'z') ||
  296:                    (ch >= '0' && ch <= '9' && i > 1) ||
  297:                    (ch == '|') || (ch == '%') || (ch == '\"') ||
  298:                    (((ch == '%' || ch == '$') && i == 1) ||
  299:                     (standard == 0 &&
  300:                      (ch == '.' ||
  301:                       (ch == '/' && i == 1) ||
  302:                       (((ch == '/' && varnam[i - 1] != '/') ||
  303:                         (ch == '%' && varnam[i - 1] == '/')) &&
  304:                        (varnam[1] == '.' || varnam[1] == '/')))))) {
  305: 
  306:                 nextch = *(codptr + 1);
  307:                 
  308:                 if (ch == '|') vb_ct++;
  309: 
  310:                 if (ch == '\"') {
  311:                     qt_ct++;
  312:                     
  313:                     if ((lastch != '|') && (nextch != '|')) {
  314:                         merr_raise (INVEXPR);
  315:                         return;
  316:                     }
  317:                     
  318:                 }
  319: 
  320:                 if ((ch == '|') && ((nextch != '\"') && (lastch != '\"'))) {
  321: 
  322:                     if ((qt_ct == 1) && (vb_ct == 2)) {
  323:                         merr_raise (QUOTER);
  324:                         return;
  325:                     }
  326:                     else if ((vb_ct == 2) && (qt_ct == 1)){
  327:                         merr_raise (INVEXPR);
  328:                         return;
  329:                     }
  330:                     
  331:                 }
  332:                 
  333:                 if (vb_ct > 2) {
  334:                     merr_raise (INVEXPR);
  335:                     return;
  336:                 }
  337:                 
  338:                 varnam[i++] = ch;
  339: 
  340:                 lastch = ch;
  341:             }
  342: 
  343:             varnam[i] = EOL;          
  344:             
  345:             if (i == 1 && ch != '(') {
  346:                 merr_raise (INVEXPR);
  347:                 return;
  348:             }
  349: 
  350:         } 
  351:         else {          /* local variable name */
  352: 
  353:             while (isalnum (ch = *++codptr)) {
  354:                 varnam[i++] = ch;
  355:             }
  356:         
  357:             varnam[i] = EOL;
  358: 
  359:             
  360:             if (*codptr == '.') {
  361:                 if (*(codptr + 1) == '$') {
  362:                     codptr++;
  363: 
  364:                     obj_field = TRUE;
  365:                     stcpy (object_instance, varnam);
  366:                     stcnv_m2c (object_instance);
  367:                     obj_get_attribute (object_instance, "CLASS", object_class);
  368: 
  369:                     stcnv_m2c (object_instance);
  370:                     stcnv_c2m (object_class);
  371:                     
  372:                     expr (STRING);
  373:                     return;
  374:                 }
  375:                 else {
  376:                     merr_raise (INVEXPR);
  377:                     return;
  378:                 }
  379:             }
  380:             
  381:         }
  382:         
  383:         if (ch == '(') {        /* it's an array */
  384:             
  385:             if (extyp == LABEL) {
  386:                 codptr--;
  387:                 return;
  388:             }
  389: 
  390:             if (++spx >= PARDEPTH) {
  391:                 merr_raise (STKOV);
  392:                 return;
  393:             }
  394: 
  395:             op_stck[spx] = ARRAY;
  396:             
  397:             if ((argstck[++arg] = a) >= s) {
  398:                 
  399:                 char   *bak;
  400:                 bak = partition;
  401: 
  402:                 if (getpmore () == 0) {
  403:                     merr_raise (STKOV);
  404:                     return;
  405:                 }
  406:                 
  407:                 a = a - bak + partition;
  408:                 b = b - bak + partition;
  409: 
  410:             }
  411: 
  412:             a += stcpy (a, varnam) + 1;
  413:             codptr++;
  414:             
  415:             goto nextchr;
  416: 
  417:         }
  418: 
  419:         if (spx == 0) {
  420:             
  421:             if (extyp != STRING && extyp != ARGIND && extyp != OFFSET) {
  422:                 codptr--;
  423:                 return;
  424:             }
  425: 
  426:             if (varnam[0] != '^') {
  427:                 symtab (get_sym, varnam, a);
  428:             }
  429:             else if (varnam[1] != '$') {
  430:                 global (get_sym, varnam, a);
  431:             }
  432:             else {
  433:                 ssvn (get_sym, varnam, a);
  434:             }
  435:             
  436:             if (merr () != OK) {
  437: 
  438:                 stcpy (varerr, varnam);
  439:                 
  440:                 if (merr () == UNDEF || merr () == M6 || merr () == M7) {
  441:                     arg = 1;
  442:                     codptr--;
  443:                     
  444:                     goto undefglvn;
  445:                 }
  446: 
  447:             }
  448: 
  449:             if (ch == EOL || ch == SP || (extyp == ARGIND) || ch == ',' || ch == ':' || ch == ')' || ch == '@' || (merr () > OK)) {
  450:                 return;
  451:             }
  452: 
  453:             arg = 1;
  454:             argstck[1] = a;
  455:             f = OPERAND;
  456:             op_stck[1] = f;
  457:             spx = 2;
  458: 
  459:             goto op10;          /* shortcut: following char is garbage or operator */
  460: 
  461:         }
  462: 
  463:         codptr--;
  464:         
  465:         if ((argstck[++arg] = a) >= s) {
  466:             
  467:             char   *bak;
  468:             bak = partition;
  469: 
  470:             if (getpmore () == 0) {
  471:                 merr_raise (STKOV);
  472:                 return;
  473:             }
  474: 
  475:             a = a - bak + partition;
  476:             b = b - bak + partition;
  477: 
  478:         }
  479: 
  480:         /* evaluate glvn or $_(glvn) */
  481: 
  482: var1:
  483:         
  484:         if (op_stck[spx] == '$') {
  485: 
  486:             f = op_stck[spx - 1];
  487: 
  488:             
  489:             switch (f) {
  490: 
  491: 
  492:                 case 'd':           /* $DATA */
  493:                     
  494:                     ch = dat;
  495: 
  496: glv_fcn:
  497: 
  498:                     if (varnam[0] != '^') {
  499:                         symtab (ch, varnam, a);
  500:                     }
  501:                     else if (varnam[1] != '$'){
  502:                         global  (ch, varnam, a);
  503:                     }
  504:                     else {
  505:                         ssvn (ch, varnam, a);
  506:                     }
  507: 
  508: d_o_n:
  509: 
  510:                     if (*++codptr != ')') merr_raise (INVEXPR);
  511: 
  512:                     if (merr () > OK) {
  513:                         stcpy (varerr, varnam);
  514:                         return;
  515:                     }
  516: 
  517:                     spx -= 2;
  518:                     
  519:                     goto nxt_operator;
  520: 
  521: 
  522:                 case 'o':           /* $ORDER */
  523: 
  524:                     if (rtn_dialect () == D_M77) {
  525:                         merr_raise (NOSTAND);
  526:                         return;
  527:                     }
  528:                     
  529:                     ch = fra_order;
  530:                     ordercnt = 1L;
  531:                     
  532:                     if (*(codptr + 1) != ',') {
  533:                         ordercounter = 0;
  534:                         goto glv_fcn;
  535:                     }
  536: 
  537:                     if (++spx > PARDEPTH) {
  538:                         merr_raise (STKOV);
  539:                         return;
  540:                     }
  541: 
  542:                     stcpy (a, varnam);
  543:                     
  544:                     op_stck[spx] = OPERAND;
  545:                     codptr++;
  546:                     
  547:                     goto nextchr;
  548: 
  549: 
  550:                 case 'n':           /* $NEXT */
  551: 
  552:                     ordercnt = 1L;
  553:                     ordercounter = 0;
  554:                     
  555:                     if (varnam[0] != '^') {
  556:                         symtab (fra_order, varnam, a);
  557:                     }
  558:                     else if (varnam[1] != '$') {
  559:                         global  (fra_order, varnam, a);
  560:                     }
  561:                     else {
  562:                         ssvn (fra_order, varnam, a);
  563:                     }
  564: 
  565:                     if (a[0] == EOL) {
  566:                         a[0] = '-';
  567:                         a[1] = '1';
  568:                         a[2] = EOL;
  569:                     }
  570: 
  571:                     goto d_o_n;
  572: 
  573: 
  574:                 case 'q':           /* $QUERY */
  575:                 case 'O':           /* $ZORDER */
  576:                 
  577:                     ch = fra_query;
  578:                     ordercnt = 1L;
  579:                     
  580:                     if (*(codptr + 1) != ',') goto glv_fcn;
  581: 
  582:                     if (++spx > PARDEPTH) {
  583:                         merr_raise (STKOV);
  584:                         return;
  585:                     }
  586: 
  587:                     stcpy (a, varnam);
  588:                     
  589:                     op_stck[spx] = OPERAND;
  590:                     codptr++;
  591:                     
  592:                     goto nextchr;
  593: 
  594: 
  595:                 case ZNEXT:     /* $ZNEXT */
  596: 
  597:                     ordercnt = 1L;
  598:                     
  599:                     if (varnam[0] != '^') {
  600:                         symtab (fra_query, varnam, a);
  601:                     }
  602:                     else if (varnam[1] != '$') {
  603:                         global  (fra_query, varnam, a);
  604:                     }
  605:                     else {
  606:                         ssvn (fra_query, varnam, a);
  607:                     }
  608:                     
  609:                     if (a[0] == EOL) {
  610:                         a[0] = '-';
  611:                         a[1] = '1';
  612:                         a[2] = EOL;
  613:                     }
  614: 
  615:                     goto d_o_n;
  616: 
  617: 
  618:                 case 'N':           /* $NAME */
  619: 
  620:                     /* resolve naked reference */
  621:                     if (varnam[0] == '^' && varnam[1] == DELIM) {
  622:                         
  623:                         stcpy (a, zref);
  624:                         ch = stlen (a);
  625:                         
  626:                         while (a[ch--] != DELIM) {
  627:                         
  628:                             if (ch <= 0) {
  629:                                 merr_raise (NAKED);
  630:                                 return;
  631:                             }
  632:                         
  633:                         }
  634: 
  635:                         stcpy (&a[++ch], &varnam[1]);
  636:                         stcpy (varnam, a);
  637: 
  638:                     }
  639: 
  640:                     if (*(codptr + 1) != ',') {
  641:                         zname (a, varnam);
  642:                         goto d_o_n;
  643:                     }
  644: 
  645:                     if (++spx > PARDEPTH) {
  646:                         merr_raise (STKOV);
  647:                         return;
  648:                     }
  649: 
  650:                     stcpy (a, varnam);
  651:                     
  652:                     op_stck[spx] = OPERAND;
  653:                     codptr++;
  654:                     
  655:                     goto nextchr;
  656: 
  657: 
  658:                 case ZPREVIOUS:     /* $ZPREVIOUS */
  659: 
  660:                     ordercnt = (-1L);
  661:                     ordercounter = 0;
  662:                     ch = fra_order;
  663:                     
  664:                     goto glv_fcn;
  665: 
  666: 
  667:                 case ZDATA:     /* $ZDATA */
  668: 
  669:                     ch = zdata;
  670:                     goto glv_fcn;
  671: 
  672: 
  673:                 case 'g':           /* $GET */
  674:                     
  675:                     if (varnam[0] != '^') {
  676:                         symtab (get_sym, varnam, a);
  677:                     }
  678:                     else if (varnam[1] != '$') {
  679:                         global (get_sym, varnam, a);
  680:                     }
  681:                     else {
  682:                         ssvn (get_sym, varnam, a);
  683:                     }
  684: 
  685:                     if (merr () == M7 || merr () == M6) merr_raise (UNDEF);
  686: 
  687:                     if (merr () > OK) {
  688: 
  689:                         stcpy (varerr, varnam);
  690:                     
  691:                         if (merr () != UNDEF) return;
  692:                     }
  693:                     
  694:                     if (merr () == UNDEF) {
  695: 
  696:                         //smw 15 nov 2023 merr_raise (ierr < 0 ? OK - CTRLB : OK);
  697:                         merr_clear ();
  698:                         
  699:                         if (*++codptr == ',') {
  700: 
  701:                             if (standard) {
  702:                                 merr_raise (NOSTAND);
  703:                                 return;
  704:                             }
  705: 
  706:                             op_stck[spx - 1] = GET;     /* dummy function for $GET */
  707:                             arg--;
  708:                             codptr++;
  709:                             
  710:                             goto nextchr;
  711:                         
  712:                         } 
  713:                         else {
  714: 
  715:                             if (*codptr != ')') {
  716:                                 merr_raise (INVEXPR);
  717:                                 return;
  718:                             }
  719: 
  720:                             *a = EOL;
  721: 
  722:                         }
  723: 
  724:                     } 
  725:                     else {        /* glvn was defined */
  726:                         
  727:                         if (*++codptr == ',') { /* skip second argument */
  728:                             
  729:                             i = 0;      /* quote flag */                            
  730:                             f = 0;      /* bracket counter */
  731: 
  732:                             for (;;) {
  733: 
  734:                                 ch = *++codptr;
  735:                                 
  736:                                 if (ch == EOL) {
  737:                                     merr_raise (INVEXPR);
  738:                                     return;
  739:                                 }
  740: 
  741:                                 if (ch == '"') {
  742:                                     i = !i;
  743:                                     continue;
  744:                                 }
  745: 
  746:                                 if (i) continue;
  747:                                 
  748:                                 if (ch == '(') {
  749:                                     f++;
  750:                                     continue;
  751:                                 }
  752: 
  753:                                 if (ch == ')') {
  754:                                     if (--f < 0) break;
  755:                                 }
  756: 
  757:                             }
  758: 
  759:                         } 
  760:                         else if (*codptr != ')') {
  761:                             merr_raise (INVEXPR);
  762:                             return;
  763:                         }
  764: 
  765:                     }
  766: 
  767:                     spx -= 2;
  768:                     goto nxt_operator;
  769: 
  770:                 case 'i':           /* $INCREMENT */
  771:                     
  772:                     if (varnam[0] != '^') {
  773:                         symtab (getinc, varnam, a);
  774:                     }
  775:                     else {
  776:                         
  777:                         int setopsav;
  778: 
  779:                         setopsav = setop;
  780:                         setop = '+';
  781:                         a[0] = '1';
  782:                         a[1] = EOL;
  783:                         
  784:                         if (varnam[1] != '$') {
  785:                             global  (set_sym, varnam, a);
  786:                         }
  787:                         else {
  788:                             ssvn (set_sym, varnam, a);
  789:                         }
  790: 
  791:                         setop = setopsav;
  792: 
  793:                     }
  794: 
  795:                     goto d_o_n;
  796: 
  797: 
  798:                 case OPERAND:       /* three arguments $TEXT */
  799: 
  800:                     if (spx >= 6 && op_stck[spx - 5] == 't' && op_stck[spx - 4] == '$' && op_stck[spx - 2] == '$') {
  801:                         
  802:                         stcpy (a, &varnam[varnam[0]=='^']); /* third argument */
  803:                         
  804:                         if (++spx > PARDEPTH) {
  805:                             merr_raise (STKOV);
  806:                             return;
  807:                         }
  808: 
  809:                         op_stck[spx] = OPERAND;
  810:                         codptr++;
  811:                         
  812:                         goto nextchr;
  813: 
  814:                     }
  815: 
  816:             }               /* end switch */
  817:         }
  818:         
  819:         /* retrieve look-up */
  820: 
  821:         if (varnam[0] != '^') {
  822:             symtab (get_sym, varnam, a);
  823:         }
  824:         else if (varnam[1] != '$') {
  825:             global  (get_sym, varnam, a);
  826:         }
  827:         else {
  828:             ssvn (get_sym, varnam, a);
  829:         }
  830: 
  831: 
  832: undefglvn:
  833: 
  834: 
  835:         if (merr ()) stcpy (varerr, varnam);
  836:         
  837:         if ((merr () == M6) || (merr () == M7) || (merr () == UNDEF)) {
  838:             
  839:             stcpy (tmp, codptr + 1);
  840:             
  841:             if (varnam[0] == '^') { /* is there a default expression?? */
  842:                 
  843:                 if (gvndefault[0] == EOL) return;
  844:                 
  845:                 stcpy (&code[1], gvndefault);
  846: 
  847:             } 
  848:             else {
  849: 
  850:                 if (lvndefault[0] == EOL) return;
  851:             
  852:                 stcpy (&code[1], lvndefault);
  853:             
  854:             }
  855:             
  856:             /* simulate a $GET function */
  857:             code[0] = SP;
  858:             
  859:             stcat (code, ")\201");
  860:             stcat (code, tmp);
  861:             
  862:             codptr = &code[1];
  863:             
  864:             if (((++spx) + 1) > PARDEPTH) {
  865:                 merr_raise (STKOV);
  866:                 return;
  867:             }
  868: 
  869:             op_stck[spx] = GETX;    /* dummy function for $GET */
  870:             op_stck[++spx] = '$';
  871:             
  872:             /* stack $ZREFERENCE and $ZLOCAL */
  873:             if ((refsav[refsx] = calloc (1, 2 * 256)) == NULL) {
  874:                 merr_raise (STKOV);
  875:                 return;
  876:             }               /* could not allocate stuff...     */
  877:             
  878:             stcpy (refsav[refsx], zref);
  879:             stcpy (refsav[refsx++] + 256, zloc);
  880:             
  881:             ierr -= M7; //smw TODO HUH??
  882:             arg--;
  883:             
  884:             goto nextchr;
  885: 
  886:         }
  887: 
  888:         if (merr () > OK) return;
  889: 
  890:         if (spx == 0) {
  891: 
  892:             if ((ch = *++codptr) == EOL || ch == SP || ch == ',' || ch == ':') return;
  893: 
  894:             if (++spx > PARDEPTH) {
  895:                 merr_raise (STKOV);
  896:                 return;
  897:             }
  898: 
  899:             op_stck[spx] = OPERAND;
  900:             
  901:             goto next10;
  902: 
  903:         }
  904: 
  905:         f = op_stck[spx];
  906:         
  907:         if (f == ARRAY || f == '(') {
  908:             
  909:             if (++spx > PARDEPTH) {
  910:                 merr_raise (STKOV);
  911:                 return;
  912:             }
  913: 
  914:             op_stck[spx] = OPERAND;
  915:             codptr++;
  916:             
  917:             goto nextchr;
  918: 
  919:         }
  920: 
  921:         if (f == INDIRECT && (extyp == STRING || extyp == ARGIND || extyp == OFFSET)) {
  922:             spx--;
  923:             goto indirect;      /* VARIABLE indirection */
  924:         }
  925: 
  926:         goto nxt_expr;
  927: 
  928:     }
  929: 
  930:     if (ch >= '0' && ch <= '9') {
  931: 
  932:         if (extyp == LABEL) goto scan_name;     /* scan_label */
  933: 
  934:         /* scan number */
  935:         i = 0;              /* point flag */
  936:         j = 0;              /* exp flag */
  937:         f = ch;             /* first character */
  938: 
  939:         if ((argstck[++arg] = a) >= s) {
  940:             
  941:             char   *bak;
  942:             bak = partition;
  943:             
  944:             if (getpmore () == 0) {
  945:                 merr_raise (STKOV);
  946:                 return;
  947:             }
  948: 
  949:             a = a - bak + partition;
  950: 
  951:         }
  952: 
  953:         b = a;
  954: 
  955: p_entry:           /* entry point if first character was a point */
  956:         
  957:         for (;;) {
  958: 
  959:             if (ch < '0') {
  960: 
  961:                 if (ch != '.' || i || j) break;
  962:             
  963:                 i++;
  964: 
  965:             } 
  966:             else if (ch > '9') {
  967: 
  968:                 if (j) break;
  969:                 if (ch != 'E' && (lowerflag == FALSE || ch != 'e')) break;
  970:                 
  971:                 if (ch == 'E') {
  972:                     if ((*(codptr + 1) == 'U') && (*(codptr + 2) == 'R')) break;
  973:                     if ((*(codptr + 1) == 'S') && (*(codptr + 2) == 'P')) break;
  974:                 }
  975: 
  976:                 j++;
  977:                 
  978:                 do {
  979: 
  980:                     *b++ = ch;
  981:                     ch = *++codptr;
  982: 
  983:                 } while (ch == '+' || ch == '-');
  984: 
  985:             }
  986: 
  987:             *b++ = ch;
  988:             ch = *++codptr;
  989: 
  990:         }
  991: 
  992: #ifdef EUR2DEM
  993: 
  994:         switch (ch) {
  995: 
  996:             case 'E':
  997:                 
  998:                 if ((*(codptr + 1) == 'U') && (*(codptr + 2) == 'R')) {
  999:                     *b++ = ch;
 1000:                     *b++ = *++codptr;
 1001:                     *b++ = *++codptr;
 1002:                     ch = *++codptr;
 1003:                     j = 1;
 1004:                     
 1005:                     break;
 1006:                 }
 1007: 
 1008:                 if ((*(codptr + 1) == 'S') && (*(codptr + 2) == 'P')) {
 1009:                     *b++ = ch;
 1010:                     *b++ = *++codptr;
 1011:                     *b++ = *++codptr;
 1012:                     ch = *++codptr;
 1013:                     j = 1;
 1014:                 }
 1015: 
 1016:                 break;
 1017: 
 1018: 
 1019:             case 'D':
 1020: 
 1021:                 if (*(codptr + 1) == 'M') {
 1022:                     *b++ = ch;
 1023:                     *b++ = *++codptr;
 1024:                     ch = *++codptr;
 1025:                     j = 1;
 1026: 
 1027:                     break;
 1028:                 }
 1029: 
 1030:                 if (*(codptr + 1) == 'E' && *(codptr + 2) == 'M') {
 1031:                     *b++ = ch;
 1032:                     *b++ = *++codptr;
 1033:                     *b++ = *++codptr;
 1034:                     ch = *++codptr;
 1035:                     j = 1;
 1036:                 }
 1037: 
 1038:                 break;
 1039:             
 1040: 
 1041:             case 'A':
 1042: 
 1043:                 if (*(codptr + 1) == 'T' && *(codptr + 2) == 'S') {
 1044:                     *b++ = ch;
 1045:                     *b++ = *++codptr;
 1046:                     *b++ = *++codptr;
 1047:                     ch = *++codptr;
 1048:                     j = 1;
 1049:                 }
 1050: 
 1051:                 break;
 1052:             
 1053: 
 1054:             case 'B':
 1055:                 
 1056:                 if (*(codptr + 1) == 'F' && *(codptr + 2) == 'R') {
 1057:                     *b++ = ch;
 1058:                     *b++ = *++codptr;
 1059:                     *b++ = *++codptr;
 1060:                     ch = *++codptr;
 1061:                     j = 1;
 1062:                 }
 1063:                 
 1064:                 break;
 1065: 
 1066: 
 1067:             case 'F':
 1068: 
 1069:                 if (*(codptr + 1) == 'F') {
 1070:                     *b++ = ch;
 1071:                     *b++ = *++codptr;
 1072:                     ch = *++codptr;
 1073:                     j = 1;
 1074: 
 1075:                     break;
 1076:                 }
 1077: 
 1078:                 if (*(codptr + 1) == 'M' && *(codptr + 2) == 'K') {
 1079:                     *b++ = ch;
 1080:                     *b++ = *++codptr;
 1081:                     *b++ = *++codptr;
 1082:                     ch = *++codptr;
 1083:                     j = 1;
 1084:                     
 1085:                     break;
 1086:                 }
 1087: 
 1088:                 if (*(codptr + 1) == 'R' && *(codptr + 2) == 'F') {
 1089:                     *b++ = ch;
 1090:                     *b++ = *++codptr;
 1091:                     *b++ = *++codptr;
 1092:                     ch = *++codptr;
 1093:                     j = 1;
 1094:                 }
 1095: 
 1096:                 break;
 1097:             
 1098: 
 1099:             case 'I':
 1100: 
 1101:                 if (*(codptr + 1) == 'E' && *(codptr + 2) == 'P') {
 1102:                     *b++ = ch;
 1103:                     *b++ = *++codptr;
 1104:                     *b++ = *++codptr;
 1105:                     ch = *++codptr;
 1106:                     j = 1;
 1107: 
 1108:                     break;
 1109:                 }
 1110: 
 1111:                 if (*(codptr + 1) == 'T' && *(codptr + 2) == 'L') {
 1112:                     *b++ = ch;
 1113:                     *b++ = *++codptr;
 1114:                     *b++ = *++codptr;
 1115:                     ch = *++codptr;
 1116:                     j = 1;
 1117:                 }
 1118: 
 1119:                 break;
 1120:             
 1121: 
 1122:             case 'N':
 1123:                 
 1124:                 if (*(codptr + 1) == 'L' && *(codptr + 2) == 'G') {
 1125:                     *b++ = ch;
 1126:                     *b++ = *++codptr;
 1127:                     *b++ = *++codptr;
 1128:                     ch = *++codptr;
 1129:                     j = 1;
 1130:                 }
 1131: 
 1132:                 break;
 1133:             
 1134: 
 1135:             case 'P':
 1136: 
 1137:                 if (*(codptr + 1) == 'T' && *(codptr + 2) == 'E') {
 1138:                     *b++ = ch;
 1139:                     *b++ = *++codptr;
 1140:                     *b++ = *++codptr;
 1141:                     ch = *++codptr;
 1142:                     j = 1;
 1143:                 }
 1144: 
 1145: 
 1146:         }
 1147: 
 1148: #endif /* EUR2DEM */
 1149: 
 1150:         *b = EOL;
 1151: 
 1152:         if (j || f == '0' || (i && ((*(b - 1)) < '1'))) {   /* <'1' eqiv. to '.' || '0' */
 1153:             atyp = numlit (a);
 1154:             if (atyp) stcat (a, WHR[atyp]);
 1155:         }
 1156: 
 1157:         
 1158:         if (spx) {
 1159:             codptr--;
 1160:             goto exec;
 1161:         }
 1162: 
 1163:         if (ch == EOL || ch == SP || ch == ',' || ch == ':' || (ch == '^' && extyp == OFFSET)) return;
 1164:         
 1165:         spx = 1;
 1166:         op_stck[1] = OPERAND;
 1167: 
 1168:     }
 1169: 
 1170:     if (ch != '"') goto next10;
 1171: 
 1172:     /* scan string */
 1173:     if ((argstck[++arg] = a) >= s) {
 1174: 
 1175:         char *bak;
 1176: 
 1177:         bak = partition;
 1178:         
 1179:         if (getpmore () == 0) {
 1180:             merr_raise (STKOV);
 1181:             return;
 1182:         }
 1183: 
 1184:         a = a - bak + partition;
 1185:         b = b - bak + partition;
 1186: 
 1187:     }
 1188: 
 1189:     i = 0;
 1190: 
 1191:     for (;;) {
 1192: 
 1193:         while ((ch = *++codptr) > '"') {
 1194:             a[i++] = ch;
 1195:         }
 1196:         
 1197:         /* we make use of the fact that */
 1198:         /* EOL < "any ASCII character" */
 1199:         if (ch == '"' && (ch = *++codptr) != '"') {
 1200: 
 1201:             if (ch == '_' && *(codptr + 1) == '"') {
 1202:                 codptr++;
 1203:                 continue;
 1204:             }
 1205:             
 1206:             a[i] = EOL;
 1207:             
 1208:             if (spx) {
 1209:                 codptr--;
 1210:                 goto exec;
 1211:             }
 1212:             
 1213:             if (ch == EOL || ch == SP || ch == ',' || ch == ':') return;
 1214:             
 1215:             spx = 1;
 1216:             op_stck[1] = OPERAND;
 1217:             
 1218:             goto next10;
 1219: 
 1220:         }
 1221: 
 1222:         if (ch == EOL) {
 1223:             merr_raise (QUOTER);
 1224:             return;
 1225:         }
 1226: 
 1227:         a[i++] = ch;
 1228: 
 1229:     }
 1230: 
 1231: next05:
 1232:     
 1233:     ch = *(++codptr);
 1234: 
 1235: next10:
 1236: 
 1237:     switch (ch) {
 1238: 
 1239:         
 1240:         case EOL:
 1241:         case SP:
 1242: 
 1243:             if (op_stck[1] == OPERAND && spx == 1) return;
 1244:         
 1245:             merr_raise (INVEXPR);
 1246:             return;
 1247: 
 1248: 
 1249:         case ',':
 1250: 
 1251:             if (spx == 0) {
 1252:                 merr_raise (ARGER);
 1253:                 return;
 1254:             }
 1255: 
 1256: 
 1257: comma:
 1258: 
 1259:             f = op_stck[spx - 1];
 1260: 
 1261:             /* f= (spx>0 ? op_stck[spx-1] : 0);
 1262:             * if (f) */ 
 1263:             switch (f) {
 1264: 
 1265:                 case '$':           /* first arg of $function */
 1266:                     
 1267:                     if (op_stck[spx - 2] == 's') {  /* we already have one valid arg */
 1268:                         
 1269:                         i = 0;          /* quote *//* and skip rest of select */
 1270:                         j = 0;          /* bracket */
 1271:                         
 1272:                         for (;;) {
 1273: 
 1274:                             ch = *++codptr;
 1275:                             
 1276:                             if (ch == '"') {
 1277:                                 toggle (i);
 1278:                                 continue;
 1279:                             }
 1280: 
 1281:                             if (i) {
 1282:                                 if (ch != EOL) continue;
 1283:                                 
 1284:                                 merr_raise (QUOTER);
 1285:                                 return;
 1286:                             }
 1287: 
 1288:                             if (ch == ')') {
 1289:                                 
 1290:                                 if (j--) continue;
 1291:                                 
 1292:                                 spx -= 3;
 1293:                                 
 1294:                                 goto nxt_operator;
 1295:                             }
 1296: 
 1297:                             if (ch == '(') {
 1298:                                 j++;
 1299:                                 continue;
 1300:                             }
 1301: 
 1302:                             if (ch == EOL) {
 1303:                                 merr_raise (SELER);
 1304:                                 return;
 1305:                             }
 1306:                         }
 1307: 
 1308:                     }
 1309: 
 1310:                     /* function argument */
 1311:                     /* put comma on the stack */
 1312:                     if (++spx > PARDEPTH) {
 1313:                         merr_raise (STKOV);
 1314:                         return;
 1315:                     }
 1316: 
 1317:                     op_stck[spx] = f;       /* '$' */
 1318: 
 1319:                     /*       a+=stlen(a)+1; */ 
 1320:                     
 1321:                     while (*a++ != EOL);
 1322: 
 1323:                     codptr++;
 1324:                     
 1325:                     goto nextchr;
 1326: 
 1327: 
 1328:                 case ARRAY:         /* array subscript */
 1329: 
 1330:                     *(a - 1) = DELIM;
 1331:                     arg--;
 1332:                     spx--;
 1333: 
 1334:                     while (*a++ != EOL) ;
 1335: 
 1336:                     codptr++;
 1337: 
 1338:                     goto nextchr;
 1339: 
 1340: 
 1341:                 default:
 1342: 
 1343:                     if ((extyp == NAME) || (spx > 1)) {
 1344:                         merr_raise (INVEXPR);
 1345:                         return;
 1346:                     }
 1347:                 
 1348:                     return;
 1349: 
 1350:             }
 1351: 
 1352:         case '^':
 1353: 
 1354:             if (extyp == LABEL || extyp == OFFSET) break;
 1355:             
 1356: uparrow:
 1357:         
 1358:             if (spx >= 5) {         /* take care of $TEXT with three args */
 1359:                 
 1360:                 if (op_stck[spx - 4] == 't' && op_stck[spx - 3] == '$' && op_stck[spx - 1] == '$') {
 1361: 
 1362:                     if (++spx > PARDEPTH) {
 1363:                         merr_raise (STKOV);
 1364:                         return;
 1365:                     }
 1366: 
 1367:                     op_stck[spx] = '$';
 1368:                     
 1369:                     while (*a++ != EOL);
 1370:                     
 1371:                     if (*(codptr+1)=='@') goto next05;
 1372: 
 1373:                 }
 1374: 
 1375:             }
 1376: 
 1377:             goto scan_name;
 1378:     
 1379: 
 1380:         case '.':
 1381: 
 1382:             if ((ch = *++codptr) < '0' || ch > '9') {
 1383:                 merr_raise (INVEXPR);
 1384:                 return;
 1385:             }
 1386: 
 1387:             if ((argstck[++arg] = a) >= s) {
 1388:                 
 1389:                 char   *bak;
 1390:                 bak = partition;
 1391:                 
 1392:                 if (getpmore () == 0) {
 1393:                     merr_raise (STKOV);
 1394:                     return;
 1395:                 }
 1396: 
 1397:                 a = a - bak + partition;
 1398:                 b = b - bak + partition;
 1399: 
 1400:             }
 1401:             
 1402:             i = 1;              /* point flag */
 1403:             j = 0;              /* exp flag */
 1404:             f = '.';            /* first character */
 1405:             b = a;
 1406:             *b++ = f;
 1407:             
 1408:             goto p_entry;
 1409: 
 1410: 
 1411:         case ')':
 1412: 
 1413:             if (spx <= 1) {
 1414: 
 1415:                 if (setpiece) return;
 1416: 
 1417:                 if (spx == 0) {
 1418:                     merr_raise (BRAER);
 1419:                     return;
 1420:                 }
 1421: 
 1422:             }
 1423: 
 1424:             if (op_stck[spx] != OPERAND) {
 1425:                 merr_raise (INVEXPR);
 1426:                 return;
 1427:             }
 1428: 
 1429:             if ((f = op_stck[spx - 1]) == ARRAY) {  /* array return */
 1430:                 
 1431:                 *--a = DELIM;
 1432:                 stcpy (varnam, a = argstck[--arg]);
 1433:             
 1434:                 if ((spx -= 2) <= 0 && extyp != STRING && extyp != ARGIND) return;
 1435:                 
 1436:                 goto var1;
 1437:             
 1438:             }
 1439:             
 1440:             /* precedence close parenthesis */
 1441:             if (f == '(') {
 1442:                 spx -= 2;
 1443:                 goto nxt_operator;
 1444:             }
 1445: 
 1446:             if (spx <= 2) {
 1447:                 merr_raise (BRAER);
 1448:                 return;
 1449:             }               /* unmatched ')' */
 1450: 
 1451: 
 1452:             /**
 1453:             * *********** function evaluation ******************************************
 1454:             * 
 1455:             * Note: Input for function() is found in 'partition':
 1456:             * There are 'f' arguments to be found at 'a'
 1457:             * The arguments are separated by an EOL character.
 1458:             * There is a list of the addresses of the arguments
 1459:             * in 'a==argstck[arg], argstck[arg+1], argstck[arg+f-1]'
 1460:             * Result is returned at a==argstck[arg]
 1461:             * 
 1462:             */
 1463:             f = 1;              /* f == number of arguments */
 1464:             if (op_stck[spx -= 2] == OPERAND) {
 1465: 
 1466:                 do {
 1467:                     f++;
 1468:                     arg--;
 1469:                 } while (op_stck[spx -= 2] == OPERAND);
 1470:                 
 1471:                 a = argstck[arg];
 1472: 
 1473:             }
 1474: 
 1475:             i = op_stck[spx--];
 1476:         
 1477:             switch (i) {            /* function select */
 1478:                 
 1479: 
 1480:                 case 'e':           /* $EXTRACT */
 1481: 
 1482:                     switch (f) {
 1483: 
 1484: 
 1485:                         case 1:
 1486:                         
 1487:                             a[1] = EOL;
 1488:                             goto nxt_operator;
 1489:                         
 1490: 
 1491:                         case 2:
 1492:                         
 1493:                             b = argstck[arg + 1];
 1494:                             i = intexpr (b) - 1;    /* numeric value of 2nd argument */
 1495: 
 1496:                             /*set_io (UNIX);
 1497:                             printf ("i = %d a = '%s'\n", i, a[i]);
 1498:                             set_io (MUMPS);*/
 1499:                             
 1500:                             if (merr () == MXNUM) {
 1501:                                 merr_raise (OK);
 1502:                                 if (i >= 0) i = 256;
 1503:                             }
 1504: 
 1505:                             f = b - a - 1;      /* length of first argument */
 1506:                             
 1507:                             if (i > f || i < 0) {
 1508:                                 if (i > f) {
 1509:                                     a[0] = EOL;
 1510:                                     goto nxt_operator;
 1511:                                 }
 1512:                                 if (i < 0) {
 1513:                                     if (en_revstrf && !standard) {
 1514:                                         a[0] = a[f - (abs(i) - 1)];
 1515:                                         a[1] = EOL;
 1516:                                     }
 1517:                                     else {
 1518:                                         a[0] = EOL;
 1519:                                     }
 1520:                                 }
 1521:                             }
 1522:                             else {
 1523:                                 /* out of range */
 1524:                                 a[0] = a[i];
 1525:                                 a[1] = EOL;
 1526:                             }           /* get character */
 1527:                             
 1528:                             goto nxt_operator;
 1529: 
 1530: 
 1531:                         case 3:
 1532: 
 1533:                         {
 1534:                             char tstr[STRLEN];
 1535:                             long int e_length;
 1536:                             long int e_start;
 1537:                             long int e_end;
 1538: 
 1539:                             stcpy (tstr, a);
 1540: 
 1541:                             e_start = intexpr (argstck[arg + 1]) - 1;
 1542:                             e_end = intexpr (argstck[arg + 2]);
 1543:                             e_length = stlen(tstr);
 1544: 
 1545:                             if (e_start < 0) {
 1546: 
 1547:                                 if (en_revstrf && !standard) {
 1548:                                     e_start = e_length - abs(e_start) + 1;
 1549:                                 }
 1550:                                 else {
 1551:                                     a[0] = EOL;
 1552:                                     goto nxt_operator;
 1553:                                 }
 1554: 
 1555:                             }
 1556:                             
 1557:                             if (e_end < 0) {
 1558: 
 1559:                                 if (en_revstrf && !standard) {
 1560:                                     e_end = e_length - abs(e_end) + 1;
 1561:                                 }
 1562:                                 else {
 1563:                                     a[0] = EOL;
 1564:                                     goto nxt_operator;
 1565:                                 }
 1566: 
 1567:                             }
 1568: 
 1569:                             tstr[e_end] = EOL;
 1570:                             stcpy (a, &(tstr[e_start]));
 1571: 
 1572:                             goto nxt_operator;
 1573:                             
 1574:                         }
 1575:                             
 1576:                         default:
 1577:                             merr_raise (FUNARG); 
 1578:                                 
 1579:                             {
 1580:                                 return;
 1581:                             }
 1582: 
 1583:                     }
 1584: 
 1585:                 case 'a':           /* $ASCII */
 1586: 
 1587:                     if (f == 1) {
 1588:                         intstr (a, (*a != EOL ? UNSIGN ((int) *a) : -1));
 1589:                         goto nxt_operator;
 1590:                     }
 1591: 
 1592:                     if (f > 2) {
 1593:                         merr_raise (FUNARG);
 1594:                         return;
 1595:                     }
 1596: 
 1597:                     b = argstck[arg + 1];
 1598:                     i = intexpr (b);
 1599: 
 1600:                     /* ascii number of selected character or -1 if out of range */
 1601:                     intstr (a, (i >= (b - a)) || i <= 0 ? -1 : UNSIGN ((int) a[i - 1]));
 1602:                     
 1603:                     goto nxt_operator;
 1604: 
 1605: 
 1606:                 case 'c':           /* $CHARACTER */
 1607: 
 1608:                     {
 1609:                         short l, l1, m, n;
 1610: 
 1611:                         l1 = f;
 1612:                         i = 0;
 1613:                         f = 0;
 1614:                         j = 0;
 1615:                         m = 0;
 1616:                         n = 1;
 1617:                         l = 0;
 1618: 
 1619:                         for (;;) {
 1620:                             
 1621:                             if ((ch = a[i++]) == EOL) {
 1622: 
 1623:                                 if (m == 0) {
 1624: 
 1625:                                     if (j > DEL) {
 1626:                                     
 1627:                                         if (standard) {
 1628:                                             merr_raise (NOSTAND);
 1629:                                             return;
 1630:                                         }
 1631:                                     
 1632:                                         if (eightbit) {
 1633:                                             j &= 0377;
 1634:                                             if ((((char) j) == EOL) || (((char) j) == DELIM)) j = NUL;
 1635:                                         } 
 1636:                                         else {
 1637:                                             j &= 0177;
 1638:                                         }
 1639: 
 1640:                                     }
 1641: 
 1642:                                     if (f >= STRLEN) {
 1643:                                         a[f] = EOL;
 1644:                                         merr_raise (M75);
 1645:                                     
 1646:                                         return;
 1647:                                     }
 1648: 
 1649:                                     a[f++] = j;
 1650: 
 1651:                                 }
 1652: 
 1653:                                 if (++l >= l1) break;
 1654: 
 1655:                                 j = 0;
 1656:                                 m = 0;
 1657:                                 n = 1;
 1658:                                 
 1659:                                 continue;
 1660: 
 1661:                             }
 1662: 
 1663:                             if (n == 0) continue;
 1664:                             
 1665:                             if (ch >= '0' && ch <= '9') {
 1666:                                 j *= 10;
 1667:                                 j += ch - '0';
 1668:                             
 1669:                                 continue;
 1670:                             }
 1671: 
 1672:                             if (ch == '-') {
 1673:                                 m |= 01;
 1674:                                 continue;
 1675:                             }
 1676: 
 1677:                             if (ch != '+') n = 0;
 1678: 
 1679:                         }
 1680: 
 1681:                         a[f] = EOL;
 1682: 
 1683:                     }
 1684:                     
 1685:                     goto nxt_operator;
 1686: 
 1687: 
 1688:                 case 'p':           /* $PIECE */
 1689: 
 1690:                     {
 1691:                         long l, l1, m, n;
 1692: 
 1693:                         b = argstck[arg + 1];
 1694:                         l1 = b - a - 1;     /* length of 1st argument */
 1695: 
 1696:                         switch (f) {
 1697: 
 1698: 
 1699:                             case 2:
 1700: 
 1701:                                 f = 1;
 1702:                                 l = 1;
 1703: 
 1704:                                 break;
 1705:                             
 1706: 
 1707:                             case 3:
 1708: 
 1709:                                 f = intexpr (argstck[arg + 2]);
 1710:                                 
 1711:                                 if (merr () == MXNUM) {
 1712:                                     merr_raise (OK);
 1713:                                     if (j >= 0) f = 256;
 1714:                                 }
 1715: 
 1716:                                 if (f <= 0) {
 1717:                                     a[0] = EOL;
 1718:                                     goto nxt_operator;
 1719:                                 }
 1720: 
 1721:                                 l = f;
 1722:                                 
 1723:                                 break;
 1724:                             
 1725: 
 1726:                             case 4:
 1727: 
 1728:                                 l = intexpr (argstck[arg + 3]);
 1729:                                 
 1730:                                 if (merr () == MXNUM) {
 1731:                                     merr_raise (OK);
 1732:                                     if (l >= 0) l = 256;
 1733:                                 }
 1734: 
 1735:                                 if ((f = intexpr (argstck[arg + 2])) <= 0) f = 1;
 1736: 
 1737:                                 if (merr () == MXNUM) {
 1738:                                     merr_raise (OK);
 1739:                                     if (f >= 0) f = 256;
 1740:                                 }
 1741: 
 1742:                                 if (f > l) {
 1743:                                     a[0] = EOL;
 1744:                                     goto nxt_operator;
 1745:                                 }
 1746: 
 1747:                                 break;
 1748:                             
 1749: 
 1750:                             default:
 1751: 
 1752:                                 merr_raise (FUNARG);
 1753:                                 return;
 1754:                         }
 1755: 
 1756:                         i = 0;
 1757:                         m = 0;
 1758:                         ch = 0;
 1759:                         
 1760:                         while (b[ch] != EOL) ch++;       /* $l of 2nd arg */
 1761: 
 1762:                         if (ch == 1) {
 1763: 
 1764:                             ch = b[0];
 1765:                             j = 1;
 1766:                             
 1767:                             if (f > 1) {
 1768: 
 1769:                                 while (i < l1) {    /* scan 1st string ... */
 1770:                                 
 1771:                                     if (a[i++] != ch) continue;   /* ... for occurence of 2nd */
 1772:                                 
 1773:                                     if (++j == f) {
 1774:                                         m = i;
 1775:                                         goto p10;
 1776:                                     }
 1777: 
 1778:                                 }
 1779: 
 1780:                                 a[0] = EOL;
 1781:                                 goto nxt_operator;
 1782:                             
 1783:                             }
 1784:                             
 1785: p10:
 1786:                             for (; i < l1; i++) {
 1787: 
 1788:                                 if (a[i] != ch) continue;
 1789:                                 
 1790:                                 if (j == l) {
 1791:                                     a[i] = EOL;
 1792:                                     break;
 1793:                                 }
 1794: 
 1795:                                 j++;
 1796: 
 1797:                             }
 1798: 
 1799:                             if (m > 0) stcpy (a, &a[m]);
 1800: 
 1801:                             goto nxt_operator;
 1802: 
 1803:                         }
 1804:                         
 1805:                         if (ch == 0) {
 1806:                             a[0] = EOL;
 1807:                             goto nxt_operator;
 1808:                         }           /* 2nd arg is empty */
 1809:                         
 1810:                         /* else (ch>1) */
 1811:                         n = 1;
 1812:                         
 1813:                         if (f > 1) {
 1814: 
 1815:                             while (i < l1) {    /* scan 1st string ... */
 1816:                                 j = 0;
 1817:                                 
 1818: p20:
 1819: 
 1820:                                 if (a[i + j] != b[j]) {
 1821:                                     i++;
 1822:                                     continue;
 1823:                                 }       /* ... for occurence of 2nd */
 1824:                                 
 1825:                                 if (++j < ch) goto p20;
 1826: 
 1827:                                 i += ch;    /* skip delimiter */
 1828:                                 
 1829:                                 if (++n == f) {
 1830:                                     m = i;
 1831:                                     goto p30;
 1832:                                 }
 1833:                             }
 1834:                             
 1835:                             a[0] = EOL;
 1836:                             
 1837:                             goto nxt_operator;
 1838:                         
 1839:                         }
 1840: p30:                    
 1841:                         while (i < l1) {
 1842:                             j = 0;
 1843:                             
 1844: p40:
 1845: 
 1846:                             if (a[i + j] != b[j]) {
 1847:                                 i++;
 1848:                                 continue;
 1849:                             }
 1850: 
 1851:                             if (++j < ch) goto p40;
 1852:                             
 1853:                             if (n == l) {
 1854:                                 a[i] = EOL;
 1855:                                 break;
 1856:                             }           /* last $piece: done! */
 1857:                             
 1858:                             i += ch;
 1859:                             n++;
 1860: 
 1861:                         }
 1862: 
 1863:                         if (m > 0) stcpy (a, &a[m]);
 1864:                         
 1865:                         goto nxt_operator;
 1866:                     
 1867:                     }
 1868: 
 1869:                 case 'l':           /* $LENGTH */
 1870: 
 1871:                     if (f == 1) {
 1872:                         lintstr (a, stlen (a));
 1873:                         goto nxt_operator;
 1874:                     }
 1875: 
 1876:                     if (f > 2) {
 1877:                         merr_raise (FUNARG);
 1878:                         return;
 1879:                     }
 1880: 
 1881:                     i = 0;
 1882:                     j = 0;
 1883:                     ch = 0;
 1884:                     b = argstck[arg + 1];
 1885:                     
 1886:                     if ((f = stlen (b))) {
 1887: 
 1888:                         f--;
 1889:                         
 1890:                         while ((i = find (&a[ch], b)) > 0) {
 1891:                         j++;
 1892:                         ch += i + f;
 1893:                         }
 1894:                         
 1895:                         j++;
 1896: 
 1897:                     }
 1898: 
 1899:                     intstr (a, j);
 1900: 
 1901:                     goto nxt_operator;
 1902: 
 1903:                 case 'f':           /* $FIND */
 1904: 
 1905:                     {
 1906:                         short l1;
 1907: 
 1908:                         if (f < 2 || f > 3) {
 1909:                             merr_raise (FUNARG);
 1910:                             return;
 1911:                         }
 1912: 
 1913:                         if (f == 3) {
 1914: 
 1915:                             i = intexpr (argstck[arg + 2]);
 1916:                             
 1917:                             if (merr () == MXNUM) {
 1918:                                 
 1919:                                 if (i > 0) i = 256;
 1920:                                 
 1921:                                 merr_raise (OK);
 1922:                                 
 1923:                                 /* important special case:
 1924:                                 * $FIND("","",number) ::= $S(number<1:1,1:integer(number))
 1925:                                 * needs special treatment so that it does not yield wrong
 1926:                                 * results on large values of number.
 1927:                                 */
 1928:                                 if ((argstck[arg + 1][0] == EOL) && (i > 0)) {
 1929: 
 1930:                                     numlit (argstck[arg + 2]);
 1931:                                     
 1932:                                     i = 0;
 1933:                                     
 1934:                                     while ((a[i] = argstck[arg + 2][i]) != EOL) {
 1935: 
 1936:                                         if (a[i] == '.') {
 1937:                                             a[i] = EOL;
 1938:                                             break;
 1939:                                         }
 1940: 
 1941:                                         i++;
 1942: 
 1943:                                     }
 1944: 
 1945:                                     goto nxt_operator;
 1946: 
 1947:                                 }
 1948:                             }
 1949: 
 1950:                             i--;
 1951:                             
 1952:                             if (i < 0) i = 0;
 1953: 
 1954:                         } 
 1955:                         else {
 1956:                             i = 0;
 1957:                         }
 1958: 
 1959:                         b = argstck[arg + 1];
 1960:                         j = b - a - 1;      /* length of first argument */
 1961:                         
 1962:                         if ((l1 = stlen (b)) == 0) {
 1963:                             i++;
 1964:                             goto f20;
 1965:                         }
 1966: 
 1967:                         for (f = i; f < j; f++) {
 1968:                             
 1969:                             for (ch = 0; ch < l1; ch++) {
 1970:                                 if (a[f + ch] != b[ch]) goto f10;
 1971:                             }
 1972: 
 1973:                             i = (++f) + l1;
 1974:                             
 1975:                             goto f20;
 1976: 
 1977: f10:
 1978:                             ; /* null statement to avoid compiler error
 1979:                                  due to having a label at the end of a
 1980:                                  block */
 1981: 
 1982:                         }
 1983: 
 1984:                         i = 0;
 1985:                         
 1986: f20:
 1987: 
 1988:                         lintstr (a, i);
 1989: 
 1990:                     }
 1991: 
 1992:                     goto nxt_operator;
 1993: 
 1994: 
 1995:                 case 'j':           /* $JUSTIFY */
 1996: 
 1997:                     if (f < 2 || f > 3) {
 1998:                         merr_raise (FUNARG);
 1999:                         return;
 2000:                     } 
 2001: 
 2002:                     {
 2003:                         long l, l1;
 2004: 
 2005:                         l = intexpr (b = argstck[arg + 1]); /* 2nd arg */
 2006:                         if (merr () == MXNUM) return; /* $J() arg number overflow */
 2007:                         
 2008:                         if (l > STRLEN) {
 2009:                             /* $J() width string too long   */
 2010:                             merr_raise (M75);
 2011:                             return;
 2012:                         }
 2013: 
 2014:                         if (f == 2) {
 2015:                             f = b - a - 1;
 2016:                         } 
 2017:                         else {
 2018: 
 2019:                             f = intexpr (argstck[arg + 2]); /* 3rd arg */
 2020: 
 2021:                             if (merr () == MXNUM) return;  /* $J() arg number overflow */
 2022: 
 2023:                             if (f > (STRLEN - 2)) {
 2024:                                 /* $J() .precision too long */
 2025:                                 merr_raise (M75);
 2026:                                 return;
 2027:                             }
 2028: 
 2029:                             numlit (a);
 2030:                             
 2031:                             if (f < 0) {
 2032:                                 merr_raise (ARGER);
 2033:                                 return;
 2034:                             }
 2035: 
 2036:                             /* s j=$l(a),i=$f(a,".")-1 */
 2037:                             j = (a[0] == '-');
 2038:                             
 2039:                             if (a[j] == '.') {  /* insert leading zero */
 2040:                                 
 2041:                                 i = j;
 2042:                                 
 2043:                                 while (a[i++] != EOL);
 2044:                                 
 2045:                                 while (i > j) {
 2046:                                     a[i] = a[i - 1];
 2047:                                     i--;
 2048:                                 }
 2049: 
 2050:                                 a[j] = '0';
 2051: 
 2052:                             }
 2053: 
 2054:                             i = (-1);
 2055:                             j = 0;
 2056:                             
 2057:                             while (a[j] != EOL) {
 2058:                                 if (a[j] == '.') i = j;
 2059:                                 j++;
 2060:                             }
 2061: 
 2062:                             if (i < 0) {
 2063:                                 a[i = j] = '.';
 2064:                                 a[j + 1] = EOL;
 2065:                             } 
 2066:                             else {
 2067:                                 j--;
 2068:                             }
 2069:                             
 2070:                             if (j - i > f) {    /* rounding required */
 2071:                                 
 2072:                                 if ((l1 = f + i + 1) > STRLEN) {
 2073:                                     merr_raise (M75);
 2074:                                     return;
 2075:                                 }
 2076:                                 
 2077:                                 if (a[l1] > '4') {
 2078: 
 2079:                                     do {
 2080:                                         
 2081:                                         if (a[--l1] == '.') l1--;
 2082: 
 2083:                                         if (l1 < (a[0] == '-')) {
 2084: 
 2085:                                             for (l1 = f + i + 1; l1 > 0; l1--) a[l1] = a[l1 - 1];
 2086:                                             
 2087:                                             a[a[0] == '-'] = '1';
 2088:                                             i++;
 2089:                                             
 2090:                                             break;
 2091:                                         
 2092:                                         }
 2093:                                         
 2094:                                         a[l1]++;
 2095:                                         
 2096:                                         if (a[l1] == ':') a[l1] = '0';
 2097: 
 2098:                                     } while (a[l1] == '0');
 2099: 
 2100:                                 }
 2101: 
 2102:                                 a[f + i + 1] = EOL;
 2103:                                 
 2104:                                 if (a[0] == '-' && a[1] == '0') {
 2105:                                     
 2106:                                     l1 = 2;
 2107:                                     
 2108:                                     while (a[l1] != EOL) {
 2109:                                         
 2110:                                         if (a[l1] >= '1' && a[l1] <= '9') {
 2111:                                             l1 = 0;
 2112:                                             break;
 2113:                                         }
 2114:                                         
 2115:                                         l1++;
 2116: 
 2117:                                     }
 2118: 
 2119:                                     if (l1) {
 2120: 
 2121:                                         i--;
 2122:                                         l1 = 0;
 2123:                                         
 2124:                                         while ((a[l1] = a[l1 + 1]) != EOL) l1++;
 2125: 
 2126:                                     }
 2127:                                 }
 2128: 
 2129:                             }
 2130:                             else { /* rounding not required */
 2131: 
 2132:                                 if (f + i + 1 > STRLEN) {
 2133:                                     merr_raise (M75);
 2134:                                     return;
 2135:                                 }
 2136: 
 2137:                                 while (j < f + i) a[++j] = '0';
 2138: 
 2139:                                 a[++j] = EOL;
 2140:                             
 2141:                             }
 2142:                             
 2143:                             if (f == 0) a[i] = EOL;
 2144: 
 2145:                         }           /* end of 3 arg-form */
 2146:                         
 2147:                         if (f < l) {
 2148: 
 2149:                             i = stlen (a) + 1;
 2150:                             
 2151:                             if (++l <= i) goto nxt_operator;
 2152: 
 2153:                             while (i >= 0) a[l--] = a[i--];
 2154:                             while (l >= 0) a[l--] = SP;
 2155: 
 2156:                         }
 2157: 
 2158:                     }
 2159:                     
 2160:                     goto nxt_operator;
 2161:                 
 2162: 
 2163:                 /* case 'd': *//* $DATA */
 2164:                 /* case 'g': *//* $GET */
 2165:                 /* case 'i': *//* $INCREMENT */
 2166:                 /* case 'n': *//* $NEXT */
 2167:                 /* case ZNEXT: *//* $ZNEXT */
 2168:                 /* case ZPREVIOUS: *//* $ZPREVIOUS */
 2169:                 case 'o':           /* $ORDER */
 2170: 
 2171:                     if (f > 2) {
 2172:                         merr_raise (FUNARG);
 2173:                         return;
 2174:                     }
 2175:                     
 2176:                     stcpy (varnam, argstck[arg]);
 2177:                     ordercnt = intexpr (argstck[arg + 1]);
 2178:                     ordercounter = 0;
 2179:                     
 2180:                     if (varnam[0] != '^') {
 2181:                         symtab (fra_order, varnam, a);
 2182:                     }
 2183:                     else if (varnam[1] != '$') {
 2184:                         global  (fra_order, varnam, a);
 2185:                     }
 2186:                     else {
 2187:                         ssvn (fra_order, varnam, a);
 2188:                     }
 2189:                     
 2190:                     goto nxt_operator;
 2191: 
 2192: 
 2193:                 case 'q':           /* $QUERY */
 2194:                     
 2195:                     if (f > 2) {
 2196:                         merr_raise (FUNARG);
 2197:                         return;
 2198:                     }
 2199: 
 2200:                     stcpy (varnam, argstck[arg]);
 2201:                     ordercnt = intexpr (argstck[arg + 1]);
 2202: 
 2203:                     if (varnam[0] == '^' && varnam[1] == '$') {
 2204:                         ssvn (fra_query, varnam, a);
 2205:                     }
 2206:                     else if (ordercnt == 1) {
 2207:                         if (varnam[0] != '^') {
 2208:                             symtab (fra_query, varnam, a);
 2209:                         }
 2210:                         else {
 2211:                             global (fra_query, varnam, a);
 2212:                         }
 2213:                     }
 2214:                     else {
 2215:                         char qryarg_ext[256];
 2216: 
 2217:                         freem_ref_t *revq_ref = (freem_ref_t *) malloc (sizeof (freem_ref_t));
 2218: 
 2219:                         /* convert the $QUERY argument from internal to external format */
 2220:                         mref_init (revq_ref, MREF_RT_GLOBAL, "scratch");
 2221:                         internal_to_mref (revq_ref, varnam);
 2222:                         mref_to_external (revq_ref, qryarg_ext);
 2223: 
 2224:                         stcnv_c2m (qryarg_ext);
 2225: 
 2226:                         /* put the $QUERY argument into the local variable %INT.REVQ */
 2227:                         symtab (set_sym, "%INT.REVQ\201\201", qryarg_ext);
 2228: 
 2229:                         /* set up for calling into polyfill wrapper */
 2230:                         code[0] = '\201';
 2231:                         stcpy (code, "$^%ZREVQRY\201");
 2232: 
 2233:                         codptr = code;
 2234: 
 2235:                         f = '$';
 2236: 
 2237:                         zexflag = TRUE;
 2238: 
 2239:                         /* run the polyfill wrapper */
 2240:                         goto extra_fun;
 2241:                     }
 2242: 
 2243:                     goto nxt_operator;
 2244: 
 2245: 
 2246:                 case 'N':           /* $NAME */
 2247: 
 2248:                     if (f > 2) {
 2249:                         merr_raise (FUNARG);
 2250:                         return;
 2251:                     }
 2252: 
 2253:                     f = intexpr (argstck[arg + 1]);
 2254:                     
 2255:                     if (f < 0) {
 2256:                         merr_raise (ARGER);
 2257:                         return;
 2258:                     }
 2259: 
 2260:                     i = 0;
 2261:                     
 2262:                     while (a[++i] != EOL) {
 2263:                         if (a[i] == DELIM && --f < 0) {
 2264:                             break;
 2265:                         }
 2266:                     }
 2267:                     
 2268:                     a[i] = EOL;
 2269: 
 2270:                     stcpy (varnam, a);
 2271:                     zname (a, varnam);
 2272: 
 2273:                     goto nxt_operator;
 2274: 
 2275: 
 2276:                 case QLENGTH:           /* $QLENGTH */
 2277: 
 2278:                     if (f != 1) {
 2279:                         merr_raise (FUNARG);
 2280:                         return;
 2281:                     }
 2282: 
 2283:                     f = 0;
 2284:                     i = 0;
 2285:                     
 2286:                     {
 2287:                         int ch, quote;
 2288: 
 2289:                         quote = 0;
 2290:                         
 2291:                         while ((ch = a[i++]) != EOL) {
 2292: 
 2293:                             if (ch == '"') quote = !quote;
 2294:                             if (quote) continue;
 2295:                             if (ch == '(' && f == 0) f = 1;
 2296:                             if (ch == ',') f++;
 2297:                         
 2298:                         }
 2299:                     
 2300:                     }
 2301:                     
 2302:                     intstr (a, f);
 2303:                     
 2304:                     goto nxt_operator;
 2305: 
 2306: 
 2307:                 case QSUBSCRIPT: /* $QSUBSCRIPT */
 2308: 
 2309:                     if (f != 2) {
 2310:                         merr_raise (FUNARG);
 2311:                         return;
 2312:                     }
 2313: 
 2314:                     if ((f = intexpr (argstck[arg+1])) < -1) {
 2315:                         merr_raise (ARGER);
 2316:                         return;
 2317:                     }
 2318: 
 2319:                     { 
 2320:                         int ch, env, quote, count, startsub;
 2321:                         
 2322:                         if (f == -1) { /* get environment */
 2323:                             
 2324:                             quote = 0; 
 2325:                             env = FALSE; 
 2326:                             count = 0; 
 2327:                             startsub = 0; 
 2328:                             i = 0;
 2329: 
 2330:                             while ((ch = a[i++]) != EOL) {
 2331: 
 2332:                                 if (ch == '"') quote= !quote;
 2333:                                 if (quote) continue;
 2334: 
 2335:                                 if (ch == '|') {
 2336:                                     
 2337:                                     if (env) {
 2338:                                         a[i-1] = EOL;
 2339:                                         stcpy (a, &a[startsub]);
 2340:                                     
 2341:                                         break;
 2342:                                     
 2343:                                     }
 2344:                                     else {
 2345:                                         startsub = i;
 2346:                                         env = TRUE;
 2347:                                     }
 2348: 
 2349:                                 }
 2350: 
 2351:                             }
 2352: 
 2353:                             if (!env) *a= EOL;
 2354: 
 2355:                         }
 2356:                         else {
 2357: 
 2358:                             quote = 0; 
 2359:                             env = FALSE; 
 2360:                             count = 0; 
 2361:                             startsub = 0; 
 2362:                             i = 0;
 2363: 
 2364:                             while ((ch=a[i++])!=EOL) {
 2365: 
 2366:                                 if (ch == '"') quote = !quote;
 2367:                                 if (quote) continue;
 2368: 
 2369:                                 if (ch == '|' && count == 0) {
 2370:                                 
 2371:                                     if (env) {
 2372: 
 2373:                                         if (*a == '^') a[--i] = '^';
 2374:                                         
 2375:                                         startsub = i;
 2376: 
 2377:                                     }
 2378:                                     else {  
 2379:                                         env = TRUE;
 2380:                                     }
 2381: 
 2382:                                 }
 2383:                                 
 2384:                                 if (ch == '(' || ch == ',' || ch == ')') {
 2385:                                     
 2386:                                     if (count == f) { 
 2387:                                         a[i-1] = EOL; 
 2388:                                         break; 
 2389:                                     }
 2390:                                     
 2391:                                     count++; 
 2392:                                     startsub = i;
 2393: 
 2394:                                 }
 2395: 
 2396:                             }
 2397:                             
 2398:                             if (startsub) stcpy (a, &a[startsub]);
 2399:                             
 2400:                             if (count < f) *a = EOL;
 2401: 
 2402:                         }
 2403:                         if (a[0] == '"') { /* un-quote */
 2404: 
 2405:                             quote = 1; 
 2406:                             i = 1; 
 2407:                             f = 0;
 2408:                             
 2409:                             while ((ch = a[i++]) != EOL) {
 2410: 
 2411:                                 if (ch == '"') quote = !quote;
 2412:                                 
 2413:                                 if (quote) a[f++] = ch;
 2414: 
 2415:                             }
 2416: 
 2417:                             a[f] = EOL;
 2418: 
 2419:                         }
 2420: 
 2421:                     }
 2422: 
 2423:                 /* goto nxt_operator; */
 2424: 
 2425: 
 2426:                 case 's':           /* $SELECT */
 2427:                 
 2428:                     goto nxt_operator;
 2429: 
 2430:                     
 2431:                 case SVNstack:          /* $STACK() */
 2432: 
 2433:                     if (f > 2) {
 2434:                         merr_raise (FUNARG);
 2435:                         return;
 2436:                     }
 2437: 
 2438:                     if (f == 1) {
 2439: 
 2440:                         char iex_buf[256];
 2441:                         int iexp;
 2442:                         
 2443:                         stcpy (iex_buf, argstck[arg]);
 2444:                         iexp = atoi (iex_buf);
 2445: 
 2446:                         /*set_io (UNIX);
 2447:                         printf ("iexp = %d\n", iexp);
 2448:                         set_io (MUMPS);
 2449:                         */
 2450:                         
 2451:                         if (iexp == -1) {                            
 2452:                             intstr (a, merr_topstk);
 2453:                         }
 2454:                         else if (iexp == 0) {
 2455:                             stcpy (a, stack0);
 2456:                         }
 2457:                         else if (iexp > 0 && iexp <= merr_topstk) {
 2458: 
 2459:                             if (merr_topstk > nstx) {
 2460:                                 stcpy (a, merr_stack[merr_topstk].ECODE);
 2461:                             }
 2462:                             else {
 2463:                                 if (nestc[iexp] == '$') {
 2464:                                     stcpy (a, "$$\201");
 2465:                                 }
 2466:                                 else {
 2467:                                     if ((mtok_token_to_command (a, nestc[iexp])) != 1) {
 2468:                                         stcpy (a, "???");
 2469:                                     }
 2470:                                 }
 2471:                             }
 2472:                             
 2473:                         }
 2474:                         else {
 2475:                             merr_raise (FUNARG);
 2476:                             return;
 2477:                         }
 2478: 
 2479:                     }                
 2480: 
 2481:                     if (f == 2) {
 2482: 
 2483:                         int stkidx;
 2484:                         char sub[255];
 2485:                         char indst[255];
 2486:                         stcpy (indst, argstck[arg]);
 2487:                         stcnv_m2c (indst);
 2488: 
 2489:                         stkidx = atoi (indst);
 2490: 
 2491:                         if (stkidx > NESTLEVLS || stkidx < 0) {
 2492:                             merr_raise (FUNARG);
 2493:                             return;
 2494:                         }
 2495: 
 2496:                         stcpy (sub, argstck[2]);
 2497:                         stcnv_m2c (sub);
 2498: 
 2499:                         if (strcmp (sub, "MCODE") == 0) {
 2500:                             strcpy (a, merr_stack[stkidx].MCODE);
 2501:                         }
 2502:                         else if (strcmp (sub, "ECODE") == 0) {
 2503:                             strcpy (a, merr_stack[stkidx].ECODE);
 2504:                         }
 2505:                         else if (strcmp (sub, "PLACE") == 0) {
 2506:                             strcpy (a, merr_stack[stkidx].PLACE);
 2507:                         }
 2508:                         else {
 2509:                             merr_raise (SYNTERR);
 2510:                             return;
 2511:                         }
 2512: 
 2513:                         stcnv_c2m (a);
 2514: 
 2515:                     }
 2516: 
 2517:         
 2518:                     goto nxt_operator;
 2519: 
 2520: 
 2521:                 case FNUMBER:           /* $FNUMBER */
 2522: 
 2523:                     if (f < 2 || f > 3) {
 2524:                         merr_raise (FUNARG);
 2525:                         return;
 2526:                     } 
 2527: 
 2528:                     {
 2529: 
 2530:                         short l1;
 2531:                         short Pflag;
 2532:                         short Tflag;
 2533:                         short commaflag;
 2534:                         short plusflag;
 2535:                         short minusflag;
 2536:                         short EuroFlag;
 2537:                         short IsZero;
 2538:                         
 2539:                         Pflag = FALSE,
 2540:                         Tflag = FALSE,
 2541:                         commaflag = FALSE,
 2542:                         plusflag = FALSE,
 2543:                         minusflag = FALSE,
 2544:                         EuroFlag = FALSE,
 2545:                         IsZero = FALSE;
 2546: 
 2547:                         b = argstck[arg + 1];
 2548: 
 2549:                         while ((i = *b++) != EOL) { /* evaluate options */
 2550: 
 2551:                             switch (i) {
 2552:                         
 2553: 
 2554:                                 case 'P':
 2555: 
 2556:                                     Pflag = TRUE;
 2557:                                     continue;
 2558:                         
 2559: 
 2560:                                 case 'p':
 2561: 
 2562:                                     if (lowerflag) Pflag = TRUE;
 2563:                                     continue;
 2564:                         
 2565: 
 2566:                                 case 'T':
 2567: 
 2568:                                     Tflag = TRUE;
 2569:                                     continue;
 2570:                         
 2571: 
 2572:                                 case 't':
 2573: 
 2574:                                     if (lowerflag) Tflag = TRUE;
 2575:                                     continue;
 2576:                         
 2577: 
 2578:                                 case ',':
 2579: 
 2580:                                     commaflag = TRUE;
 2581:                                     continue;
 2582:                             
 2583: 
 2584:                                 case '.':
 2585: 
 2586:                                     EuroFlag = TRUE;
 2587:                                     continue;
 2588:                         
 2589: 
 2590:                                 case '+':
 2591: 
 2592:                                     plusflag = TRUE;
 2593:                                     continue;
 2594:                         
 2595: 
 2596:                                 case '-':
 2597: 
 2598:                                     minusflag = TRUE;
 2599: 
 2600: 
 2601:                             }
 2602:                         }
 2603: 
 2604:                         if (Pflag && (Tflag || plusflag || minusflag)) {
 2605:                             merr_raise (ARGER);
 2606:                             return;
 2607:                         }
 2608: 
 2609:                         if (f == 3) j = intexpr (argstck[arg + 2]); /* 3rd arg */
 2610:                         
 2611:                         if (merr () == MXNUM) {
 2612:                         
 2613:                             if (j >= 0) j = 256;
 2614:                         
 2615:                             merr_raise (OK);
 2616:                         
 2617:                         }
 2618: 
 2619:                         numlit (a);
 2620:                         IsZero = (a[0] == '0');
 2621: 
 2622:                         if (f == 3) {
 2623: 
 2624:                             f = j;
 2625:                             
 2626:                             if (f < 0) {
 2627:                                 merr_raise (ARGER);
 2628:                                 return;
 2629:                             }
 2630: 
 2631:                             if (f > STRLEN) {
 2632:                                 merr_raise (M75);
 2633:                                 return;
 2634:                             }
 2635: 
 2636:                             /* s j=$l(a),i=$f(a,".")-1 */
 2637:                             j = (a[0] == '-');
 2638:                             
 2639:                             if (a[j] == '.') {  /* insert leading zero */
 2640: 
 2641:                                 i = j;
 2642:                             
 2643:                                 while (a[i++] != EOL);
 2644: 
 2645:                                 while (i > j) {
 2646:                                     a[i] = a[i - 1];
 2647:                                     i--;
 2648:                                 }
 2649: 
 2650:                                 a[j] = '0';
 2651: 
 2652:                             }
 2653: 
 2654:                             i = (-1);
 2655:                             j = 0;
 2656: 
 2657:                             while (a[j] != EOL) {
 2658: 
 2659:                                 if (a[j] == '.') i = j;
 2660:                                 
 2661:                                 j++;
 2662:                             
 2663:                             }
 2664: 
 2665:                             if (i < 0) {
 2666:                                 a[i = j] = '.';
 2667:                                 a[j + 1] = EOL;
 2668:                             } 
 2669:                             else {
 2670:                                 j--;
 2671:                             }
 2672: 
 2673:                             if (j - i > f) {    /* rounding required */
 2674: 
 2675:                                 l1 = f + i + 1;
 2676: 
 2677:                                 if (a[l1] > '4') {
 2678: 
 2679:                                     do {
 2680: 
 2681:                                         if (a[--l1] == '.') l1--;
 2682: 
 2683:                                         if (l1 < 0) {
 2684: 
 2685:                                             for (l1 = f + i + 1; l1 > 0; l1--) {
 2686:                                                 a[l1] = a[l1 - 1];
 2687:                                             }
 2688:                                             
 2689:                                             a[0] = '1';
 2690:                                             i++;
 2691:                                             
 2692:                                             break;
 2693: 
 2694:                                         }
 2695: 
 2696:                                         a[l1]++;
 2697: 
 2698:                                         if (a[l1] == ':') a[l1] = '0';
 2699: 
 2700:                                     } while (a[l1] == '0');
 2701: 
 2702:                                 }
 2703: 
 2704:                                 a[f + i + 1] = EOL;
 2705:                                 
 2706:                                 if (a[0] == '-' && a[1] == '0') {
 2707: 
 2708:                                     l1 = 2;
 2709:                                     
 2710:                                     while (a[l1] != EOL) {
 2711: 
 2712:                                         if (a[l1] >= '1' && a[l1] <= '9') {
 2713:                                             l1 = 0;
 2714:                                             break;
 2715:                                         }
 2716: 
 2717:                                         l1++;
 2718: 
 2719:                                     }
 2720: 
 2721:                                     if (l1) {
 2722: 
 2723:                                         i--;
 2724:                                         l1 = 0;
 2725:                                         
 2726:                                         while ((a[l1] = a[l1 + 1]) != EOL) l1++;
 2727: 
 2728:                                     }
 2729: 
 2730:                                 }
 2731: 
 2732:                             } 
 2733:                             else {
 2734:                             
 2735:                                 if (f + i > STRLEN) {
 2736:                                     merr_raise (M75);
 2737:                                     return;
 2738:                                 }
 2739: 
 2740:                                 while (j < f + i) a[++j] = '0';
 2741: 
 2742:                                 a[++j] = EOL;
 2743:                             }
 2744:                                 
 2745:                             if (f == 0) a[i] = EOL;
 2746: 
 2747:                         }           /* end of 3 arg-form */
 2748:                         
 2749:                         if (commaflag) {
 2750: 
 2751:                             i = 0;
 2752:                             
 2753:                             while ((f = a[i]) != '.' && f != EOL) i++;
 2754:                             
 2755:                             if (a[0] == '-') {
 2756: 
 2757:                                 f = (i + 1) % 3;
 2758:                                 j = 1;
 2759:                                 i = 1;
 2760:                                 tmp[0] = '-';
 2761: 
 2762:                             } 
 2763:                             else {
 2764: 
 2765:                                 f = (i + 2) % 3;
 2766:                                 j = 0;
 2767:                                 i = 0;
 2768: 
 2769:                             }
 2770: 
 2771:                             while ((tmp[j++] = a[i]) != EOL) {
 2772: 
 2773:                                 if (j >= STRLEN) {
 2774:                                     merr_raise (M75);
 2775:                                     return;
 2776:                                 }
 2777:                                 
 2778:                                 if (a[i++] == '.') f = -1; /* do not insert comma after point */
 2779: 
 2780:                                 if (f-- == 0 && a[i] != EOL && a[i] != '.') {
 2781:                                     f = 2;
 2782:                                     tmp[j++] = ',';
 2783:                                 }
 2784: 
 2785:                             }
 2786: 
 2787:                             stcpy (a, tmp);
 2788: 
 2789:                         }
 2790: 
 2791:                         if (EuroFlag && !standard) {    /* exchange point and comma */
 2792:                             
 2793:                             i = 0;
 2794:                             
 2795:                             while ((f = a[i]) != EOL) {
 2796: 
 2797:                                 if (f == '.') a[i] = ',';
 2798:                                 if (f == ',') a[i] = '.';
 2799: 
 2800:                                 i++;
 2801: 
 2802:                             }
 2803: 
 2804:                         }
 2805: 
 2806:                         if (Tflag) {
 2807: 
 2808:                             i = stcpy (tmp, a);
 2809:                             
 2810:                             if (plusflag && tmp[0] != '-' && !IsZero) {
 2811:                             
 2812:                                 tmp[i] = '+';
 2813:                                 tmp[++i] = EOL;
 2814:                                 stcpy (a, tmp);
 2815:                             
 2816:                             } 
 2817:                             else if (tmp[0] == '-') {
 2818:                             
 2819:                                 tmp[i] = minusflag ? SP : '-';
 2820:                                 tmp[++i] = EOL;
 2821:                                 stcpy (a, &tmp[1]);
 2822:                             
 2823:                             } 
 2824:                             else {
 2825:                             
 2826:                                 tmp[i] = SP;
 2827:                                 tmp[++i] = EOL;
 2828:                                 stcpy (a, tmp);
 2829:                             
 2830:                             }
 2831: 
 2832:                             goto nxt_operator;
 2833: 
 2834:                         }
 2835: 
 2836:                         if (Pflag) {
 2837: 
 2838:                             i = stcpy (&tmp[1], a);
 2839:                             
 2840:                             if (a[0] == '-') {
 2841:                             
 2842:                                 a[0] = '(';
 2843:                                 a[i] = ')';
 2844:                                 a[++i] = EOL;
 2845:                             
 2846:                             } 
 2847:                             else {
 2848:                             
 2849:                                 tmp[0] = SP;
 2850:                                 tmp[++i] = SP;
 2851:                                 tmp[++i] = EOL;
 2852: 
 2853:                                 stcpy (a, tmp);
 2854:                             }
 2855: 
 2856:                             goto nxt_operator;
 2857: 
 2858:                         }
 2859: 
 2860:                         if (plusflag && a[0] != '-' && !IsZero) {
 2861:                             stcpy (tmp, a);
 2862:                             a[0] = '+';
 2863:                             stcpy (&a[1], tmp);
 2864:                         }
 2865: 
 2866:                         if (minusflag && a[0] == '-') {
 2867:                             stcpy (tmp, &a[1]);
 2868:                             stcpy (a, tmp);
 2869:                         }
 2870: 
 2871:                     }
 2872: 
 2873:                     goto nxt_operator;
 2874: 
 2875: 
 2876:                 case REVERSE:           /* $REVERSE */
 2877: 
 2878:                     if (f != 1) {
 2879:                         merr_raise (FUNARG);
 2880:                         return;
 2881:                     }
 2882: 
 2883:                     i = stlen (a) - 1;
 2884:                     j = i / 2;
 2885:                     i = i - j;
 2886:                     
 2887:                     while (j >= 0) {
 2888:                         f = a[j];
 2889:                         a[j--] = a[i];
 2890:                         a[i++] = f;
 2891:                     }
 2892: 
 2893:                     goto nxt_operator;
 2894: 
 2895: 
 2896:                 case 't':           /* $TEXT */
 2897: 
 2898:                     {
 2899:                         long l1, rouoldc;
 2900:                         short reload = FALSE;
 2901: 
 2902:                         if (f > 3) {
 2903:                             merr_raise (FUNARG);
 2904:                             return;
 2905:                         }
 2906: 
 2907:                         i = 0;
 2908:                         
 2909:                         if (f > 1) {
 2910:                             stcpy (tmp, argstck[arg + 1]);
 2911:                             i = intexpr (tmp);
 2912:                         }
 2913: 
 2914:                         if (a[0] == EOL) {
 2915: 
 2916:                             if (i < 0) {
 2917:                                 merr_raise (ARGER);
 2918:                                 return;
 2919:                             }
 2920: 
 2921:                             /* $T(+0) returns routine name */
 2922:                             if (i == 0) {
 2923: 
 2924:                                 if (f != 3) {
 2925:                                     stcpy (a, rou_name);
 2926:                                 } 
 2927:                                 else {
 2928:                                     stcpy (a, argstck[arg + 2]);
 2929:                                 }                                
 2930: 
 2931:                                 goto nxt_operator;
 2932: 
 2933:                             }
 2934: 
 2935:                         }
 2936: 
 2937:                         if (f == 3) {
 2938: 
 2939:                             reload = TRUE;  /* load routine; */
 2940:                             f = mcmnd;
 2941:                             mcmnd = 'd';    /* make load use standard-path */
 2942:                             
 2943:                             stcpy (tmp, argstck[arg + 2]);
 2944:                             
 2945:                             rouoldc = roucur - rouptr;
 2946:                             
 2947:                             zload (tmp);
 2948:                             
 2949:                             mcmnd = f;
 2950:                             
 2951:                             if (merr () > OK) {
 2952: 
 2953:                                 zload (rou_name);
 2954:                                 
 2955:                                 if (merr () == NOPGM) {
 2956:                                     ierr -= NOPGM; /* smw 15 nov 2023 TODO HUH?? */
 2957:                                     *a = EOL;
 2958: 
 2959:                                     goto nxt_operator;
 2960:                                 }
 2961: 
 2962:                                 return;
 2963: 
 2964:                             }
 2965: 
 2966:                         }
 2967: 
 2968:                         j = 0;
 2969:                         f = 1;
 2970:                         
 2971:                         if (a[0] != EOL) {  /* 1st arg == label */
 2972: 
 2973:                             for (;;) {
 2974:                         
 2975:                                 if (j >= (rouend - rouptr)) {
 2976:                                     a[0] = EOL;
 2977:                                     goto t_end;
 2978:                                 }
 2979: 
 2980:                                 l1 = j;
 2981:                                 f = 0;
 2982:                                 
 2983:                                 while (*(rouptr + (++l1)) == a[f++]);
 2984:                                 
 2985:                                 if (a[--f] == EOL && (*(rouptr + l1) == TAB || *(rouptr + l1) == SP || *(rouptr + l1) == '(')) break;
 2986: 
 2987:                                 j += (UNSIGN (*(rouptr + j)) + 2);  /* skip line */
 2988: 
 2989:                             }
 2990: 
 2991:                             f = 0;
 2992: 
 2993:                         }
 2994: 
 2995:                         if (i > 0) {
 2996: 
 2997:                             while (f < i) {
 2998: 
 2999:                                 if ((j = j + (UNSIGN (*(rouptr + j))) + 2) >= (rouend - rouptr)) {
 3000:                                     a[0] = EOL;
 3001:                                     goto t_end;
 3002:                                 }
 3003:                                 
 3004:                                 f++;
 3005: 
 3006:                             }
 3007: 
 3008:                         }
 3009: 
 3010:                         if (i < 0) {
 3011: 
 3012:                             j--;
 3013:                             
 3014:                             while (f != i) {
 3015: 
 3016:                                 while (*(rouptr + (--j)) != EOL && j >= 0);
 3017:                                 
 3018:                                 if (--f != i && j < 1) {
 3019:                                     a[0] = EOL;
 3020:                                     goto t_end;
 3021:                                 }
 3022: 
 3023:                             }
 3024: 
 3025:                             j++;
 3026: 
 3027:                         }
 3028: 
 3029:                         f = (-1);
 3030:                         j++;
 3031: 
 3032:                         while ((a[++f] = (*(rouptr + (j++)))) != EOL) {
 3033:                             if (a[f] == TAB || a[f] == SP)
 3034:                             break;
 3035:                         }
 3036: 
 3037:                         if (j >= (rouend - rouptr - 1)) {
 3038:                             a[0] = EOL;
 3039:                         } 
 3040:                         else {
 3041: 
 3042:                             a[f] = SP;
 3043:                             
 3044:                             while ((*(rouptr + j)) == TAB || (*(rouptr + j)) == SP) {
 3045:                                 j++;
 3046:                                 a[++f] = SP;
 3047:                             }
 3048: 
 3049:                             stcpy (&a[++f], rouptr + j);
 3050: 
 3051:                         }
 3052: 
 3053: t_end:
 3054:                         if (reload) {
 3055:                             zload (rou_name);
 3056:                             roucur = rouptr + rouoldc;
 3057:                         }           /* reload routine; */
 3058: 
 3059:                     }
 3060:                     
 3061:                     goto nxt_operator;
 3062: 
 3063: 
 3064:                 case TRANSLATE:     /* $TRANSLATE */
 3065: 
 3066:                     if (f > 3 || f < 2) {
 3067:                         merr_raise (FUNARG);
 3068:                         return;
 3069:                     } 
 3070: 
 3071:                     {
 3072:                         short   l1, m;
 3073:                         char   *c;
 3074: 
 3075:                         b = argstck[arg + 1];
 3076:                         c = argstck[arg + 2];
 3077: 
 3078:                         if (f == 2) {
 3079:                             l1 = 0;
 3080:                         }
 3081:                         else {
 3082:                             l1 = stlen (c); /* $l of 3rd arg */
 3083:                         }
 3084: 
 3085:                         m = 0;
 3086:                         f = 0;
 3087:                         
 3088:                         while ((ch = a[f++]) != EOL) {
 3089: 
 3090:                             j = 0;
 3091:                             
 3092:                             while (b[j] != EOL) {
 3093: 
 3094:                                 if (ch == b[j]) {
 3095: 
 3096:                                     if (j < l1) {
 3097:                                         ch = c[j];
 3098:                                     }
 3099:                                     else {
 3100:                                         ch = EOL;
 3101:                                     }
 3102: 
 3103:                                     break;
 3104: 
 3105:                                 }
 3106: 
 3107:                                 j++;
 3108: 
 3109:                             }
 3110: 
 3111:                             if (ch != EOL) a[m++] = ch;
 3112: 
 3113:                         }
 3114: 
 3115:                         a[m] = EOL;
 3116: 
 3117:                     }
 3118: 
 3119:                     goto nxt_operator;
 3120: 
 3121:                 case TYPE:
 3122:                 {
 3123:                     char piv[255];
 3124:                     
 3125:                     if (f != 1) {
 3126:                         merr_raise (FUNARG);
 3127:                         return;
 3128:                     }
 3129: 
 3130:                     stcpy (piv, argstck[arg]);
 3131:                     stcnv_m2c (piv);
 3132: 
 3133:                     obj_get_attribute (piv, "CLASS", a);
 3134:                     stcnv_c2m (a);
 3135:                     
 3136:                     goto nxt_operator;
 3137:                 }
 3138: 
 3139:                 case INSTANCEOF:
 3140:                 {
 3141:                     char io_inst[255];
 3142:                     char io_cls[255];
 3143:                     short io_res;
 3144:                     
 3145:                     if (f != 2) {
 3146:                         merr_raise (FUNARG);
 3147:                         return;
 3148:                     }
 3149: 
 3150:                     stcpy (io_inst, argstck[arg]);
 3151:                     stcpy (io_cls, argstck[arg + 1]);
 3152: 
 3153:                     stcnv_m2c (io_inst);
 3154:                     stcnv_m2c (io_cls);
 3155: 
 3156:                     io_res = obj_instance_of (io_inst, io_cls);
 3157:                     
 3158:                     intstr (a, (int) io_res);
 3159:                     
 3160:                     goto nxt_operator;
 3161:                 }
 3162:                 case 'r':           /* $RANDOM */
 3163: 
 3164:                     if (f != 1) {
 3165:                         merr_raise (FUNARG);
 3166:                         return;
 3167:                     } 
 3168: 
 3169:                     {
 3170:                         long ilong;
 3171: 
 3172:                         nrandom = (ran_a * nrandom + ran_b) % ran_c;
 3173: 
 3174:                         if ((i = intexpr (a)) < 1) {
 3175:                             merr_raise (ARGER);
 3176:                             return;
 3177:                         }
 3178: 
 3179:                         ilong = (nrandom * i) / ran_c;
 3180:                         
 3181:                         if (ilong < 0) ilong += i;
 3182: 
 3183:                         lintstr (a, ilong);
 3184: 
 3185:                     }
 3186: 
 3187:                     goto nxt_operator;
 3188: 
 3189: 
 3190:                 /* $VIEW */
 3191:                 case 'v':
 3192: 
 3193:                     view_fun (f, a);
 3194: 
 3195:                     if (merr () > 0) return;
 3196:                     
 3197:                     goto nxt_operator;
 3198: 
 3199: 
 3200:                 /* $ZBOOLEAN */
 3201:                 case 'B':
 3202: 
 3203:                     if (f != 3) {
 3204:                         merr_raise (FUNARG);
 3205:                         return;
 3206:                     }
 3207: 
 3208:                     i = 0;
 3209:                     ch = intexpr (argstck[arg + 2]) % 16;
 3210:                     b = argstck[arg + 1];
 3211:                     
 3212:                     if (*b == EOL) {
 3213:                         *b = 0;
 3214:                         b[1] = 0;
 3215:                     }
 3216: 
 3217:                     f = 0;
 3218:                     
 3219:                     switch (ch) {
 3220: 
 3221:                         
 3222:                         /* 1: A AND B */
 3223:                         case 1:
 3224:                         
 3225:                             while (a[i] != EOL) {
 3226: 
 3227:                                 a[i] &= b[f];
 3228:                                 i++;
 3229: 
 3230:                                 if (b[++f] == EOL) f = 0;
 3231: 
 3232:                             }
 3233: 
 3234:                             break;
 3235: 
 3236: 
 3237:                         /* 7: A OR B */                    
 3238:                         case 7:
 3239:                         
 3240:                             while (a[i] != EOL) {
 3241: 
 3242:                                 a[i] |= b[f];
 3243:                                 i++;
 3244:                                 
 3245:                                 if (b[++f] == EOL) f = 0;
 3246: 
 3247:                             }
 3248: 
 3249:                             break;
 3250:                         
 3251: 
 3252:                         /* 6: A XOR B */
 3253:                         case 6:
 3254:                         
 3255:                             while (a[i] != EOL) {
 3256:                                 
 3257:                                 a[i] = (a[i] ^ b[f]) & (eightbit ? 0377 : 0177);
 3258:                                 i++;
 3259: 
 3260:                                 if (b[++f] == EOL) f = 0;
 3261: 
 3262:                             }
 3263: 
 3264:                             break;
 3265:                         
 3266: 
 3267:                         /* 14: A NAND B */
 3268:                         case 14:
 3269:                         
 3270:                             while (a[i] != EOL) {
 3271:                                 
 3272:                                 a[i] = ~(a[i] & b[f]) & (eightbit ? 0377 : 0177);
 3273:                                 i++;
 3274: 
 3275:                                 if (b[++f] == EOL) f = 0;
 3276: 
 3277:                             }
 3278: 
 3279:                             break;
 3280:                         
 3281: 
 3282:                         /* 8: A NOR B */
 3283:                         case 8:
 3284:                         
 3285:                             while (a[i] != EOL) {
 3286: 
 3287:                                 a[i] = ~(a[i] | b[f]) & (eightbit ? 0377 : 0177);
 3288:                                 i++;
 3289: 
 3290:                                 if (b[++f] == EOL) f = 0;
 3291: 
 3292:                             }
 3293: 
 3294:                             break;
 3295:                         
 3296: 
 3297:                         /* 9: A EQUALS B */
 3298:                         case 9:
 3299:                         
 3300:                             while (a[i] != EOL) {
 3301: 
 3302:                                 a[i] = ~(a[i] ^ b[f]) & (eightbit ? 0377 : 0177);
 3303:                                 i++;
 3304: 
 3305:                                 if (b[++f] == EOL) f = 0;
 3306: 
 3307:                             }
 3308: 
 3309:                             break;
 3310:                         
 3311: 
 3312:                         /* 2: A AND NOT B */
 3313:                         case 2:
 3314:                         
 3315:                             while (a[i] != EOL) {
 3316: 
 3317:                                 a[i] &= ~b[f];
 3318:                                 i++;
 3319:                                 
 3320:                                 if (b[++f] == EOL) f = 0;
 3321: 
 3322:                             }
 3323: 
 3324:                             break;
 3325:                         
 3326: 
 3327:                         /* 11: A OR NOT B */
 3328:                         case 11:
 3329:                         
 3330:                             while (a[i] != EOL) {
 3331:                                 
 3332:                                 a[i] = (a[i] | ~b[f]) & (eightbit ? 0377 : 0177);
 3333:                                 i++;
 3334: 
 3335:                                 if (b[++f] == EOL) f = 0;
 3336:                             
 3337:                             }
 3338:                             
 3339:                             break;
 3340:                         
 3341: 
 3342:                         /* 13: NOT A OR B */
 3343:                         case 13:
 3344:                         
 3345:                             while (a[i] != EOL) {
 3346: 
 3347:                                 a[i] = (~a[i] | b[f]) & (eightbit ? 0377 : 0177);
 3348:                                 i++;
 3349:                                 
 3350:                                 if (b[++f] == EOL) f = 0;
 3351:                             
 3352:                             }
 3353:                             
 3354:                             break;
 3355:                         
 3356: 
 3357:                         /* 4: NOT A AND B */
 3358:                         case 4:
 3359:                         
 3360:                             while (a[i] != EOL) {
 3361: 
 3362:                                 a[i] = ~a[i] & b[f];
 3363:                                 i++;
 3364:                                 
 3365:                                 if (b[++f] == EOL) f = 0;
 3366: 
 3367:                             }
 3368: 
 3369:                             break;
 3370:                         
 3371: 
 3372:                         /* 5: B */
 3373:                         case 5:
 3374:                         
 3375:                             while (a[i] != EOL) {
 3376: 
 3377:                                 a[i++] = b[f];
 3378:                                 
 3379:                                 if (b[++f] == EOL) f = 0;
 3380:                             
 3381:                             }
 3382:                             
 3383:                             break;
 3384:                         
 3385: 
 3386:                         /* 10: NOT B */
 3387:                         case 10:
 3388:                         
 3389:                             while (a[i] != EOL) {
 3390:                                 
 3391:                                 a[i++] = ~b[f] & 0177;
 3392:                                 
 3393:                                 if (b[++f] == EOL) f = 0;
 3394:                             
 3395:                             }
 3396:                             
 3397:                             break;
 3398:                         
 3399: 
 3400:                         /* 12: NOT A */
 3401:                         case 12:
 3402:                         
 3403:                             while (a[i] != EOL) {
 3404: 
 3405:                                 a[i] = ~a[i] & 0177;
 3406:                                 i++;
 3407: 
 3408:                                 if (b[++f] == EOL) f = 0;
 3409: 
 3410:                             }
 3411: 
 3412:                             break;
 3413: 
 3414: 
 3415:                         /* 0: always FALSE */
 3416:                         case 0:
 3417:                         
 3418:                             while (a[i] != EOL)
 3419:                             a[i++] = 0;
 3420:                             break;
 3421: 
 3422: 
 3423:                         /* 15: always TRUE */
 3424:                         case 15:
 3425:                         
 3426:                             ch = (char) 0177;
 3427:                             while (a[i] != EOL)
 3428:                             a[i++] = ch;
 3429:                             /* 3: A */
 3430: 
 3431:                     }
 3432: 
 3433:                     goto nxt_operator;
 3434: 
 3435: 
 3436:                 /* ZCRC "cyclic redundancy check" check sums */
 3437:                 case ZCRC:
 3438: 
 3439:                     if (f == 1) {
 3440:                         f = 0;          /* missing 2nd arg defaults to "0" */
 3441:                     }
 3442:                     else {
 3443: 
 3444:                         if (f != 2) {
 3445:                             merr_raise (FUNARG);
 3446:                             return;
 3447:                         }
 3448:                         
 3449:                         if ((f = intexpr (argstck[arg + 1])) != 0 && f != 1) {
 3450:                             merr_raise (ARGER);
 3451:                             return;
 3452:                         }
 3453: 
 3454:                     }
 3455: 
 3456:                     i = 0;
 3457:                     
 3458:                     if (f == 0) {       /* XORing */
 3459: 
 3460:                         f = 0;
 3461:                     
 3462:                         while (a[i] != EOL) f ^= a[i++];
 3463: 
 3464:                         f = f & 0377;
 3465: 
 3466:                     } 
 3467:                     else {            /* ASCII sum */
 3468: 
 3469:                         f = 0;
 3470:                     
 3471:                         while (a[i] != EOL) f += a[i++];
 3472: 
 3473:                     }
 3474: 
 3475:                     intstr (a, f);
 3476:                     
 3477:                     goto nxt_operator;
 3478: 
 3479: 
 3480:                 /* $ZFUNCTIONKEY */
 3481:                 case 'F':
 3482: 
 3483:                     if (f != 1) {
 3484:                         merr_raise (FUNARG);
 3485:                         return;
 3486:                     }
 3487:                     
 3488:                     if ((i = intexpr (a)) < 1 || i > 44) {
 3489:                         merr_raise (FUNARG);
 3490:                         return;
 3491:                     }
 3492:                     
 3493:                     stcpy (a, zfunkey[i - 1]);
 3494:                     
 3495:                     goto nxt_operator;
 3496: 
 3497: 
 3498:                 case 'P':           /* $ZPIECE */
 3499: 
 3500:                     /* Similar to $PIECE                                    */
 3501:                     /* The difference is, that stuff within quotes is not   */
 3502:                     /* counted as delimiter. nor is stuff within brackets   */
 3503: 
 3504:                     {
 3505:                         short l, l1, m, n;
 3506:                         short quo = 0;    /* quotes */
 3507:                         short bra = 0;    /* brackets */
 3508:                         char ch0;
 3509: 
 3510:                         b = argstck[arg + 1];
 3511:                         l1 = b - a - 1;     /* length of 1st argument */
 3512: 
 3513:                         switch (f) {
 3514:                             
 3515: 
 3516:                             case 2:
 3517: 
 3518:                                 f = 1;
 3519:                                 l = 1;
 3520:                             
 3521:                                 break;
 3522:                             
 3523: 
 3524:                             case 3:
 3525:                                 
 3526:                                 if ((f = intexpr (argstck[arg + 2])) <= 0) {
 3527:                                     a[0] = EOL;
 3528:                                     goto nxt_operator;
 3529:                                 }
 3530: 
 3531:                                 if (merr () == MXNUM) {
 3532:                                     if (f >= 0) f = 256;
 3533:                                     merr_raise (OK);
 3534:                                 }
 3535:                                 
 3536:                                 l = f;
 3537:                                 break;
 3538:                             
 3539: 
 3540:                             case 4:
 3541:                                 
 3542:                                 l = intexpr (argstck[arg + 3]);
 3543:                                 
 3544:                                 if (merr () == MXNUM) {
 3545:                                     
 3546:                                     if (l >= 0) l = 256;
 3547:                                 
 3548:                                     merr_raise (OK);
 3549:                                 
 3550:                                 }
 3551: 
 3552:                                 if ((f = intexpr (argstck[arg + 2])) <= 0) f = 1;
 3553: 
 3554:                                 if (merr () == MXNUM) {
 3555:                                     
 3556:                                     if (f >= 0) f = 256;
 3557:                                     
 3558:                                     merr_raise (OK);
 3559:                                 
 3560:                                 }
 3561:                                 
 3562:                                 if (f > l) {
 3563:                                     a[0] = EOL;
 3564:                                     goto nxt_operator;
 3565:                                 }
 3566: 
 3567:                                 break;
 3568: 
 3569: 
 3570:                             default:
 3571:                             
 3572:                                 merr_raise (FUNARG);
 3573:                                 return;
 3574: 
 3575:                         }
 3576: 
 3577:                         i = 0;
 3578:                         m = 0;
 3579:                         ch = 0;
 3580: 
 3581:                         while (b[ch] != EOL) ch++;       /* $l of 2nd arg */
 3582: 
 3583:                         if (ch == 1) {
 3584: 
 3585:                             ch = b[0];
 3586:                             j = 1;
 3587:                             
 3588:                             if (f > 1) {
 3589: 
 3590:                                 while (i < l1) {    /* scan 1st string ... */
 3591:                                     
 3592:                                     ch0 = a[i++];
 3593:                                     
 3594:                                     if (ch != '"') {
 3595: 
 3596:                                         if (ch0 == '"') {
 3597:                                             toggle (quo);
 3598:                                             continue;
 3599:                                         }
 3600: 
 3601:                                         if (quo) continue;
 3602: 
 3603:                                     }
 3604: 
 3605:                                     if (ch0 == '(') bra++;
 3606:                                     if (ch0 == ')') bra--;
 3607: 
 3608:                                     if (ch0 != ch) continue;
 3609:                                     if (bra > 1) continue;
 3610:                                     if ((ch0 != '(') && bra) continue;
 3611:                                     
 3612:                                     if (++j == f) {
 3613:                                         m = i;
 3614:                                         goto zp10;
 3615:                                     }
 3616: 
 3617:                                 }
 3618: 
 3619:                                 /* if(j<f) */ 
 3620:                                 a[0] = EOL;
 3621: 
 3622:                                 goto nxt_operator;
 3623: 
 3624:                             }
 3625: 
 3626: zp10:
 3627: 
 3628:                             for (; i < l1; i++) {
 3629: 
 3630:                                 ch0 = a[i];
 3631:                                 
 3632:                                 if (ch != '"') {
 3633: 
 3634:                                     if (ch0 == '"') {
 3635:                                         toggle (quo);
 3636:                                         continue;
 3637:                                     }
 3638:                                     
 3639:                                     if (quo) continue;
 3640: 
 3641:                                 }
 3642: 
 3643:                                 if (ch0 == '(') bra++;
 3644:                                 if (ch0 == ')') bra--;
 3645:                                 if (ch0 != ch) continue;
 3646:                                 if (bra > 1) continue;
 3647:                                 if ((ch0 != '(') && bra) continue;
 3648: 
 3649:                                 if (j == l) {
 3650:                                     a[i] = EOL;
 3651:                                     break;
 3652:                                 }
 3653: 
 3654:                                 j++;
 3655: 
 3656:                             }
 3657: 
 3658:                             if (m > 0) stcpy (a, &a[m]);
 3659: 
 3660:                             goto nxt_operator;
 3661: 
 3662:                         }
 3663: 
 3664:                         if (ch == 0) {
 3665:                             a[0] = EOL;
 3666:                             goto nxt_operator;
 3667:                         }           /* 2nd arg is empty */
 3668: 
 3669:                         /* else (ch>1) $Length of Delimiter>1 */
 3670:                         n = 1;
 3671: 
 3672:                         if (f > 1) {
 3673: 
 3674:                             while (i < l1) {    /* scan 1st string ... */
 3675: 
 3676:                                 j = 0;
 3677:                             
 3678:                                 if ((ch0 = a[i]) == '"') {
 3679:                                     toggle (quo);
 3680:                                     i++;
 3681:                             
 3682:                                     continue;
 3683:                                 }
 3684:                             
 3685:                                 if (quo) {
 3686:                                     i++;
 3687:                                     continue;
 3688:                                 }
 3689:                                 
 3690:                                 if (ch0 == '(') {
 3691:                                     bra++;
 3692:                                     i++;
 3693:                                 
 3694:                                     continue;
 3695:                                 }
 3696:                                 
 3697:                                 if (ch0 == ')') {
 3698:                                     bra--;
 3699:                                     i++;
 3700:                                 
 3701:                                     continue;
 3702:                                 }
 3703: 
 3704:                                 if (bra) {
 3705:                                     i++;
 3706:                                     continue;
 3707:                                 }
 3708: 
 3709: zp20:
 3710:                                 if (a[i + j] != b[j]) {
 3711:                                     i++;
 3712:                                     continue;
 3713:                                 }       /* ... for occurence of 2nd */
 3714:                                 
 3715:                                 if (++j < ch) goto zp20;
 3716:                                 
 3717:                                 i += ch;    /* skip delimiter */
 3718:                                 
 3719:                                 if (++n == f) {
 3720:                                     m = i;
 3721:                                     goto zp30;
 3722:                                 }
 3723:                             }
 3724:                             
 3725:                             /* if(n<f) */ a[0] = EOL;
 3726:                             
 3727:                             goto nxt_operator;
 3728:                         }
 3729: 
 3730: zp30:
 3731: 
 3732:                         while (i < l1) {
 3733:                             
 3734:                             j = 0;
 3735:                             
 3736:                             if ((ch0 = a[i]) == '"') {
 3737:                                 toggle (quo);
 3738:                                 i++;
 3739:                             
 3740:                                 continue;
 3741:                             }
 3742:                             
 3743:                             if (quo) {
 3744:                                 i++;
 3745:                                 continue;
 3746:                             }
 3747: 
 3748:                             if (ch0 == '(') {
 3749:                                 bra++;
 3750:                                 i++;
 3751:                             
 3752:                                 continue;
 3753:                             }
 3754: 
 3755:                             if (ch0 == ')') {
 3756:                                 bra--;
 3757:                                 i++;
 3758:                             
 3759:                                 continue;
 3760:                             }
 3761: 
 3762:                             if (bra) {
 3763:                                 i++;
 3764:                                 continue;
 3765:                             }
 3766: 
 3767: zp40:                       
 3768:                             if (a[i + j] != b[j]) {
 3769:                                 i++;
 3770:                                 continue;
 3771:                             }
 3772:                             
 3773:                             if (++j < ch) goto zp40;
 3774:                                 
 3775:                             if (n == l) {
 3776:                                 a[i] = EOL;
 3777:                                 break;
 3778:                             }           /* last $zpiece: done! */
 3779:                             
 3780:                             i += ch;
 3781:                             n++;
 3782: 
 3783:                         }
 3784: 
 3785:                         if (m > 0) stcpy (a, &a[m]);
 3786: 
 3787:                         goto nxt_operator;
 3788:                     
 3789:                     }
 3790: 
 3791:                 case 'L':           /* $ZLENGTH */
 3792: 
 3793:                     /* Similar to $LENGTH with two arguments                */
 3794:                     /* The difference is, that stuff within quotes is not   */
 3795:                     /* counted as delimiter. nor is stuff within brackets   */
 3796: 
 3797:                     if (f != 2) {
 3798:                         merr_raise (FUNARG);
 3799:                         return;
 3800:                     }
 3801: 
 3802:                     i = 0;
 3803:                     j = 0;
 3804:                     
 3805:                     b = argstck[arg + 1];
 3806:                     
 3807:                     if ((f = stlen (b))) {
 3808:                         int     quo,
 3809:                         bra,
 3810:                         ch0;
 3811: 
 3812:                         quo = 0;
 3813:                         bra = 0;
 3814: 
 3815:                         if (f == 1) {       /* length of delimiter =1 char */
 3816: 
 3817:                             ch = b[0];
 3818:                             j = 0;
 3819:                         
 3820:                             for (;;) {
 3821: 
 3822:                                 ch0 = a[i++];
 3823: 
 3824:                                 if (ch0 == EOL) break;
 3825:                                 
 3826:                                 if (ch != '"') {
 3827:                                     
 3828:                                     if (ch0 == '"') {
 3829:                                         toggle (quo);
 3830:                                         continue;
 3831:                                     }
 3832: 
 3833:                                     if (quo) continue;
 3834: 
 3835:                                 }
 3836: 
 3837:                                 if (ch0 == '(') bra++;
 3838:                                 if (ch0 == ')') bra--;
 3839:                                 if (ch0 != ch) continue;
 3840:                                 if (bra > 1) continue;
 3841:                                 if ((ch0 != '(') && bra) continue;
 3842:                                 
 3843:                                 j++;
 3844:                             }
 3845: 
 3846:                             
 3847:                             j++;
 3848:                             
 3849:                         } 
 3850:                         else {
 3851: 
 3852:                             int n;
 3853: 
 3854:                             j = 1;
 3855: 
 3856:                             for (;;) {
 3857: 
 3858:                                 n = 0;
 3859: 
 3860:                                 if ((ch0 = a[i]) == '"') {                                
 3861:                                     toggle (quo);
 3862:                                     i++;
 3863:                                     
 3864:                                     continue;
 3865:                                 }
 3866: 
 3867:                                 if (ch0 == EOL) break;
 3868: 
 3869:                                 if (quo) {
 3870:                                     i++;
 3871:                                     continue;
 3872:                                 }
 3873: 
 3874:                                 if (ch0 == '(') {
 3875:                                     bra++;
 3876:                                     i++;
 3877:                                 
 3878:                                     continue;
 3879:                                 }
 3880: 
 3881:                                 if (ch0 == ')') {
 3882:                                     bra--;
 3883:                                     i++;
 3884:                                     
 3885:                                     continue;
 3886:                                 }
 3887: 
 3888:                                 if (bra) {
 3889:                                     i++;
 3890:                                     continue;
 3891:                                 }
 3892: 
 3893: zl10:                           
 3894: 
 3895:                                 if (a[i + n] != b[n]) {
 3896:                                     i++;
 3897:                                     continue;
 3898:                                 }
 3899: 
 3900:                                 if (++n < f) goto zl10;
 3901:                                 
 3902:                                 i += f;     /* skip delimiter */
 3903:                                 j++;
 3904:                             
 3905:                             }
 3906:                         }
 3907:                     }
 3908: 
 3909:                     intstr (a, j);
 3910:                     goto nxt_operator;
 3911: 
 3912:                 case ZLSD:          /* $ZLSD levenshtein function */
 3913:                     
 3914:                     if (f != 2) {
 3915:                         merr_raise (FUNARG);
 3916:                         return;
 3917:                     }
 3918: 
 3919:                     f = levenshtein (a, argstck[arg + 1]);
 3920:                     intstr (a, f);
 3921:                     
 3922:                     goto nxt_operator;
 3923: 
 3924: 
 3925:                 /* $ZKEY */
 3926:                 /* transform a string to be used as a key in an array so   */
 3927:                 /* the result string will collate in the desired way       */
 3928:                 /* according to the production rule specified by VIEW 93   */
 3929:                 case 'K':
 3930:                     
 3931:                     if (f == 2) {
 3932:                         zkey (a, intexpr (argstck[arg + 1]));
 3933:                     }
 3934:                     else if (f == 1) {
 3935:                         zkey (a, v93);
 3936:                     }
 3937:                     else {
 3938:                         merr_raise (FUNARG);
 3939:                     }
 3940:                     
 3941:                     if (merr () > OK) return;
 3942: 
 3943:                     goto nxt_operator;
 3944: 
 3945: 
 3946:                 /* $ZREPLACE */
 3947:                 /* Replace in first argument non overlapping occurences    */
 3948:                 /* of the second argument by the third argument.           */
 3949:                 /* if the third argument is missing, assume it to be empty */
 3950:                 case 'R':
 3951:                     
 3952:                     if (f == 3) {
 3953:                         zreplace (a, argstck[arg + 1], argstck[arg + 2]);
 3954:                     }
 3955:                     else if (f == 2) {
 3956:                         zreplace (a, argstck[arg + 1], "\201");
 3957:                     }
 3958:                     else {
 3959:                         merr_raise (FUNARG);
 3960:                     }
 3961: 
 3962:                     if (merr () > OK) return;
 3963: 
 3964:                     goto nxt_operator;
 3965: 
 3966: 
 3967:                 /* $ZSYNTAX */
 3968: 
 3969:                 case 'S':
 3970: 
 3971:                     if (f != 1) {
 3972:                         merr_raise (FUNARG);
 3973:                         return;
 3974:                     }
 3975: 
 3976:                     zsyntax (a);
 3977:                     
 3978:                     if (merr () > OK) return;
 3979: 
 3980:                     goto nxt_operator;
 3981: 
 3982: 
 3983:                 /* $ZTIME()/$ZDATE() */
 3984:                 case 'T':
 3985:                 case 'D':
 3986: 
 3987:                     {
 3988:                         time_t unix_epoch;
 3989:                         char *horo_time = a;
 3990:                         char fmt_string[120];
 3991:                         struct tm *zdate_time;                        
 3992:                         
 3993:                         if (f > 2) {
 3994:                             merr_raise (FUNARG);
 3995:                             return;
 3996:                         }
 3997: 
 3998:                         if (!is_horolog (horo_time)) {
 3999:                             merr_raise (ZINVHORO);
 4000:                             return;
 4001:                         }
 4002:                         
 4003:                         if (f == 2) {
 4004:                             stcpy (fmt_string, argstck[arg + 1]);
 4005:                         }
 4006:                         else if (f == 1) {
 4007:                             char zdf_key[50];
 4008: 
 4009:                             switch (i) {
 4010:                                 
 4011:                                 case 'D':
 4012:                                     sprintf (zdf_key, "^$JOB\202%d\202ZDATE_FORMAT\201", pid);
 4013:                                     break;
 4014: 
 4015:                                 case 'T':
 4016:                                     sprintf (zdf_key, "^$JOB\202%d\202ZTIME_FORMAT\201", pid);
 4017:                                     break;
 4018: 
 4019:                             }
 4020:                                                                 
 4021:                             ssvn (get_sym, zdf_key, fmt_string);
 4022:                         }
 4023:                         
 4024:                         stcnv_m2c (fmt_string);
 4025:                                 
 4026:                         unix_epoch = horolog_to_unix (horo_time);
 4027:                         zdate_time = localtime (&unix_epoch);
 4028: 
 4029:                         strftime (a, 255, fmt_string, zdate_time);
 4030:                         
 4031:                         stcnv_c2m (a);
 4032: 
 4033:                         goto nxt_operator;
 4034:                     }
 4035:                     
 4036: 
 4037:                 /* $ZHOROLOG() */
 4038:                 /* convert string date to $H format */
 4039:                 case 'H':
 4040:                     {
 4041:                         char *time_str = a;
 4042:                         char *fmt_string = argstck[arg + 1];
 4043:                         struct tm zhoro_tm;
 4044:                         unsigned long ilong;
 4045:                         unsigned long ilong1;
 4046:                         
 4047:                         if (f != 2) {
 4048:                             merr_raise (FUNARG);
 4049:                             return;
 4050:                         }
 4051: 
 4052:                         strptime (time_str, fmt_string, &zhoro_tm);
 4053: 
 4054:                         ilong1 = mktime (&zhoro_tm) + tzoffset;
 4055:                         ilong = ilong1 / 86400;
 4056: 
 4057:                         lintstr (a, ilong + 47117);
 4058:                         i = stlen (a);
 4059: 
 4060:                         a[i++] = ',';
 4061:                         ilong = ilong1 - (ilong * 86400) + 43200;
 4062: 
 4063:                         lintstr (&a[i], ilong);                       
 4064: 
 4065:                         goto nxt_operator;
 4066:                         
 4067:                     }
 4068:                     
 4069:                     
 4070:                 case GETX:          /* dummy function for implicit $GET */
 4071: 
 4072:                     /* un-stack $ZREFERENCE and $ZLOCAL */
 4073:                     stcpy (zref, refsav[--refsx]);
 4074:                     stcpy (zloc, refsav[refsx] + 256);
 4075:                     
 4076:                     free (refsav[refsx]);
 4077:                 
 4078:                 
 4079:                 case GET:           /* dummy function for $GET with two args */
 4080:                 
 4081:                     goto nxt_operator;
 4082: 
 4083:                 
 4084:                 case 'E':           /* ZEDIT */
 4085:                 
 4086:                     if (f > 4) {
 4087:                         merr_raise (FUNARG);
 4088:                         return;
 4089:                     } 
 4090: 
 4091:                     {
 4092: 
 4093:                         int k, l, rev, esc;
 4094: 
 4095:                         if (f == 1) {
 4096:                             rev = TRUE;
 4097:                             goto reverse;
 4098:                         }
 4099: 
 4100:                         j = (f == 4 ? intexpr (argstck[arg + 3]) : 1);  /* type of action */
 4101:                         
 4102:                         if ((rev = j < 0)) j = (-j);
 4103:                         if ((esc = j / 10) == 1 || esc == 2) j = j % 10;
 4104: 
 4105:                         if (j < 1 || j > 3) {
 4106:                             merr_raise (ARGER);
 4107:                             return;
 4108:                         }
 4109: 
 4110:                         f = (f >= 3 ? intexpr (argstck[arg + 2]) : 0);  /* target length */
 4111:                         
 4112:                         if (f > 255) merr_raise (ARGER);
 4113:                         
 4114:                         if (merr () > OK) return;
 4115: 
 4116:                         if (esc == 1) {     /* remove ESC-Sequences */
 4117:                             
 4118:                             stcpy (tmp, a);
 4119:                             
 4120:                             i = 0;
 4121:                             k = 0;
 4122:                             l = 1;
 4123:                             esc = 0;
 4124:                             
 4125:                             while ((a[k] = tmp[i++]) != EOL) {
 4126: 
 4127:                                 if (l) {
 4128:                                     if (a[k] != ESC) {
 4129:                                         k++;
 4130:                                         continue;
 4131:                                     }
 4132:                             
 4133:                                     if ((a[k] = tmp[i++]) != '[') continue;
 4134: 
 4135:                                     l = 0;
 4136:                                     
 4137:                                     continue;
 4138:                                 }
 4139: 
 4140:                                 if (a[k] >= '@') l = 1;
 4141: 
 4142:                             }
 4143: 
 4144:                         }
 4145: 
 4146:                         /* anything to be done ??? */
 4147:                         if (argstck[arg + 1][0] == EOL) goto reverse;
 4148:                         
 4149:                         stcpy (tmp, argstck[arg + 1]);
 4150:                         
 4151:                         if (j != 1) {       /* remove leading characters */
 4152:                             
 4153:                             i = 0;
 4154:                             k = 0;
 4155:                             
 4156:                             while (a[i] != EOL) {
 4157: 
 4158:                                 if (a[i] == tmp[k]) {
 4159:                                     i++;
 4160:                                     k = 0;
 4161:                                 
 4162:                                     continue;
 4163:                                 }
 4164:                                 
 4165:                                 if (tmp[k++] == EOL) break;
 4166:                             
 4167:                             }
 4168:                             
 4169:                             if (i) stcpy (a, &a[i]);
 4170: 
 4171:                         }
 4172: 
 4173:                         if (j != 3) {       /* remove trailing characters */
 4174: 
 4175:                             i = stlen (a) - 1;
 4176:                             k = 0;
 4177:                         
 4178:                             while (i >= 0) {
 4179:                                 
 4180:                                 if (a[i] == tmp[k]) {
 4181:                                     i--;
 4182:                                     k = 0;
 4183: 
 4184:                                     continue;
 4185:                                 }
 4186:                                 
 4187:                                 if (tmp[k++] == EOL) break;
 4188: 
 4189:                             }
 4190: 
 4191:                             a[i + 1] = EOL;
 4192: 
 4193:                         }
 4194: 
 4195:                         i = stlen (a);
 4196:                         
 4197:                         if ((f -= i) > 0) { /* characters to append */
 4198:                             
 4199:                             if (esc == 2) { /* ignore ESC-Sequences */
 4200:                                 
 4201:                                 k = 0;
 4202:                                 l = 1;
 4203: 
 4204:                                 while (a[k] != EOL) {
 4205: 
 4206:                                     if (l) {
 4207: 
 4208:                                         if (a[k++] == ESC) {
 4209:                                         
 4210:                                             f += 2;
 4211:                                             
 4212:                                             if (a[k++] == '[') l = 0;
 4213:                                         
 4214:                                         }
 4215:                                     } 
 4216:                                     else {
 4217:                                     
 4218:                                         f++;
 4219:                                     
 4220:                                         if (a[k++] >= '@') l = 1;
 4221: 
 4222:                                     }
 4223: 
 4224:                                 }
 4225: 
 4226:                             }
 4227: 
 4228:                             k = 0;
 4229:                             
 4230:                             if (j == 1) {
 4231:                                 k = f;
 4232:                                 f = 0;
 4233:                             }
 4234: 
 4235:                             if (j == 2) {
 4236:                                 k = f - f / 2;
 4237:                                 f -= k;
 4238:                             }
 4239: 
 4240:                             l = stlen (tmp);
 4241:                             
 4242:                             if (k) {        /* append on right side */
 4243:                                 
 4244:                                 a[k += i] = EOL;
 4245:                                 j = l;
 4246:                                 
 4247:                                 while (--k >= i) {
 4248: 
 4249:                                     a[k] = tmp[--j];
 4250:                                     
 4251:                                     if (j <= 0) j = l;
 4252: 
 4253:                                 }
 4254: 
 4255:                             }
 4256: 
 4257:                             if (f) {        /* append on left side */
 4258:                                 
 4259:                                 i = 0;
 4260:                                 
 4261:                                 while (l < f) tmp[l++] = tmp[i++];
 4262: 
 4263:                                 stcpy (&tmp[l], a);
 4264:                                 stcpy (a, tmp);
 4265: 
 4266:                             }
 4267: 
 4268:                         }
 4269: 
 4270: reverse: 
 4271:                         
 4272:                         if (rev) {
 4273:                             
 4274:                             i = stlen (a) - 1;
 4275:                             j = 0;
 4276:                             f = i / 2;
 4277:                         
 4278:                             while (j <= f) {
 4279:                                 k = a[j];
 4280:                                 a[j++] = a[i];
 4281:                                 a[i--] = k;
 4282:                             }
 4283: 
 4284:                         }
 4285: 
 4286:                     }
 4287: 
 4288:                     goto nxt_operator;
 4289: 
 4290:                 default:
 4291:                     merr_raise (ILLFUN);
 4292:                     return;
 4293: 
 4294: 
 4295:             }
 4296: 
 4297:             /* end of function evaluation section */
 4298: 
 4299: nxt_operator:
 4300: 
 4301:             if (spx > 0 && (f = op_stck[spx]) != ARRAY && f != '(') {
 4302:                 goto nxt_expr;
 4303:             }
 4304:             /* push answer */
 4305: 
 4306:             op_stck[++spx] = OPERAND;
 4307:             codptr++;
 4308:             
 4309:             goto nextchr;
 4310: 
 4311: 
 4312:     case '$':               /* scan function name convert upper to lower */
 4313: 
 4314:         if (op_stck[spx] == OPERAND) goto m_operator;
 4315:         if ((f = *++codptr) >= 'A' && f <= 'Z') f += 32;
 4316: 
 4317:         if (f == 'z' && standard) {
 4318:             merr_raise (NOSTAND);
 4319:             return;
 4320:         }
 4321: 
 4322:         if (f == '$' || f == '%') {         /* extrinsic function/extrinsic variable */
 4323:             
 4324:             zexflag = FALSE;
 4325: 
 4326: extra_fun:
 4327: 
 4328: 
 4329:             {
 4330:                 short   savmcmnd, savsetp;    /* stuff to be saved */
 4331:                 char    savarnam[256];
 4332:                 char   *savdofr;
 4333:                 long    savlen;
 4334:                 short   savtest;
 4335:                 short   savop;
 4336:                 char   *savargs = NULL;
 4337:                 int     savarg;
 4338:                 char   *savastck;
 4339:                 char   *savpart;
 4340:                 char   *b;
 4341:                 char   *namold;
 4342:                 long    rouoldc;
 4343:                 char    label[255],
 4344:                 routine[255];
 4345:                 short   errex;      /* FLAG: error exit */
 4346:                 short   libcall;
 4347:                 libcall = FALSE;
 4348: 
 4349:                 for (i = 0; i < 255; i++) {
 4350:                     routine[i] = '\201';
 4351:                 }
 4352:                 
 4353:                 if (f == '%') libcall = TRUE;
 4354:                 
 4355:                 savmcmnd = mcmnd;
 4356:                 savsetp = setpiece;
 4357:                 savop = setop;
 4358:                 savtest = test;
 4359:                 stcpy (savarnam, varnam);
 4360:                 savdofr = dofram0;
 4361:                 errex = FALSE;
 4362:                 
 4363:                 if ((argstck[++arg] = a) >= s) {
 4364:                     
 4365:                     char   *bak;
 4366:                     bak = partition;
 4367:                     
 4368:                     if (getpmore () == 0) {
 4369:                         merr_raise (STKOV);
 4370:                         return;
 4371:                     }
 4372: 
 4373:                     a = a - bak + partition;
 4374:                     b = b - bak + partition;
 4375: 
 4376:                 }
 4377: 
 4378:                 savlen = a - argptr;
 4379:                 savpart = partition;
 4380:                 
 4381:                 if (spx > 0) {
 4382: 
 4383:                     if ((savargs = calloc ((unsigned) (savlen + 256L), 1)) == NULL) {
 4384:                         merr_raise (STKOV);
 4385:                         return;
 4386:                     }           /* could not allocate stuff...     */
 4387:                     
 4388:                     stcpy0 (savargs, argptr, savlen + 256L);
 4389:                     argptr = partition;
 4390: 
 4391:                 }
 4392: 
 4393:                 savarg = arg;
 4394: 
 4395:                 if ((savastck = calloc ((unsigned) (arg + 1), sizeof (char *))) == NULL) {
 4396:                     merr_raise (STKOV);
 4397:                     return;
 4398:                 }           /* could not allocate stuff...     */
 4399: 
 4400:                 stcpy0 (savastck, (char *) argstck, (long) ((arg + 1) * sizeof (char *)));
 4401: 
 4402:                 b = label;      /* parse label */
 4403:                 
 4404:                 if ((ch = *++codptr) == '%') {
 4405:                     *b++ = ch;
 4406:                     codptr++;
 4407:                 }
 4408: 
 4409:                 while (((ch = *codptr) >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) {
 4410:                     *b++ = ch;
 4411:                     codptr++;
 4412:                 }
 4413: 
 4414:                 *b = EOL;
 4415:                 b = routine;               
 4416: 
 4417:                 
 4418:                 if (obj_field) {                    
 4419:                     strcpy (b, &(object_class[1]));
 4420:                     stcnv_c2m (b);
 4421:                     b += strlen (object_class) - 1;
 4422:                     *++b = EOL;
 4423:                 }
 4424:                 
 4425:                 
 4426: 
 4427:                 if (ch == '^') {    /* parse routine name */
 4428: 
 4429: 
 4430:                     
 4431:                     if (((ch = *++codptr) >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '%') {
 4432:                         *b++ = ch;
 4433:                     }
 4434:                     
 4435:                     while (((ch = *++codptr) >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) {
 4436:                         *b++ = ch;
 4437:                     }
 4438: 
 4439:                     if (libcall) {
 4440:                         char newnam[255];
 4441:                         
 4442:                         for (i = 0; i < stlen (routine); i++) {
 4443:                             routine[i] = tolower (routine[i]);
 4444:                         }
 4445: 
 4446:                         newnam[0] = '%';
 4447:                         newnam[1] = 'u';
 4448:                         newnam[2] = 'l';
 4449:                         newnam[3] = '\201';
 4450: 
 4451:                         stcat (newnam, routine);
 4452:                         
 4453:                         routine[0] = EOL;
 4454:                         stcpy (routine, newnam);
 4455: 
 4456:                         b = b + 3;                        
 4457:                     }
 4458: 
 4459:                     
 4460:                     if (routine[0] == EOL) {
 4461:                         merr_raise (ILLFUN);
 4462:                         errex = TRUE;
 4463:                         
 4464:                         goto errexfun;
 4465:                     }
 4466: 
 4467:                 }
 4468: 
 4469:                 
 4470:                 
 4471:                 {
 4472:                     char nrou[255];
 4473:                     char ntag[255];
 4474:                     char nbuf[255];
 4475: 
 4476:                     stcpy (nrou, routine);
 4477:                     stcpy (ntag, label);
 4478: 
 4479:                     stcnv_m2c (nrou);
 4480:                     stcnv_m2c (ntag);
 4481:                     
 4482: 
 4483:                     if (rtn_resolve (nrou, ntag, nbuf) != NULL) {
 4484:                         strcpy (routine, nbuf);
 4485:                         stcnv_c2m (routine);
 4486:                     }
 4487:                     else {
 4488:                         merr_raise (LBLUNDEF);
 4489:                         return;
 4490:                     }
 4491:                 }
 4492:                 
 4493:                 
 4494:                 *b = EOL;
 4495:                 
 4496:                 /* something must be specified */
 4497:                 if (label[0] == EOL && routine[0] == EOL) {
 4498:                     merr_raise (ILLFUN);
 4499:                     errex = TRUE;
 4500:                     
 4501:                     goto errexfun;
 4502:                 }
 4503: 
 4504:                 
 4505:                 if (obj_field) {
 4506:                     char t_objf[255];
 4507: 
 4508:                     snprintf (t_objf, 254, "%s\201", object_instance);
 4509:                     
 4510:                     dofram0 = dofrmptr;
 4511:                     *dofrmptr++ = DELIM;
 4512:                     dofrmptr += stcpy (dofrmptr, t_objf) + 1;
 4513:                 }
 4514:                 
 4515:                 
 4516:                 if (*codptr == '(' && *(codptr + 1) != ')') {
 4517: 
 4518:                     
 4519:                     if (!obj_field) dofram0 = dofrmptr;
 4520:                     obj_field = FALSE;
 4521:                     
 4522: 
 4523:                     //dofram0 = dofrmptr;
 4524:                     
 4525:                     i = 0;
 4526:                     codptr++;
 4527:                     
 4528:                     for (;;) {
 4529: 
 4530:                         setpiece = TRUE;    /* to avoid error on closing bracket */
 4531:                         
 4532:                         if (*codptr == '.' && (*(codptr + 1) < '0' || *(codptr + 1) > '9')) {
 4533:                             
 4534:                             codptr++;
 4535:                             
 4536:                             expr (NAME);
 4537:                             codptr++;
 4538:                             *dofrmptr++ = DELIM;    /* to indicate call by name */
 4539:                             dofrmptr += stcpy (dofrmptr, varnam) + 1;
 4540:                         
 4541:                         } 
 4542:                         else {
 4543:                             expr (STRING);
 4544:                             dofrmptr += stcpy (dofrmptr, argptr) + 1;
 4545:                         }
 4546: 
 4547:                         setpiece = FALSE;
 4548:                         i++;
 4549:                         
 4550:                         if (merr () > OK) {
 4551:                             dofrmptr = dofram0;
 4552:                             errex = TRUE;
 4553:                             
 4554:                             goto errexfun;
 4555:                         }
 4556: 
 4557:                         ch = *codptr++;
 4558:                         
 4559:                         if (ch == ',') continue;
 4560: 
 4561:                         if (ch != ')') {
 4562:                             merr_raise (COMMAER);
 4563:                             dofrmptr = dofram0;
 4564:                             errex = TRUE;
 4565: 
 4566:                             goto errexfun;
 4567:                         }
 4568: 
 4569:                         ch = *codptr;
 4570:                         
 4571:                         break;
 4572: 
 4573:                     }
 4574: 
 4575:                 } 
 4576:                 else {
 4577: 
 4578:                     
 4579:                     if (!obj_field) {
 4580:                         dofram0 = 0;                    
 4581:                     }
 4582: 
 4583:                     obj_field = FALSE;
 4584:                     
 4585:                     //dofram0 = 0;
 4586:                     if (*codptr == '(') codptr += 2;
 4587:                 
 4588:                 }
 4589: 
 4590:                 rouoldc = roucur - rouptr;
 4591:                 namold = 0;
 4592: 
 4593:                 if (routine[0] != EOL) {    /* load routine */                    
 4594:                     
 4595:                     dosave[0] = EOL;
 4596:                     loadsw = TRUE;
 4597:                     
 4598:                     while ((*(namptr++)) != EOL);
 4599:                     
 4600:                     namold = namptr;
 4601:                     
 4602:                     stcpy (namptr, rou_name);
 4603:                     zload (routine);
 4604:                     
 4605:                     if (merr () > OK) {
 4606:                         errex = TRUE;
 4607:                         goto errexfun;
 4608:                     }
 4609: 
 4610:                 } 
 4611: 
 4612:                 {
 4613: 
 4614:                     char *reg, *reg1;
 4615: 
 4616:                     reg1 = rouptr;
 4617:                     reg = reg1;
 4618:                     
 4619:                     if (label[0] != EOL) {
 4620: 
 4621:                         while (reg < rouend) {
 4622:                         
 4623:                             reg++;
 4624:                             j = 0;
 4625:                         
 4626:                             while (*reg == label[j]) {
 4627:                                 reg++;
 4628:                                 j++;
 4629:                             }
 4630:                         
 4631:                             if (label[j] == EOL) {
 4632: 
 4633:                                 if (*reg == ':') {
 4634:                                     char return_type[255];
 4635:                                     short ret_type;
 4636:                                     register int typei;
 4637: 
 4638:                                     /* we got a return type. parse it. */
 4639:                                     reg++; /* skip over the colon */
 4640: 
 4641:                                     typei = 0;
 4642:                                     
 4643:                                     while (isalpha ((ch = *reg++))) {
 4644:                                         return_type[typei++] = toupper (ch);
 4645:                                     }
 4646:                                     
 4647:                                     reg--; /* back up to the previous char so that parsing of the entry point can resume later */
 4648:                                     return_type[typei] = '\0';
 4649: 
 4650:                                     ret_type = dt_get_type (return_type);
 4651:                                     if (ret_type == DT_INVALID) {
 4652:                                         merr_raise (INVTYPE);
 4653:                                         errex = TRUE;
 4654: 
 4655:                                         goto errexfun;
 4656:                                     }
 4657: 
 4658:                                     /* save off the return type to be checked by QUIT code */
 4659:                                     extr_types[nstx + 1] = ret_type; 
 4660:                                     
 4661:                                     //printf ("return_type = '%s' *reg = '%c'\r\n", return_type, *reg);
 4662:                                 }
 4663:                                 
 4664:                                 if (*reg == TAB || *reg == SP) goto off;
 4665:                                 /* call of procedure without specifying a parameter list */
 4666: 
 4667:                                 if (*reg == '(') {
 4668: 
 4669:                                     if (dofram0 == 0) dofram0 = dofrmptr;
 4670:                                 
 4671:                                     goto off;
 4672: 
 4673:                                 }
 4674: 
 4675:                             }
 4676: 
 4677:                             reg = (reg1 = reg1 + UNSIGN (*reg1) + 2);
 4678: 
 4679:                         }
 4680: 
 4681:                         {
 4682: 
 4683:                             merr_raise (LBLUNDEF);
 4684:                             stcpy (varerr, label);  /* to be included in error message */
 4685: 
 4686:                             if (dofram0) dofrmptr = dofram0; /* reset frame pointer */
 4687: 
 4688:                             zload (rou_name);
 4689:                             
 4690:                             errex = TRUE;
 4691:                             
 4692:                             goto errexfun;
 4693: 
 4694:                         }
 4695:                     }
 4696: 
 4697: off:
 4698:                     
 4699:                     roucu0 = reg1;
 4700:                 
 4701:                 }
 4702:                 
 4703:                 if (roucu0 >= rouend) {
 4704: 
 4705:                     merr_raise (LBLUNDEF);
 4706:                     stcpy (varerr, label);  /* to be included in error message */
 4707:                     
 4708:                     if (dofram0) dofrmptr = dofram0; /* reset frame pointer */
 4709:                     
 4710:                     zload (rou_name);
 4711:                     errex = TRUE;
 4712: 
 4713:                     goto errexfun;
 4714: 
 4715:                 }
 4716: 
 4717:                 if (routine[0] != EOL) stcpy (rou_name, routine);
 4718: 
 4719:                 roucu0++;
 4720:                 forsw = FALSE;
 4721: 
 4722: #ifdef DEBUG_NEWSTACK
 4723:                 printf("Stack PUSH in expr.c!\r\n");
 4724: #endif
 4725: 
 4726:                 if (++nstx > NESTLEVLS) {
 4727:                     nstx--;
 4728:                     merr_raise (STKOV);
 4729:                     errex = TRUE;
 4730: 
 4731:                     goto errexfun;
 4732:                 }
 4733:                 else {
 4734:                     estack++;
 4735:                 }
 4736: 
 4737:                 nestc[nstx] = '$';
 4738: 
 4739: #ifdef DEBUG_NEWSTACK
 4740:                 if(!cmdptr) printf("CMDPTR is ZERO!\r\n");
 4741: #endif
 4742: 
 4743:                 nestp[nstx] = cmdptr;
 4744:                 nestn[nstx] = namold;
 4745:                 nestr[nstx] = rouoldc;
 4746:                 nestnew[nstx] = 0;
 4747:                 nestlt[nstx] = level;
 4748:                 level = 0;      /* push level ; clr level */
 4749:                 ztrap[nstx][0] = EOL;
 4750: 
 4751:                 cmdptr += stcpy (cmdptr, codptr - 1) + 1;
 4752:                 roucur = roucu0;
 4753: 
 4754:                 if (dofram0) {
 4755:                     
 4756:                     char *reg, *reg1;
 4757: 
 4758:                     reg = roucu0;
 4759:                     reg1 = dofram0;
 4760: 
 4761:                     while ((ch = (*reg++)) != '(') {
 4762: 
 4763:                         if (ch == SP || ch == TAB || ch == EOL) {
 4764:                             break;
 4765:                         }
 4766: 
 4767:                     }
 4768:                     
 4769:                     if (ch != '(') {
 4770: 
 4771:                         merr_raise (TOOPARA);
 4772:                         dofrmptr = dofram0;
 4773:                         errex = TRUE;
 4774:                         
 4775: #ifdef DEBUG_NEWSTACK
 4776:                         printf("Cheesy Stack POP in expr.c\r\n");
 4777: #endif
 4778: 
 4779: 
 4780: 
 4781:                         nstx--;
 4782:                         estack--;
 4783: 
 4784:                         goto errexfun;
 4785: 
 4786:                     }
 4787: 
 4788:                     j = 0;
 4789: 
 4790:                     if (*reg == ')') {
 4791:                         reg++;
 4792:                     }
 4793:                     else {
 4794:                         /* PARSE FORMALLIST */
 4795:                         short fl_type;
 4796:                         short fl_mandatory;
 4797:                         short fl_byref;
 4798:                         char fl_typestr[255];
 4799:                         char fl_mand;
 4800:                         short dtcheck_result;                        
 4801:                         register short typei;
 4802:                         short lastparm;
 4803:                         short gotparm;
 4804:                         int paramct;
 4805:                         
 4806:                         fl_type = DT_AUTO;
 4807:                         fl_mandatory = TRUE;
 4808:                         fl_byref = FALSE;
 4809:                         dtcheck_result = FALSE;
 4810:                         lastparm = FALSE;
 4811:                         gotparm = FALSE;
 4812:                         paramct = 0;
 4813:                         
 4814:                         while ((ch = (*reg++)) != EOL) {
 4815:                             
 4816:                             gotparm = FALSE;
 4817:                             
 4818:                             if ((ch == ':') && j) {
 4819:                                 
 4820:                                 /* we have a type specification */
 4821:                                 typei = 0;
 4822: 
 4823:                                 while ((ch = (*reg++)) != EOL) {
 4824:                                     /* parse it */
 4825:                                     if (isalpha (ch)) {
 4826:                                         fl_typestr[typei++] = ch;
 4827:                                     }
 4828:                                     else if (ch == ':') {
 4829:                                         /* we have an "optional" part */
 4830:                                         fl_typestr[typei] = '\0';
 4831:                                         fl_mand = *(reg + 1);
 4832: 
 4833:                                         if ((fl_mand == 'o') || (fl_mand == 'O')) {
 4834:                                             fl_mandatory = FALSE;
 4835:                                         }
 4836:                                         else {
 4837:                                             merr_raise (INVLIBOPT);
 4838:                                             dofrmptr = dofram0;
 4839: 
 4840:                                             errex = TRUE;
 4841: 
 4842:                                             nstx--;
 4843:                                             estack--;
 4844: 
 4845:                                             goto errexfun;
 4846:                                         }
 4847:                                     }
 4848:                                     else if ((ch == ',') || (ch == ')')) {
 4849: 
 4850:                                         if (ch == ')') {
 4851:                                             lastparm = TRUE;
 4852:                                         }
 4853: 
 4854:                                         gotparm = TRUE;
 4855:                                         paramct++;
 4856:                                         
 4857:                                         fl_typestr[typei] = '\0';
 4858:                                         fl_type = dt_get_type (fl_typestr);
 4859: 
 4860:                                         if (fl_type == DT_INVALID) {
 4861: 
 4862:                                             merr_raise (INVTYPE);
 4863:                                             dofrmptr = dofram0;     /* reset frame pointer */
 4864:                                             errex = TRUE;
 4865:                                             
 4866:                                             nstx--;
 4867:                                             estack--;
 4868: 
 4869:                                             goto errexfun;
 4870: 
 4871:                                         }
 4872:                                         
 4873:                                         break;
 4874:                                     }
 4875:                                 }                                
 4876:                             }
 4877:                             
 4878:                             if (gotparm == TRUE) {
 4879: 
 4880:                                 if (reg1[0] == DELIM) {
 4881:                                     dtcheck_result = dt_check (fl_type, reg1 + 1, paramct);
 4882:                                 }
 4883:                                 else {
 4884:                                     dtcheck_result = dt_check (fl_type, reg1, paramct);
 4885:                                 }
 4886:                             
 4887:                                 if (dtcheck_result == FALSE) {
 4888:                                     merr_raise (TYPMISMATCH);
 4889:                                     dofrmptr = dofram0;     // reset frame pointer
 4890: 
 4891:                                     errex = TRUE;
 4892: 
 4893:                                     nstx--;
 4894:                                     estack--;
 4895: 
 4896:                                     goto errexfun;
 4897:                                 }
 4898:                             }
 4899:                             
 4900:                             if ((ch == ',' || ch == ')') && j) {
 4901:                             
 4902:                                 varnam[j] = EOL;
 4903: 
 4904: #if 0
 4905:                     printf("01 [nstx] nstx is (%d) in expr.c\r\n",nstx);
 4906:                     printf("[nestnew[nstx]] is (%d) in expr.c\r\n",nestnew[nstx]);
 4907:                     printf("[newptr] newptr is [");
 4908:                     for(loop=0; loop<50; loop++) 
 4909:                     printf("%c", (newptr[loop] == EOL) ? '!' : newptr[loop]);
 4910:                     printf("] in expr.c\r\n");
 4911: #endif
 4912: 
 4913:                                 if (nestnew[nstx] == 0) nestnew[nstx] = newptr;
 4914: 
 4915:                                 if (reg1 < dofrmptr) {
 4916: 
 4917:                                     if (*reg1 == DELIM) {   /* call by reference */
 4918: 
 4919:                                         if (stcmp (reg1 + 1, varnam)) {     /* are they different?? */
 4920:                                             symtab (new_sym, varnam, "");
 4921:                                             symtab (m_alias, varnam, reg1 + 1);
 4922:                                         }
 4923: 
 4924:                                     } 
 4925:                                     else {
 4926:                                         symtab (new_sym, varnam, "");   /* call by value */
 4927:                                         symtab (set_sym, varnam, reg1);
 4928:                                     }
 4929: 
 4930:                                     reg1 += stlen (reg1) + 1;
 4931: 
 4932:                                 } 
 4933:                                 else {
 4934:                                     symtab (new_sym, varnam, "");
 4935:                                 }
 4936:                                 
 4937:                                 if (ch == ')') break;
 4938:                                 
 4939:                                 j = 0;
 4940:                                 continue;
 4941:                             }
 4942: 
 4943:                             if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9' && j) || (ch == '%' && j == 0)) {
 4944:                                 varnam[j++] = ch;
 4945:                                 continue;
 4946:                             }
 4947:                             
 4948:                             merr_raise (ARGLIST);
 4949:                             dofrmptr = dofram0;     /* reset frame pointer */
 4950:                             errex = TRUE;
 4951: 
 4952:                             nstx--;
 4953:                             estack--;
 4954: 
 4955:                             goto errexfun;
 4956: 
 4957:                         }
 4958: 
 4959:                     }
 4960: 
 4961:                     if (reg1 < dofrmptr) {
 4962:                         merr_raise (TOOPARA);
 4963:                         dofrmptr = dofram0; /* reset frame pointer */
 4964:                         errex = TRUE;
 4965:                         nstx--;
 4966:                         estack--;                    
 4967: 
 4968:                         goto errexfun;
 4969:                     }
 4970: 
 4971:                     dofrmptr = dofram0;
 4972:                 
 4973:                 }
 4974: 
 4975:                 xecline (0);
 4976: 
 4977:                 if (repQUIT) {      /* repeat QUIT */
 4978: 
 4979:                     stcpy (code, " V 26:\201");
 4980: 
 4981: #ifdef DEBUG_NEWSTACK
 4982:                     printf("Trying to get at nstx in expr.c (2)\r\n");
 4983: #endif
 4984: 
 4985:                     intstr (&code[6], nstx - repQUIT);
 4986:                     repQUIT = 0;
 4987:                     codptr = code;
 4988: 
 4989:                     return;
 4990: 
 4991:                 }
 4992: 
 4993:                 stcpy (tmp, argptr);
 4994: 
 4995: errexfun:
 4996: 
 4997:                 mcmnd = savmcmnd;
 4998:                 setpiece = savsetp;
 4999:                 setop = savop;
 5000:                 test = savtest;
 5001:                 
 5002:                 stcpy (varnam, savarnam);
 5003:                 
 5004:                 dofram0 = savdofr;
 5005:                 argptr = partition;
 5006:                 a = argptr;
 5007:                 
 5008:                 if (spx > 0) {
 5009:                     stcpy0 (argptr, savargs, savlen + 256L);
 5010:                     free (savargs);
 5011:                 }
 5012:                 
 5013:                 arg = savarg;
 5014:                 stcpy0 ((char *) argstck, savastck, (long) ((arg + 1) * sizeof (char *)));
 5015: 
 5016:                 free (savastck);
 5017:                 a = savlen + argptr;
 5018:                 
 5019:                 if (savpart != partition) { /* autoadjust may have changed that */
 5020:                     
 5021:                     f = 0;
 5022: 
 5023:                     while (f <= arg) {
 5024: 
 5025:                         if (argstck[f]) argstck[f] = argstck[f] - savpart + partition;
 5026:                     
 5027:                         f++;
 5028: 
 5029:                     }
 5030: 
 5031:                 }
 5032: 
 5033:                 if (errex) {
 5034: 
 5035:                     if (zexflag && (merr () == NOPGM || merr () == LBLUNDEF)) merr_raise (ILLFUN);
 5036:                     return;
 5037:                 
 5038:                 }
 5039: 
 5040:                 if (merr () != OK) return;
 5041: /*                if (ierr != OK && ierr != (OK - CTRLB)) return;*/
 5042: 
 5043:                 stcpy (a, tmp);
 5044:                 
 5045:                 goto exec;
 5046:             
 5047:             }               /* end of extrinsic function/variable section */
 5048:         
 5049:         } 
 5050:         else if (((ch = *++codptr) >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
 5051: 
 5052:             if (ch < 'a') ch += 32;
 5053: 
 5054:             tmp[0] = SP;
 5055:             tmp[1] = f;
 5056:             tmp[2] = ch;
 5057:             b = &tmp[3];
 5058:             
 5059:             while (((ch = *++codptr) >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) *b++ = ch | 0140;
 5060: 
 5061:             *b++ = SP;
 5062:             *b = EOL;
 5063:             
 5064:             if (ch == '(') {        /* function */
 5065: 
 5066:                 if (f != 'z') {     /* standard instrinsic functions */
 5067: 
 5068:                     if (find (" ascii char data extract find fn fnumber get increment ins instanceof justify length na name next order piece \
 5069:                     query qlength ql qsubscript qs random re reverse select st stack text tr translate ty type view ", tmp) == FALSE) {
 5070:                         merr_raise (ILLFUN);
 5071:                         return;
 5072:                     }
 5073: 
 5074:                     if (f == 'f' && tmp[2] == 'n') f = FNUMBER;
 5075:                     else if (f == 'q' && tmp[2] == 'l') f = QLENGTH;
 5076:                     else if (f == 'q' && tmp[2] == 's') f = QSUBSCRIPT;
 5077:                     else if (f == 'r' && tmp[2] == 'e') f = REVERSE;
 5078:                     else if (f == 's' && tmp[2] == 't') f = SVNstack;
 5079:                     else if (f == 't' && tmp[2] == 'r') f = TRANSLATE;
 5080:                     else if (f == 'n' && tmp[2] == 'a') f = 'N';
 5081:                     else if (f == 't' && tmp[2] == 'y') f = TYPE;
 5082:                     else if (f == 'i' && tmp[3] == 's') f = INSTANCEOF;                   
 5083: 
 5084:                 } 
 5085:                 else {
 5086: 
 5087:                     /* userdefined intrinsic: process as extrinsic */
 5088:                     if ((find (zfunctions, tmp) == FALSE) && (tmp[2] != 'f' || tmp[3] != SP)) {
 5089:                         
 5090:                         f = stlen (tmp) - 1;
 5091:                         stcpy (&tmp[f], codptr);
 5092:                         
 5093:                         code[0] = '$';
 5094:                         code[1] = '^';
 5095:                         code[2] = '%';
 5096:                         code[3] = 'Z';
 5097:                         
 5098:                         stcpy (&code[4], &tmp[2]);
 5099:                         
 5100:                         codptr = code;
 5101:                         f = '$';
 5102:                         zexflag = TRUE;
 5103:                         
 5104:                         goto extra_fun;
 5105: 
 5106:                     }
 5107: 
 5108:                     f = tmp[2] - 32;
 5109: 
 5110:                     if (tmp[3] == SP) {
 5111: 
 5112:                         if (f == 'S' && s_fun_flag == FALSE) f = 'o';    /* ZSORT(=$ORDER) instead of ZSYNTAX */
 5113:                         if (f == 'P' && p_fun_flag == FALSE) f = ZPREVIOUS;  /* ZPREVIOUS instead of ZPIECE */
 5114:                         if (f == 'D' && d_fun_flag == FALSE) f = ZDATA;  /* ZDATA instead of ZDATE */
 5115:                         if (f == 'N' && n_fun_flag == FALSE) f = ZNEXT;  /* ZNEXT instead of ZNAME */
 5116:                         
 5117:                     } 
 5118:                     else {
 5119: 
 5120:                         switch (f) {
 5121: 
 5122: 
 5123:                             case 'C':
 5124:                                 if ((stcmp (" zcrc \201", tmp) == 0) ||
 5125:                                 (stcmp (" zcr \201", tmp) == 0))
 5126:                                 f = ZCRC;
 5127:                                 break;
 5128: 
 5129: 
 5130:                             case 'D':
 5131:                                 if (stcmp (" zdata \201", tmp) == 0)
 5132:                                 f = ZDATA;
 5133:                                 break;
 5134: 
 5135: 
 5136:                             case 'L':
 5137:                                 if (stcmp (" zlsd \201", tmp) == 0)
 5138:                                 f = ZLSD;
 5139:                                 break;
 5140: 
 5141: 
 5142:                             case 'N':
 5143:                                 if (stcmp (" znext \201", tmp) == 0)
 5144:                                 f = ZNEXT;
 5145:                                 break;
 5146: 
 5147: 
 5148:                             case 'P':
 5149:                                 if (stcmp (" zprevious \201", tmp) == 0)
 5150:                                 f = ZPREVIOUS;
 5151:                                 break;
 5152: 
 5153:                             case 'S':
 5154:                                 if (stcmp (" zsort \201", tmp) == 0)
 5155:                                 f = 'o';    /* process $ZSORT as $ORDER */
 5156:                                 break;
 5157:                                                         
 5158: 
 5159:                         }
 5160: 
 5161:                     }
 5162:                 }
 5163:             } 
 5164:             else {            /* special variable */
 5165: 
 5166:                 if (f != 'z') {
 5167:                     
 5168:                     if (find (" di dialect ec ecode es estack et etrap device horolog io job key pd pdisplay principal quit reference st stack storage sy system test ti timezone tl tlevel tr trollback wi with ", tmp) == FALSE) {
 5169:                         merr_raise (ILLFUN);
 5170:                         return;
 5171:                     }
 5172: 
 5173:                     if (f == 's') {
 5174: 
 5175:                         if (tmp[2] == 'y') f = SVNsystem;
 5176:                         if (tmp[2] == 't') f = SVNstack;
 5177: 
 5178:                     }
 5179: 
 5180:                     if (f == 'd') {
 5181:                         f = SVNdialect;
 5182:                     }
 5183:                     
 5184:                     if (f == 'e') {
 5185:                         
 5186:                         if (tmp[2] == 'c') f = SVNecode;
 5187:                         if (tmp[2] == 's') f = SVNestack;
 5188:                         if (tmp[2] == 't') f = SVNetrap;
 5189: 
 5190:                     }
 5191: 
 5192:                     if (f == 'p' && tmp[2] == 'd') f = SVNpdisplay;                        
 5193: 
 5194:                     if (f == 't') {
 5195:                         
 5196:                         if (tmp[2] == 'i') f = SVNtimezone;
 5197:                         if (tmp[2] == 'l') f = SVNtlevel;
 5198:                         if (tmp[2] == 'r') f = SVNtrollback;
 5199: 
 5200:                     }
 5201: 
 5202:                 } 
 5203:                 else {
 5204: 
 5205:                     if (find (zsvn, tmp) == FALSE) {
 5206:                         *(--b) = EOL;   /* there's a SPace we don't need */
 5207:                         f = ' ';    /* user defined svn */
 5208:                     } 
 5209:                     else {
 5210: 
 5211:                         f = tmp[2] - 32;
 5212: 
 5213:                         if (f == 'T' && tmp[3] == 'r' && (tmp[4] == SP || (stcmp (" ztrap \201", tmp) == 0))) f = ZTRAP;
 5214: 
 5215:                         if (f == 'M') { /* loadable match */
 5216: 
 5217:                             if ((f = tmp[3]) >= 'a' && f <= 'z') f -= 32;
 5218: 
 5219:                             f -= 64;
 5220: 
 5221:                         }
 5222: 
 5223:                         if (f == 'U' && tmp[3] == 't') f = SVNzut;
 5224:                             
 5225:                     }
 5226:                 }
 5227:             }
 5228:         }
 5229: 
 5230:         if (ch != '(') {        /* 'special variable' */
 5231:         
 5232:             codptr--;
 5233:         
 5234:             if (extyp != STRING && extyp != ARGIND && spx == 0) {
 5235:                 return;
 5236:             }
 5237: 
 5238:             if ((argstck[++arg] = a) >= s) {
 5239: 
 5240:                 char   *bak;
 5241:                 bak = partition;
 5242: 
 5243:                 if (getpmore () == 0) {
 5244:                     merr_raise (STKOV);
 5245:                     return;
 5246:                 }
 5247: 
 5248:                 a = a - bak + partition;
 5249:                 b = b - bak + partition;
 5250: 
 5251:             }
 5252: 
 5253:             /************* special variable evaluation ************************************/
 5254:             switch (f) {
 5255: 
 5256: 
 5257:                 /* $ZUUID */
 5258:                 case 'U':
 5259: 
 5260:                     uuid_v4 (a);
 5261:                     stcnv_c2m (a);
 5262:                     
 5263:                     goto exec;
 5264: 
 5265: #if !defined(__osf__)
 5266:                 case SVNzut:
 5267:                 {
 5268:                     unsigned long long res;
 5269:                     
 5270:                     struct timeval tv;
 5271:                     gettimeofday(&tv, NULL);
 5272: 
 5273:                     res = tv.tv_sec * 1000000 + tv.tv_usec;
 5274: 
 5275:                     sprintf (a, "%llu\201", res);
 5276: 
 5277:                     goto exec;
 5278:                 }
 5279: #endif
 5280:                 
 5281:                 /* $JOB */
 5282:                 case 'j':
 5283: 
 5284:                     lintstr (a, pid);
 5285: 
 5286:                     goto exec;
 5287: 
 5288: 
 5289:                 /* $IO */
 5290:                 case 'i':
 5291: 
 5292:                     intstr (a, io);
 5293:                     i = stlen (a);
 5294:                     a[i++] = ':';
 5295:                     a[i++] = '"';
 5296:                     i += stcpy (&a[i], dev[io]);
 5297:                     a[i++] = '"';
 5298:                     a[i] = EOL;
 5299: 
 5300:                     goto exec;
 5301:                     
 5302:                 case SVNdialect:
 5303:                 {
 5304:                     short rb_slot;
 5305:                     rb_slot = rbuf_slot_from_name (rou_name);
 5306: 
 5307:                     switch (rbuf_flags[rb_slot].dialect) {
 5308: 
 5309:                         case D_FREEM:
 5310:                             sprintf (a, "FREEM\201");
 5311:                             break;
 5312:                             
 5313:                         case D_MDS:
 5314:                             sprintf (a, "MDS\201");
 5315:                             break;
 5316: 
 5317:                         case D_M77:
 5318:                             sprintf (a, "M77\201");
 5319:                             break;
 5320: 
 5321:                         case D_M84:
 5322:                             sprintf (a, "M84\201");
 5323:                             break;
 5324: 
 5325:                         case D_M90:
 5326:                             sprintf (a, "M90\201");
 5327:                             break;
 5328: 
 5329:                         case D_M95:
 5330:                             sprintf (a, "M95\201");
 5331:                             break;
 5332: 
 5333:                         case D_M5:
 5334:                             sprintf (a, "M5\201");
 5335:                             break;
 5336:                     }
 5337: 
 5338:                     goto exec;
 5339:                             
 5340:                 }
 5341: 
 5342:                 /* $PDISPLAY */
 5343:                 case SVNpdisplay:
 5344: 
 5345:                     if (getenv ("DISPLAY") != NULL) {
 5346:                         char *mwapi_display;
 5347:                         char disp_temp[255];
 5348: 
 5349:                         mwapi_display = getenv ("DISPLAY");
 5350:                         strncpy (disp_temp, mwapi_display, 255);
 5351:                         stcnv_c2m (disp_temp);
 5352:                         stcpy (a, disp_temp);
 5353:                     }
 5354:                     else {
 5355:                         intstr (a, 0);
 5356:                     }
 5357:                     goto exec;
 5358: 
 5359:                 /* $PRINCIPAL */
 5360:                 case 'p':
 5361: 
 5362:                     a[0] = '0';
 5363:                     a[1] = ':';
 5364:                     a[2] = '"';
 5365:                     i = 3 + stcpy (&a[3], dev[HOME]);
 5366:                     a[i++] = '"';
 5367:                     a[i] = EOL;
 5368: 
 5369:                     goto exec;
 5370: 
 5371: 
 5372:                 /* $QUIT */
 5373:                 case 'q':
 5374: 
 5375:                     a[0] = '0' | (nestc[nstx] == '$');
 5376: 
 5377: 
 5378: 
 5379:                     a[1] = EOL;
 5380: 
 5381:                     goto exec;
 5382: 
 5383: 
 5384:                 /* $TEST */
 5385:                 case 't':
 5386:                     
 5387:                     a[0] = '0' | test;
 5388:                     a[1] = EOL;
 5389: 
 5390:                     goto exec;
 5391: 
 5392: 
 5393:                 /* $HOROLOG */
 5394:                 case 'h':
 5395: 
 5396:                     {
 5397: 
 5398:                         unsigned long ilong, ilong1;
 5399: 
 5400:                         ilong1 = time (0L) + tzoffset;  /* make $H local time */
 5401:                         ilong = ilong1 / 86400;
 5402:                         
 5403:                         lintstr (a, ilong + 47117);
 5404:                         i = stlen (a);
 5405:                         
 5406:                         a[i++] = ',';
 5407:                         ilong = ilong1 - (ilong * 86400);
 5408:                         
 5409:                         lintstr (&a[i], ilong);
 5410: 
 5411: //                        printf ("unix epoch = %d\r\n", horolog_to_unix (a));
 5412:                         
 5413:                         goto exec;
 5414: 
 5415:                     }
 5416: 
 5417: 
 5418:                 /* $ZHOROLOG() */
 5419:                 case 'H':
 5420:                     {
 5421: 
 5422:                         unsigned long ilong, ilong1;
 5423:                     
 5424: #if defined(USE_GETTIMEOFDAY) && !defined(__osf__)
 5425:                     
 5426:                         struct timeval timebuffer;
 5427:                         gettimeofday (&timebuffer, NULL);
 5428:                         
 5429:                         ilong1 = timebuffer.tv_sec + tzoffset;  /* make $ZH local time */
 5430:                     
 5431: #else
 5432: 
 5433:                         struct timeb timebuffer;
 5434:                         ftime (&timebuffer);
 5435:                         ilong1 = timebuffer.time + tzoffset;    /* make $ZH local time */
 5436:                     
 5437: #endif
 5438:                     
 5439:                         ilong = ilong1 / 86400;
 5440:                         lintstr (a, ilong + 47117);
 5441:                         i = stlen (a);
 5442:                         a[i++] = ',';
 5443:                         ilong = ilong1 - (ilong * 86400);
 5444:                         lintstr (&a[i], ilong);
 5445: 
 5446: #if defined(USE_GETTIMEOFDAY) && !defined(__osf__)
 5447:                         if ((ilong = timebuffer.tv_usec)) 
 5448: #else
 5449:                         if ((ilong = timebuffer.millitm)) 
 5450: #endif
 5451:                         {
 5452:                             char doggie_bag[50];
 5453: 
 5454:                             snprintf (doggie_bag, 49, ".%ld\201", ilong);
 5455:                             stcat (a, doggie_bag);
 5456:                         }
 5457:                     }
 5458:                     goto exec;
 5459: 
 5460: 
 5461:                 case SVNsystem:
 5462: 
 5463:                     snprintf (a, 512, "%d,\"%s\"\201", MDC_VENDOR_ID, jour_hostid); 
 5464:                     goto exec;
 5465: 
 5466: 
 5467:                 case SVNtimezone:
 5468: 
 5469:                     lintstr (a, tzoffset);
 5470:                     goto exec;
 5471: 
 5472: 
 5473:                 case SVNtlevel:
 5474: 
 5475:                     snprintf (a, 255, "%d\201", tp_level);
 5476:                     goto exec;
 5477: 
 5478: 
 5479:                 case SVNtrollback:
 5480: 
 5481:                     a[0] = '0';
 5482:                     a[1] = EOL;
 5483:                     goto exec;
 5484: 
 5485: 
 5486:                 case SVNecode:    
 5487: 
 5488:                     //write_m ("in SVNecode\r\n\201"); 
 5489: 
 5490:                     if (stlen (user_ecode)) {
 5491:                         stcpy (a, user_ecode);
 5492:                     }
 5493:                     else {
 5494:                         stcpy (a, ecode);
 5495:                     }
 5496:                     
 5497:                     goto exec;
 5498: 
 5499: 
 5500:                 case SVNestack:
 5501:                     {
 5502:                         char esbuf[256];
 5503:                         snprintf (esbuf, 255, "%d\201", estack);
 5504: 
 5505:                         stcpy (a, esbuf);
 5506:                         goto exec;
 5507: 
 5508:                     }
 5509: 
 5510: 
 5511:                 case SVNetrap:
 5512: //                    write_m ("in SVNetrap\r\n\201");
 5513:                     stcpy (a, etrap);
 5514:                     goto exec;
 5515: 
 5516: 
 5517:                 case SVNstack:
 5518:                     
 5519:                     intstr (a, nstx);
 5520: 
 5521:                     goto exec;
 5522: 
 5523: 		    
 5524:                 /* $KEY */
 5525:                 case 'k':
 5526: 
 5527: 		    stcpy (a, zb);
 5528: 		    if (*a >= SP && *a < DEL) *a = EOL;
 5529: 
 5530: 		    goto exec;
 5531: 
 5532: 		    
 5533:                 /* $DEVICE */
 5534:                 case 'd':
 5535:                     if (devstat[io].mdc_err == 0) {
 5536:                         snprintf (a, 3, "0\201\0");		  
 5537:                     }
 5538:                     else {
 5539:                         snprintf (a, 120, "%d,%d,%s\201\0", devstat[io].mdc_err, devstat[io].frm_err, devstat[io].err_txt);
 5540:                     }
 5541: 
 5542:                     goto exec;
 5543: 		    
 5544:                 /* $STORAGE */
 5545:                 case 's':
 5546: 		    snprintf (a, 255 , "%ld\201", DEFPSIZE);
 5547: 		    goto exec;
 5548: 
 5549: 		/* $WITH */
 5550: 		case 'w':
 5551: 		    stcpy (a, i_with);
 5552: 		    goto exec;
 5553: 		    
 5554:                 /* $X */
 5555:                 case 'x':
 5556: 
 5557: 		    intstr (a, xpos[io]);
 5558: 		    goto exec;
 5559: 
 5560: 		    
 5561:                 /* $Y */
 5562:                 case 'y':
 5563: 
 5564: 		    intstr (a, ypos[io]);
 5565: 		    goto exec;
 5566: 
 5567: 		    
 5568:                 /* non-standard special variables */
 5569: 
 5570:                 /* $ZA - on HOME device dummy, else byte offset to begin of file */
 5571:                 case 'A':
 5572: 		    if (io == HOME) {
 5573: 			a[0] = '0';
 5574: 			a[1] = EOL;
 5575: 		    }
 5576: 		    else {
 5577: 			lintstr (a, ftell (opnfile[io]));
 5578: 		    }
 5579: 		    goto exec;
 5580: 
 5581: 		    
 5582:                 /* $ZB - last keystroke */
 5583:                 case 'B':
 5584: 		    stcpy (a, zb);
 5585: 		    goto exec;
 5586: 
 5587: 		    
 5588:                 /* $ZCONTROLC flag */
 5589:                 case 'C':
 5590: 		    a[0] = '0' | zcc;
 5591: 		    zcc = FALSE;
 5592: 		    a[1] = EOL;
 5593: 		    goto exec;
 5594: 
 5595: 
 5596:                 ///* $ZX (number of columns) */
 5597:                 //case 'X':
 5598:                 //intstr (a, n_columns);
 5599:                 // goto exec;
 5600: 
 5601:                 ///* $ZY (number of rows) */
 5602:                 //case 'Y':
 5603:                 //intstr (a, n_lines);
 5604:                 //goto exec;
 5605: 
 5606:                 /* $ZERROR */
 5607:                 case 'E':
 5608: 		    stcpy (a, zerror);
 5609: 		    goto exec;
 5610: 
 5611: 		    
 5612:                 /* $ZTRAP */
 5613:                 case ZTRAP:
 5614: 
 5615: 		    stcpy (a, ztrap[nstx]);
 5616: 
 5617: 		    goto exec;
 5618: 
 5619: 		    
 5620:                 /* $ZPRECISION */
 5621:                 case 'P':
 5622: 		    intstr (a, zprecise);
 5623: 		    goto exec;
 5624: 
 5625: 		    
 5626:                 /* $ZSYSTEM */
 5627:                 case 'S':
 5628: 		    intstr (a, zsystem);
 5629: 		    goto exec;
 5630: 
 5631: 		    
 5632:                 /* $ZVERSION */
 5633:                 case 'V':
 5634: 		    stcpy (&a[stcpy (a, "FreeM \201")], FREEM_VERSION_STR);
 5635: 		    goto exec;
 5636: 
 5637: 		    
 5638:                 /* $ZNAME */
 5639:                 case 'N':
 5640:                     /*
 5641: 		    i = 0;
 5642: 		    while ((a[i] = rou_name[i]) != EOL) {
 5643: 			if (rou_name[i] == '.') break;
 5644: 			i++;
 5645: 		    }
 5646: 		    a[i] = EOL;
 5647:                     */
 5648:                     stcpy (a, rou_name);
 5649: 		    goto exec;
 5650: 
 5651: 		    
 5652:                 /* $ZI, INTERRUPT ENABLE/DISABLE */
 5653:                 case 'I':
 5654: 		    a[0] = '0' | breakon;
 5655: 		    a[1] = EOL;
 5656: 		    goto exec;
 5657: 
 5658: 		    
 5659:                 /* $ZDATE */                
 5660:                 case 'D':
 5661:                     {
 5662: 			time_t ilong;
 5663:                         struct tm *zdate_time;
 5664:                         char zdf_key[50];
 5665:                         char fmt_string[128];
 5666: 
 5667:                         snprintf (zdf_key, 49, "^$JOB\202%d\202ZDATE_FORMAT\201", pid);
 5668:                         ssvn (get_sym, zdf_key, fmt_string);
 5669:                         stcnv_c2m (fmt_string);
 5670:                         
 5671: 			ilong = time (0L);			
 5672: 
 5673:                         zdate_time = localtime (&ilong);
 5674: 
 5675:                         strftime (a, 255, fmt_string, zdate_time);
 5676:                         stcnv_c2m (a);                        
 5677: 		    }
 5678: 		    
 5679: 		    goto exec;
 5680: 
 5681: 		    
 5682:                 /* $ZTIME */
 5683:                 case 'T':
 5684:                     {
 5685: 			time_t ilong;
 5686:                         struct tm *zdate_time;
 5687:                         
 5688: 			ilong = time (0L);			
 5689: 
 5690:                         zdate_time = localtime (&ilong);
 5691: 
 5692:                         strftime (a, 255, "%X", zdate_time);
 5693:                         stcnv_c2m (a);                        
 5694: 		    }
 5695: 		    
 5696: 		    goto exec;
 5697: 
 5698: 		    
 5699:                 /* $ZJOB - value of JOB number (of father process) */
 5700:                 case 'J':
 5701: 		    if (father) {
 5702: 			lintstr (a, father);
 5703: 		    }
 5704: 		    else {
 5705: 			stcpy (a, "\201");
 5706: 		    }
 5707: 
 5708: 		    goto exec;
 5709: 
 5710: 		    
 5711:                 /* $ZORDER - value of physically next global reference @$ZO(@$ZR) */
 5712:                 case 'O':
 5713: 		    global  (getnext, tmp, a);
 5714: 
 5715: 		    if (merr () > 0) return;
 5716: 
 5717: 		    goto exec;
 5718: 
 5719: 		    
 5720:                 /* $ZLOCAL - last local reference */
 5721:                 case 'L':
 5722: 		    zname (a, zloc);
 5723: 		    if (merr () > OK) return;
 5724: 
 5725: 		    goto exec;
 5726: 
 5727: 		    
 5728:                 /* $(Z)REFERENCE - last global reference */
 5729:                 case 'r':
 5730:                 case 'R':
 5731: 		    zname (a, zref);
 5732: 		    if (merr () > OK) return;
 5733: 
 5734: 		    goto exec;
 5735: 
 5736: 		    
 5737:                 case 'C' - 64:
 5738: 		    stcpy (a, zmc);
 5739: 		    goto exec;      /* loadable match 'controls' */
 5740: 
 5741: 
 5742: 		case 'N' - 64:
 5743: 		    stcpy (a, zmn);
 5744: 		    goto exec;      /* loadable match 'numerics' */
 5745: 
 5746: 
 5747: 		case 'P' - 64:
 5748: 		    stcpy (a, zmp);
 5749: 		    goto exec;      /* loadable match 'punctuation' */
 5750: 
 5751: 
 5752: 		case 'A' - 64:
 5753: 		    stcpy (a, zmu);
 5754: 		    stcat (a, zml);
 5755: 		    goto exec;      /* loadable match 'alphabetic' */
 5756: 
 5757: 		    
 5758:                 case 'L' - 64:
 5759: 		    stcpy (a, zml);
 5760: 		    goto exec;      /* loadable match 'lowercase' */
 5761: 
 5762: 		    
 5763:                 case 'U' - 64:
 5764: 		    stcpy (a, zmu);
 5765: 		    goto exec;      /* loadable match 'uppercase' */
 5766: 
 5767: 		    
 5768:                 case 'E' - 64:
 5769: 		    for (i = NUL; i <= DEL; i++) a[i] = i;
 5770: 		    a[i] = EOL;
 5771: 		    goto exec;      /* 'loadable' match 'everything' */
 5772: 
 5773: 
 5774: 		case ' ':           /* user defined special variable */
 5775: 
 5776: 		    udfsvn (get_sym, &tmp[2], a);
 5777: 
 5778: 		    if (ierr <= OK) goto exec;
 5779: 
 5780: 		    merr_raise (OK);
 5781: 
 5782:                     /* if not found in special variable table, process as extrinsic svn */
 5783: 		    /* $$^%Z... all uppercase */
 5784: 
 5785: 		    f = 2;
 5786: 
 5787: 		    while ((ch = tmp[f]) != EOL) {
 5788: 
 5789: 			if (ch >= 'a' && ch <= 'z') ch -= 32;
 5790: 
 5791: 			tmp[f++] = ch;
 5792: 			
 5793: 		    }
 5794: 		    
 5795: 		    stcat (tmp, ++codptr);
 5796: 
 5797: 		    code[0] = '$';
 5798: 		    code[1] = '^';
 5799: 		    code[2] = '%';
 5800: 		    code[3] = 'Z';
 5801: 
 5802: 		    stcpy (&code[4], &tmp[2]);
 5803: 
 5804: 		    codptr = code;
 5805: 		    f = '$';
 5806: 		    zexflag = TRUE;
 5807: 		    arg--;
 5808: 
 5809: 		    goto extra_fun;
 5810: 
 5811:                 default:
 5812: 		    merr_raise (ILLFUN);
 5813: 		    return;
 5814:                 }
 5815:         /* end of specialvariable evaluation */
 5816:         /******************************************************************************/
 5817: 	}
 5818: 	if (++spx >= PARDEPTH) {
 5819: 	    merr_raise (STKOV);
 5820: 	    return;
 5821: 	}
 5822: 	op_stck[spx] = f;
 5823: 	op_stck[++spx] = '$';
 5824: 
 5825: 	
 5826: text:
 5827: 	if (*(codptr + 1) != '@') {
 5828: 	    f = op_stck[spx - 1];
 5829: 	    /* f= (spx>0 ? op_stck[spx-1] : 0);
 5830: 	     * if (f) */
 5831: 
 5832: 	    switch (f) {
 5833: 		case 't':           /* $TEXT is special */
 5834: 
 5835: 		    if ((argstck[++arg] = a) >= s) {
 5836: 			char   *bak;
 5837: 
 5838: 			bak = partition;
 5839: 			if (getpmore () == 0) {
 5840: 			    merr_raise (STKOV);
 5841: 			    return;
 5842: 			}
 5843: 			
 5844: 			a = a - bak + partition;
 5845: 			b = b - bak + partition;
 5846: 			
 5847: 		    }
 5848: 		    
 5849: 		    i = 0;
 5850: 		    
 5851: 		    while ((ch = *++codptr) != EOL) {
 5852: 
 5853: 			if (ch == ')') break;
 5854: 
 5855: 			if (ch == '+') {
 5856: 
 5857: 			    a[i] = EOL;
 5858: 
 5859: 			    if (++spx > PARDEPTH) {
 5860: 				merr_raise (STKOV);
 5861: 				return;
 5862: 			    }
 5863: 			    
 5864: 			    op_stck[spx] = OPERAND;
 5865: 			    goto comma;
 5866: 
 5867: 			}
 5868: 
 5869: 			if (ch == '^') {
 5870: 			    
 5871: 			    a[i] = EOL;
 5872: 			    
 5873: 			    if (++spx > PARDEPTH) {
 5874: 				merr_raise (STKOV);
 5875: 				return;
 5876: 			    }
 5877: 			    
 5878: 			    op_stck[spx] = OPERAND;
 5879: 			    a += i + 1;
 5880: 			    
 5881: 			    if (i == 0) {
 5882: 				a[0] = '1';
 5883: 				a[1] = EOL;
 5884: 			    }			    
 5885: 			    else {
 5886: 				/* just routine name: */
 5887: 				/* return first line  */
 5888: 
 5889: 				a[0] = EOL;
 5890: 
 5891: 			    }
 5892: 
 5893: 			    if ((argstck[++arg] = a) >= s) {
 5894: 				char   *bak;
 5895: 				
 5896: 				bak = partition;
 5897: 
 5898: 				if (getpmore () == 0) {
 5899: 				    merr_raise (STKOV);
 5900: 				    return;
 5901: 				}
 5902: 				
 5903: 				a = a - bak + partition;
 5904: 				b = b - bak + partition;
 5905: 				
 5906: 			    }
 5907: 			    
 5908: 			    if ((spx + 2) > PARDEPTH) {
 5909: 				merr_raise (STKOV);
 5910: 				return;
 5911: 			    }
 5912: 			    
 5913: 			    op_stck[++spx] = '$';
 5914: 			    op_stck[++spx] = OPERAND;
 5915: 			    
 5916: 			    goto uparrow;
 5917: 			}
 5918: 			
 5919: 			if ((ch < '0' && ch != '%')     /* illegal character in $TEXT */
 5920: 			    ||ch > 'z' ||
 5921: 			    (ch < 'A' && ch > '9') ||
 5922: 			    (ch < 'a' && ch > 'Z')) {
 5923: 
 5924: 			    merr_raise (INVREF);
 5925: 			    return;
 5926: 			    
 5927: 			}
 5928: 			
 5929: 			a[i++] = ch;
 5930: 
 5931: 		    }
 5932: 		    
 5933: 		    a[i] = EOL;
 5934: 		    codptr--;
 5935: 		    
 5936: 		    goto exec;
 5937: 
 5938: 		case 'd':           /* $data() */
 5939: 		case 'o':           /* $order() */
 5940: 		case 'g':           /* $get() */
 5941: 		case 'n':           /* $next() */
 5942: 		case 'q':           /* $query() */
 5943: 		case 'O':           /* $zorder() */
 5944: 		case 'N':           /* $zname() */
 5945: 		case ZNEXT:     /* $znext() */
 5946: 		case ZPREVIOUS:     /* $zprevious() */
 5947: 		    {
 5948: 
 5949: 			if ((ch = *++codptr) >= 'A' && ch <= 'Z')
 5950: 			    goto scan_name;
 5951: 
 5952: 			if (ch >= 'a' && ch <= 'z')
 5953: 			    goto scan_name;
 5954: 
 5955: 			if (ch == '%' || ch == '^')
 5956: 			    goto scan_name;
 5957: 			
 5958: 			merr_raise (INVEXPR);
 5959: 			
 5960: 			return;
 5961: 		    }
 5962: 	    }
 5963: 	}
 5964: 	
 5965: 	codptr++;
 5966: 	goto nextchr;
 5967: 
 5968: 	
 5969: 	case ':':
 5970: 	    /* colon: $select or delimiter */
 5971: 	    if (spx < 2 || op_stck[spx - 2] != 's') {
 5972: 		
 5973: 		if (op_stck[1] == OPERAND && spx == 1)
 5974: 		    return;
 5975: 
 5976: 		merr_raise (INVEXPR);
 5977: 
 5978: 		return;
 5979: 
 5980: 	    }
 5981: 	    
 5982: 	    arg--;
 5983: 	    spx--;
 5984: 	    
 5985: 	    if (tvexpr (a) == FALSE) {  /* skip next expr */
 5986: 		
 5987: 		i = 0;          /* quote */
 5988: 		j = 0;          /* bracket */
 5989: 		
 5990: 		for (;;) {
 5991: 		    
 5992: 		    ch = *++codptr;
 5993: 		    
 5994: 		    if (ch == '"') {
 5995: 			toggle (i);
 5996: 			continue;
 5997: 		    }
 5998: 		    
 5999: 		    if (i) {
 6000: 			
 6001: 			if (ch != EOL)
 6002: 			    continue;
 6003: 
 6004: 			merr_raise (QUOTER);
 6005: 			return;
 6006: 			
 6007: 		    }
 6008: 		    
 6009: 		    if (ch == ',' && !j) {
 6010: 			codptr++;
 6011: 			goto nextchr;
 6012: 		    }
 6013: 		    
 6014: 		    if (ch == '(') {
 6015: 			j++;
 6016: 			continue;
 6017: 		    }
 6018: 		    
 6019: 		    if (ch == ')') {
 6020: 			
 6021: 			if (j--)
 6022: 			    continue;
 6023: 			
 6024: 			merr_raise (SELER);
 6025: 			return;
 6026: 			
 6027: 		    }
 6028: 		    
 6029: 		    if (ch == EOL) {
 6030: 			merr_raise (SELER);
 6031: 			return;
 6032: 		    }
 6033: 		    
 6034: 		}
 6035: 	    }
 6036: 	    
 6037: 	    codptr++;
 6038: 	    goto nextchr;
 6039: 
 6040:     }
 6041: 
 6042: m_operator:
 6043: 
 6044:     if (extyp == ARGIND && spx == 1 /* && op_stck[2]!='(' */ )
 6045: 	return;
 6046: 
 6047:     f = op_stck[spx];
 6048: 
 6049:     if (++spx > PARDEPTH) {
 6050: 	merr_raise (STKOV);
 6051: 	return;
 6052:     }
 6053: 
 6054:     
 6055: op10:              /* entry for shortcut if first operator */
 6056: 
 6057:     /* check for NOT_OPERATOR */
 6058:     if (ch == NOT) {
 6059: 	if (((ch = *++codptr) == '=' || ch == '<' || ch == '>' || ch == '?' || ch == '&' || ch == '!' || ch == '[' || ch == ']')) {
 6060: 	    if (ch == ']' && *(codptr + 1) == ch) {
 6061: 		codptr++;
 6062: 		ch = SORTSAFTER;
 6063: 		if (*(codptr+1)=='=') { 
 6064: 		    codptr++; 
 6065: 		    ch=EQSORTS; 
 6066: 		}
 6067: 	    }
 6068: 	    if (ch == ']' && *(codptr + 1) == '=') {
 6069: 		codptr++;
 6070: 		ch = EQFOLLOWS;
 6071: 	    }
 6072: 	    if (ch == '!' && *(codptr + 1) == ch) {
 6073: 		codptr++;
 6074: 		ch = XOR;
 6075: 	    }
 6076: 	    
 6077: 	    op_stck[spx] = SETBIT (ch);
 6078: 	    if (ch == '?')
 6079: 		goto scan_pattern;
 6080: 	    /*                     a+=stlen(a)+1; */
 6081: 	    /* djw: does the while loop do the same as the commented out line above? */
 6082: 	    /*      we should decide yes or no and get rid of the other code... */
 6083: 
 6084: 	    while (*a++ != EOL);
 6085: 	    
 6086: 	    codptr++;
 6087: 	    goto nextchr;
 6088: 	    
 6089: 	}
 6090: 	else {
 6091: 	    op_stck[spx] = NOT;
 6092: 	    goto nextchr;
 6093: 	}
 6094:     }
 6095: 
 6096:     if (ch == '*' && *(codptr + 1) == ch) {
 6097: 	codptr++;
 6098: 	ch = POWER;
 6099:     }
 6100:     
 6101:     if (ch == ']' && *(codptr + 1) == ch) {
 6102: 	codptr++;
 6103: 	ch = SORTSAFTER;
 6104:     }
 6105:     
 6106:     if (ch == '<' && *(codptr + 1) == '=') {
 6107: 	codptr++;
 6108: 	ch = SETBIT ('>');
 6109:     }
 6110:     
 6111:     if (ch == '>' && *(codptr + 1) == '=') {
 6112: 	codptr++;
 6113: 	ch = SETBIT ('<');
 6114:     }
 6115:     
 6116:     if (ch == ']' && *(codptr + 1) == '=') {
 6117: 	codptr++;
 6118: 	ch = EQFOLLOWS;
 6119:     }
 6120:     
 6121:     if (ch == SORTSAFTER && *(codptr + 1) == '=') {
 6122: 	codptr++;
 6123: 	ch = EQSORTS;
 6124:     }
 6125:     
 6126:     if (ch == '$')
 6127: 	ch = MAXOP;
 6128:     
 6129:     if (ch == '^') {
 6130: 	codptr--;
 6131: 	return;
 6132:     }
 6133: 
 6134:     if ((op_stck[spx] = ch) != PATTERN) {
 6135: 
 6136: 	if (f == OPERAND) while (*a++ != EOL);       /* binary operator */
 6137: 
 6138: 	codptr++;
 6139: 	goto nextchr;
 6140:     }
 6141:     
 6142: scan_pattern:
 6143:     if ((ch = *++codptr) == INDIRECT) { /*  a+=stlen(a)+1;  */
 6144: 	while (*a++ != EOL) ;
 6145: 	goto m_operator;
 6146:     }
 6147:     
 6148:     if ((ch > '9' || ch < '0') && (ch != '.')) {
 6149: 	merr_raise (INVEXPR);
 6150: 	return;
 6151:     }
 6152:     
 6153:     tmp[0] = ch;
 6154:     i = 1;
 6155:     f = '1';                /* 'previous' character */
 6156:     j = 0;              /* point flag */
 6157:     group = 0;              /* grouped pattern match */
 6158: 
 6159:     while ((ch = *++codptr) != EOL) {
 6160: 
 6161: 	if ((ch >= '0') && (ch <= '9')) {
 6162: 
 6163: 	    tmp[i++] = ch;
 6164: 	    f = '1';
 6165: 
 6166: 	    continue;
 6167: 	    
 6168: 	}
 6169: 	
 6170:     if (ch == '.') {
 6171: 
 6172: 	if (j) {
 6173: 	    merr_raise (INVEXPR);
 6174: 	    return;
 6175: 	}
 6176: 	
 6177: 	j++;
 6178: 	tmp[i++] = ch;
 6179: 	f = '1';
 6180: 	
 6181: 	continue;
 6182:     }
 6183:     
 6184:     j = 0;
 6185:     if (ch == NOT) {        /* negation of pattern class ? */
 6186: 
 6187: 	ch = *(codptr + 1);
 6188: 
 6189: 	if ((ch == '"') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
 6190: 	    tmp[i++] = NOT;
 6191: 	}
 6192: 	else {
 6193: 	    ch = NOT;
 6194: 	}
 6195: 
 6196:     }
 6197: 
 6198:     if (ch == '"') {
 6199: 
 6200: 	if (f != '1' && f != 'A') {
 6201: 	    merr_raise (INVEXPR);
 6202: 	    return;
 6203: 	}
 6204: 	
 6205: 	for (;;) {
 6206: 	    
 6207: 	    tmp[i++] = ch;
 6208: 
 6209: 	    if ((ch = *++codptr) == EOL) {
 6210: 		merr_raise (QUOTER);
 6211: 		return;
 6212: 	    }
 6213: 	    
 6214: 	    if (ch == '"') {
 6215: 		
 6216: 		if ((f = *(codptr + 1)) != '"') {
 6217: 		    ch = DELIM;
 6218: 		    break;
 6219: 		}
 6220: 		
 6221: 		codptr++;
 6222: 	    }
 6223: 	}
 6224: 	
 6225: 	tmp[i++] = ch;
 6226: 	f = '"';
 6227: 	
 6228: 	continue;
 6229: 	
 6230:     }
 6231:     
 6232:     if (ch == '(') {
 6233: 
 6234: 	if (f != '1') {
 6235: 	    merr_raise (INVEXPR);
 6236: 	    return;
 6237: 	}
 6238: 	
 6239: 	group++;
 6240: 	f = '(';
 6241: 	tmp[i++] = ch;
 6242: 	
 6243: 	continue;
 6244: 	
 6245:     }
 6246:     
 6247:     if (group && (ch == ',' || ch == ')')) {
 6248: 
 6249: 	if ((f == '1') || (f == '(')) {
 6250: 	    merr_raise (INVEXPR);
 6251: 	    return;
 6252: 	}
 6253: 	
 6254: 	if (ch == ',') {
 6255: 
 6256: 	    f = '(';
 6257: 	    tmp[i++] = ch;
 6258: 	    
 6259: 	    continue;
 6260: 
 6261: 	}
 6262: 	
 6263:     if (ch == ')') {
 6264: 	group--;
 6265: 	tmp[i++] = ch;
 6266: 
 6267: 	continue;
 6268:     }
 6269:     
 6270:     } /* ??? formatting ??? */
 6271:     
 6272:     if (ch >= 'A' && ch <= 'Z') ch += 32;           /* lower case conversion */
 6273: 
 6274:     if (ch == 'z') {        /* loadable match, store as uppercase chars */
 6275: 
 6276: 	if (standard) {
 6277: 	    merr_raise (NOSTAND);
 6278: 	    return;
 6279: 	}
 6280: 	
 6281: 	ch = *++codptr;
 6282: 
 6283: 	if (ch == '"') {
 6284: 	    
 6285: 	    if (f != '1') {
 6286: 		merr_raise (INVEXPR);
 6287: 		return;
 6288: 	    }
 6289: 	    
 6290: 	    codptr--;
 6291: 	    tmp[i++] = 'z';
 6292: 	    
 6293: 	    continue;
 6294: 	    
 6295: 	}
 6296: 	
 6297: 	if (ch == '(') {
 6298: 
 6299: 	    if (f != '1') {
 6300: 		merr_raise (INVEXPR);
 6301: 		return;
 6302: 	    }
 6303: 	    
 6304: 	    codptr--;
 6305: 	    continue;
 6306: 	}
 6307: 	
 6308: 	if (ch >= 'A' && ch <= 'Z') ch += 32;       /* lower case conversion */
 6309: 
 6310: 	if (ch != 'e')
 6311: 	    j = 1;          /* process 'ze' as 'e' */
 6312:     }
 6313: 
 6314:     if (ch != 'c' && ch != 'n' &&  ch != 'p' && ch != 'a' && ch != 'l' && ch != 'u' && ch != 'e') break;
 6315: 
 6316:     if ((f != '1') && (f != 'A')) {
 6317: 	merr_raise (INVEXPR);
 6318: 	return;
 6319:     }
 6320:     
 6321:     if (j) {
 6322: 	ch -= 32;
 6323: 	j = 0;
 6324:     }
 6325:     
 6326:     tmp[i++] = ch;
 6327:     f = 'A';
 6328: 
 6329:     }
 6330: 
 6331:     if ((f == '1') || group) {
 6332: 	merr_raise (INVEXPR);
 6333: 	return;
 6334:     }
 6335:     
 6336:     tmp[i] = EOL;
 6337: 
 6338:     if ((*a = pattern (a, tmp)) > '1') {
 6339: 	merr_raise (INVEXPR);
 6340: 	return;
 6341:     }
 6342:     
 6343:     if (UNSIGN (op_stck[spx--]) & 0200) toggle (*a);
 6344:     
 6345:     *(a + 1) = EOL;
 6346: 
 6347:     goto next10;
 6348: 
 6349:     /* process values on stack */
 6350: 
 6351:     
 6352: exec:
 6353: 
 6354:     if (spx == 0) {
 6355: 
 6356: 	if ((ch = *++codptr) == EOL || ch == SP || ch == ',' || ch == ':' || (ch == '^' && (extyp == LABEL || extyp == OFFSET))) return;
 6357: 
 6358: 	op_stck[++spx] = OPERAND;
 6359: 
 6360: 	goto next10;
 6361: 
 6362:     }
 6363: 
 6364:     f = op_stck[spx];
 6365: 
 6366:     if (f == ARRAY || f == '(') {
 6367: 
 6368: 	if (++spx > PARDEPTH) {
 6369: 	    merr_raise (STKOV);
 6370: 	    return;
 6371: 	}
 6372: 	
 6373: 	op_stck[spx] = OPERAND;
 6374: 	codptr++;
 6375: 	
 6376: 	goto nextchr;
 6377: 	
 6378:     }
 6379:     
 6380:     /* process operators */
 6381: 
 6382: nxt_expr:
 6383: 
 6384:     if (f == '$') {         /* push 'OPERAND' on stack */
 6385: 	
 6386: 	op_stck[++spx] = OPERAND;
 6387: 	codptr++;
 6388: 
 6389: 	goto nextchr;
 6390: 	
 6391:     }
 6392:     
 6393:     if (f == OPERAND) {
 6394: 	merr_raise (MISSOP);
 6395: 	return;
 6396:     }
 6397:     
 6398:     if (op_stck[--spx] == OPERAND) {    /* binary operators */
 6399: 
 6400: 	b = a;
 6401: 	a = argstck[--arg];
 6402: 
 6403: 	switch (f & 0177) {     /* binary operators, NOT OMITTED */
 6404: 
 6405: 	    case PLUS:
 6406: 
 6407: 		stcpy (tmp, b);
 6408: 
 6409: plus01:
 6410: 
 6411: 		atyp = numlit (a);
 6412: 		btyp = numlit (tmp);
 6413: 		
 6414: #ifdef EUR2DEM
 6415: 		
 6416: 		if (atyp != btyp) {
 6417: 
 6418: 		    char    tmp2[256];
 6419: 
 6420: 		    if ((atyp == 0) && (a[0] == '0')) atyp = btyp;    /* zero is any currency */
 6421: 		    if ((btyp == 0) && (tmp[0] == '0')) btyp = atyp;    /* zero is any currency */
 6422: 
 6423: 		    if (atyp && btyp) {
 6424: 			
 6425: 			if (atyp > 1) {
 6426: 			    stcpy (tmp2, EUR2WHR[atyp]);
 6427: 			    mul (tmp, tmp2);
 6428: 			}
 6429: 			
 6430: 			if (btyp > 1) {
 6431: 			    zprecise += 4;
 6432: 			    stcpy (tmp2, EUR2WHR[btyp]);
 6433: 			    mdiv (tmp, tmp2, '/');
 6434: 			    zprecise -= 4;
 6435: 			}
 6436: 			
 6437: 		    }
 6438: 		    else if (atyp != btyp && typemmflag) {
 6439: 			merr_raise (TYPEMISMATCH);
 6440: 			return;
 6441: 		    }
 6442: 		    
 6443: 		}
 6444: 		
 6445: #endif /* EUR2DEM */
 6446: 		
 6447: 		add (a, tmp);
 6448: plus02:
 6449: 
 6450: #ifdef EUR2DEM
 6451: 
 6452: 		if (atyp == 0) goto next05;
 6453: 		if (atyp != btyp) cond_round (a, zprecise + 2);
 6454: 		
 6455: 		stcat (a, WHR[atyp]);
 6456: 
 6457: #endif /* EUR2EUR */
 6458: 
 6459: 		goto next05;
 6460: 
 6461: 		
 6462: 	    case MINUS:
 6463: 
 6464: 		tmp[0] = '-';
 6465: 		stcpy (&tmp[1], b);
 6466: 		goto plus01;
 6467: 
 6468: 		
 6469: 	    case MULTIPLY:
 6470: 
 6471: 		stcpy (tmp, b);
 6472: 		atyp = numlit (a);
 6473: 		btyp = numlit (tmp);
 6474: #ifdef EUR2DEM
 6475: 		if (btyp && (atyp == 0)) {
 6476: 		    atyp = btyp;
 6477: 		    btyp = 0;
 6478: 		}
 6479: 		
 6480: 		if (atyp && btyp) {
 6481: 
 6482: 		    if (typemmflag) {
 6483: 			merr_raise (TYPEMISMATCH);
 6484: 			return;
 6485: 		    }
 6486: 		    
 6487: 		    atyp = btyp = 0;
 6488: 		    
 6489: 		}
 6490: 		
 6491: #endif /* EUR2DEM */
 6492: 
 6493: 		mul (a, tmp);
 6494: 
 6495: #ifdef EUR2DEM
 6496: 		
 6497: 		if (atyp == 0) goto next05;
 6498: 
 6499: 		cond_round (a, zprecise + 2);
 6500: 		stcat (a, WHR[atyp]);
 6501: 		
 6502: #endif /* EUR2DEM */
 6503: 
 6504: 		goto next05;
 6505: 
 6506: 		
 6507: 	    case DIVIDE:
 6508: 	    case INTDIVIDE:
 6509: 	    case MODULO:
 6510: 
 6511: 		stcpy (tmp, b);
 6512: 		atyp = numlit (a);
 6513: 		btyp = numlit (tmp);
 6514: 
 6515: #ifdef EUR2DEM
 6516: 		if (atyp != btyp) {
 6517:                     char    tmp2[256];
 6518: 
 6519:                     if (atyp && btyp) {
 6520:                         
 6521:                         if (f == MODULO) {
 6522: 
 6523:                             if (atyp > 1) {
 6524:                                 stcpy (tmp2, EUR2WHR[atyp]);
 6525:                                 mul (tmp, tmp2);
 6526:                             }
 6527: 
 6528:                             if (btyp > 1) {
 6529:                                 stcpy (tmp2, EUR2WHR[btyp]);
 6530:                                 mdiv (tmp, tmp2, '/');
 6531:                             }
 6532:                             
 6533:                         }
 6534:                         else {
 6535:                             
 6536:                             if (atyp > 1) {
 6537:                                 stcpy (tmp2, EUR2WHR[atyp]);
 6538:                                 mul (tmp, tmp2);
 6539:                             }
 6540: 
 6541:                             if (btyp > 1) {
 6542:                                 stcpy (tmp2, EUR2WHR[btyp]);
 6543:                                 mul (a, tmp2);
 6544:                             }
 6545: 
 6546:                             atyp = btyp = 0;
 6547: 
 6548:                         }
 6549:                         
 6550:                     } else if (btyp && typemmflag && (*a != '0' || f == MODULO)) {
 6551:                         merr_raise (TYPEMISMATCH);                        
 6552:                         return;
 6553:                     }
 6554:                 }
 6555:                 else if (f != MODULO) {
 6556:                     atyp = 0;
 6557:                 }
 6558:                 
 6559: #endif /* EUR2DEM */
 6560:                 
 6561:                 if (tmp[0] == '0') {
 6562:                     merr_raise (M9);
 6563:                     return;
 6564:                 }
 6565:                 
 6566:                 if (atyp != btyp) zprecise += 4;
 6567:                 
 6568:                 mdiv (a, tmp, f);
 6569: 
 6570:                 if (atyp != btyp) zprecise -= 4;
 6571: 
 6572:                 goto plus02;
 6573: 
 6574:                 
 6575:             case CONCATENATE:
 6576: 
 6577:                 if (stcat (a, b)) goto next05;
 6578:                 
 6579:                 merr_raise (M75);
 6580:                 return;
 6581: 
 6582:                 
 6583:             case EQUAL:
 6584: 
 6585:                 if (stcmp (a, b)) {
 6586:                     *a = '0';
 6587:                 }
 6588:                 else {
 6589:                     *a = '1';
 6590:                 }
 6591:                 
 6592:                 /* common entry point to reverse the logical value */
 6593:                 /* of current expression               */
 6594: 
 6595: 
 6596: notop:
 6597:                 if (f & 0200) toggle (*a);        /* NOT_OPERAND */
 6598: 
 6599:                 a[1] = EOL;
 6600:                 
 6601:                 goto next05;
 6602: 
 6603:                 
 6604:             case GREATER:
 6605: 
 6606:                 stcpy (tmp, b);
 6607:                 atyp = numlit (a);
 6608:                 btyp = numlit (tmp);
 6609:                 
 6610: #ifdef EUR2DEM
 6611:                 if (atyp != btyp) {
 6612:                     char tmp2[256];
 6613: 
 6614:                     if ((atyp == 0) && (a[0] == '0')) atyp = btyp;    /* zero is any currency */
 6615:                     if ((btyp == 0) && (tmp[0] == '0')) btyp = atyp;    /* zero is any currency */
 6616: 
 6617:                     if (atyp && btyp) {
 6618:                         
 6619:                         if (atyp > 1) {
 6620:                             stcpy (tmp2, EUR2WHR[atyp]);
 6621:                             mul (tmp, tmp2);
 6622:                         }
 6623:                         
 6624:                         if (btyp > 1) {
 6625:                             stcpy (tmp2, EUR2WHR[btyp]);
 6626:                             mul (a, tmp2);
 6627:                         }
 6628:                         
 6629:                         cond_round (a, zprecise + 2);
 6630:                         cond_round (tmp, zprecise + 2);
 6631:                         
 6632:                     }
 6633:                     else if (atyp != btyp && typemmflag) {
 6634:                         merr_raise (TYPEMISMATCH);
 6635:                         return;
 6636:                     }
 6637:                 }
 6638: #endif /* EUR2DEM */
 6639:                 
 6640:                 if (comp (tmp, a)) {
 6641:                     *a = '1';
 6642:                 }
 6643:                 else {
 6644:                     *a = '0';
 6645:                 }
 6646:                 
 6647:                 goto notop;
 6648: 
 6649:                 
 6650:             case LESS:
 6651: 
 6652:                 stcpy (tmp, b);
 6653:                 atyp = numlit (a);
 6654:                 btyp = numlit (tmp);
 6655: 
 6656: #ifdef EUR2DEM
 6657:                 if (atyp != btyp) {
 6658:                     char tmp2[256];
 6659: 
 6660:                     if ((atyp == 0) && (a[0] == '0')) atyp = btyp;    /* zero is any currency */
 6661:                     if ((btyp == 0) && (tmp[0] == '0')) btyp = atyp;    /* zero is any currency */
 6662: 
 6663:                     if (atyp && btyp) {
 6664: 
 6665:                         if (atyp > 1) {
 6666:                             stcpy (tmp2, EUR2WHR[atyp]);
 6667:                             mul (tmp, tmp2);
 6668:                         }
 6669: 
 6670:                         if (btyp > 1) {
 6671:                             stcpy (tmp2, EUR2WHR[btyp]);
 6672:                             mul (a, tmp2);
 6673:                         }
 6674: 
 6675:                         cond_round (a, zprecise + 2);
 6676:                         cond_round (tmp, zprecise + 2);
 6677:                         
 6678:                     }
 6679:                     else if (atyp != btyp && typemmflag) {
 6680:                         merr_raise (TYPEMISMATCH);
 6681:                         return;
 6682:                     }
 6683:                     
 6684:                 }
 6685:                 
 6686: #endif /* EUR2DEM */
 6687:                 if (comp (a, tmp)) {
 6688:                     *a = '1';
 6689:                 }
 6690:                 else {
 6691:                     *a = '0';
 6692:                 }
 6693:                 
 6694:                 goto notop;
 6695: 
 6696:                 
 6697:             case AND:
 6698: 
 6699:                 if (tvexpr (a)) {
 6700:                     tvexpr (b);
 6701:                     *a = *b;
 6702:                 }
 6703:                 
 6704:                 goto notop;
 6705: 
 6706:                 
 6707:             case OR:
 6708: 
 6709:                 ch = tvexpr (b);        /* beware case of a="" */
 6710:                 
 6711:                 if (tvexpr (a) == FALSE && ch) *a = '1';
 6712:                 
 6713:                 goto notop;
 6714: 
 6715:                 
 6716:             case XOR:
 6717:                 
 6718:                 ch = tvexpr (b);            /* beware case of a="" */
 6719:                 *a = (tvexpr(a) == ch) ? '0' : '1';
 6720: 
 6721:                 goto notop;
 6722: 
 6723:                 
 6724:             case CONTAINS:
 6725: 
 6726:                 if (*b == EOL || find (a, b)) {
 6727:                     *a = '1';
 6728:                 }
 6729:                 else {
 6730:                     *a = '0';
 6731:                 }
 6732:                 
 6733:                 goto notop;     
 6734: 
 6735:                 
 6736:             case EQFOLLOWS:
 6737:                 
 6738:                 if (stcmp (a, b) == 0) {
 6739:                     a[0] = '1';
 6740:                     goto notop;
 6741:                 }
 6742: 
 6743:                 
 6744:             case FOLLOWS:
 6745: 
 6746:                 if (*b == EOL) {
 6747: 
 6748:                     if (*a == EOL) {
 6749:                         *a = '0';
 6750:                     }
 6751:                     else {
 6752:                         *a = '1';
 6753:                     }
 6754:                     
 6755:                 }               
 6756:                 else if (stcmp (a, b) <= 0) {     /* frequent special case */
 6757:                     *a = '0';
 6758:                 }
 6759:                 else {
 6760:                     *a = '1';
 6761:                 }
 6762:                 
 6763:                 goto notop;
 6764: 
 6765:                 
 6766:             case POWER:
 6767: 
 6768:                 stcpy (tmp, b);
 6769:                 numlit (a);
 6770:                 numlit (tmp);
 6771:                 power (a, tmp);
 6772:                 goto next05;
 6773: 
 6774:                 
 6775:             case EQSORTS:
 6776:                 
 6777:                 if (stcmp (a, b) == 0) {
 6778:                     a[0] = '1';
 6779:                     goto notop;
 6780:                 }
 6781: 
 6782:                 
 6783:             case SORTSAFTER:
 6784: 
 6785:                 if (collate (b, a)) {
 6786:                     *a = '1';
 6787:                 }
 6788:                 else {
 6789:                     *a = '0';
 6790:                 }
 6791:                 
 6792:                 goto notop;
 6793: 
 6794:                 
 6795:             case MAXOP:
 6796: 
 6797: #ifdef NOSCRAMBL
 6798:                 if (standard) {
 6799:                     merr_raise (NOSTAND);
 6800:                     return;
 6801:                 }                
 6802: #endif /* NOSCRAMBL */
 6803:                 
 6804:                 stcpy (tmp, b);
 6805:                 numlit (tmp);
 6806:                 numlit (a);
 6807:                 
 6808:                 if (comp (a, tmp)) stcpy (a, tmp);
 6809:                 
 6810:                 goto next05;
 6811: 
 6812:                 
 6813:             case MINOP:
 6814: 
 6815: #ifdef NOSCRAMBL
 6816:                 if (standard) {
 6817:                     merr_raise (NOSTAND);
 6818:                     return;
 6819:                 }                
 6820: #endif /* NOSCRAMBL */
 6821: 
 6822:                 stcpy (tmp, b);
 6823:                 numlit (tmp);
 6824:                 numlit (a);
 6825:                 
 6826:                 if (comp (a, tmp) == 0) stcpy (a, tmp);
 6827:                 
 6828:                 goto next05;
 6829: 
 6830:                 
 6831:             default:
 6832:                 merr_raise (ILLOP);
 6833:                 return;
 6834: 
 6835:         }
 6836:     }                   /* end binary operators */
 6837: 
 6838:     switch (f) {
 6839: 
 6840:         case INDIRECT:
 6841: 
 6842: 
 6843: indirect:
 6844: 
 6845:             if (*++codptr == '@' && *(codptr + 1) == '(') {
 6846: 
 6847:                 if (a[stlen (a) - 1] == ')') {
 6848:                     codptr += 2;
 6849:                     a[stlen (a) - 1] = ',';
 6850:                 }
 6851:                 else {
 6852:                     codptr++;
 6853:                 }
 6854: 
 6855:             }
 6856:             
 6857:             stcpy (a + stlen (a), codptr);
 6858:             stcpy (&code[1], a);
 6859:             codptr = code;
 6860:             *codptr = SP;
 6861:             arg--;
 6862:             
 6863:             if (spx <= 0) {
 6864:                 op_stck[0] = 0;
 6865:                 codptr++;
 6866: 
 6867:                 goto nextchr;
 6868:             }
 6869:             
 6870:             if ((op_stck[spx] & 0177) != PATTERN) goto text;
 6871: 
 6872:             a = argstck[arg];
 6873:             goto scan_pattern;
 6874: 
 6875:             
 6876:         case MINUS:         /* unary minus */
 6877: 
 6878:             b = a + stlen (a) + 1;
 6879: 
 6880:             while (b > a) {
 6881:                 *b = *(b - 1);
 6882:                 b--;
 6883:             }
 6884:             
 6885:             *a = '-';
 6886: 
 6887:             
 6888:         case PLUS:              /* unary plus */
 6889: 
 6890:             atyp = numlit (a);
 6891:             
 6892: #ifdef EUR2DEM
 6893:             if (atyp) {
 6894:                 stcat (a, WHR[atyp]);
 6895:             }
 6896: #endif /* EUR2DEM */
 6897:             goto nxt_operator;
 6898: 
 6899:             
 6900:         case NOT:               /* unary not */
 6901: 
 6902:             tvexpr (a);
 6903:             toggle (*a);
 6904:             
 6905:             goto nxt_operator;
 6906: 
 6907:             
 6908:         default:
 6909:             merr_raise (MISSOPD);
 6910:             return;
 6911:             
 6912:     }                   /* end unary operators */
 6913: 
 6914:     
 6915: }                   /* end expr() */
 6916: 
 6917: 
 6918: /******************************************************************************/
 6919: /* $ZSYNTAX */
 6920: /* a simple syntax check.                                    */
 6921: /* $ZSYNTAX expects one argument. If it finds no fault, it   */
 6922: /* returns an empty string. Otherwise it returns a pair of   */
 6923: /* integers separated by a comma. The first number indicates */
 6924: /* the position where the error has been found. The second   */
 6925: /* number returns an error code (same meaning as in $ZE)     */
 6926: /* only the most frequent errors are searched for:           */
 6927: /* - illegal commands                                        */
 6928: /* - not matching brackets                                   */
 6929: /* - not matching quotes                                     */
 6930: /* - missing or surplus arguments                            */
 6931: /* - surplus commata                                         */
 6932: 
 6933: void zsyntax(char *a)
 6934: {
 6935:     register int i;
 6936:     register int j;
 6937:     register int f;
 6938:     register int ch;
 6939:     
 6940:     char    tmp[256];
 6941:     char   *b;
 6942:     short   cmnd;
 6943:     short   forline;            /* flag: FOR encountered */
 6944: 
 6945:     b = a;
 6946:     forline = FALSE;
 6947:     while ((ch = *b) == '.' || ch == SP)
 6948:         b++;                /* level points for blockstr. */
 6949:     while ((ch = *b++) != EOL) {    /* scan command */
 6950:         if (ch == ';' || ch == '!')
 6951:             break;          /* comment or unix_call */
 6952:         if (ch >= 'A' && ch <= 'Z')
 6953:             ch += 32;           /* uppercase to lowercase */
 6954:         f = ch;
 6955:         cmnd = f;
 6956:         if (ch < 'b' || ch > 'z' || /* illegal char in cmmd position */
 6957:             ch == 'm' || ch == 't' || ch == 'y') {
 6958:             j = CMMND;
 6959: 
 6960:             
 6961: zserr:
 6962: 
 6963:             intstr (a, b - a);
 6964:             a[i = stlen (a)] = ',';
 6965: 
 6966:             merr_num_to_code (j, &a[++i]);
 6967:             stcnv_c2m (a);
 6968:             
 6969:             return;
 6970:         }
 6971:         i = 1;
 6972:         while (((tmp[++i] = ch = *b++) != EOL) &&   /* check full command name */
 6973:                ((ch >= 'A' && ch <= 'Z') ||
 6974:                 (ch >= 'a' && ch <= 'z')))
 6975:             if (ch < 'a')
 6976:                 tmp[i] = ch + 32;
 6977:         if (f != 'z') {
 6978:             if (i > 2) {
 6979:                 tmp[0] = SP;
 6980:                 tmp[1] = f;
 6981:                 tmp[i] = SP;
 6982:                 tmp[++i] = EOL;
 6983:                 if (find (
 6984:                         " break close do else for goto hang halt if job kill lock new open quit read set use view write xecute "
 6985:                         ,tmp) == FALSE) {
 6986:                     j = CMMND;
 6987:                     goto zserr;
 6988:                 }
 6989:             }
 6990:         }
 6991:         i = 0;              /* quote */
 6992:         j = 0;              /* bracket */
 6993:         if (ch == ':') {        /*  scan postcond */
 6994:             while ((ch = *b++) != EOL) {
 6995:                 if (ch == '*' && *b == ch)
 6996:                     b++;        /* exponentiation */
 6997:                 if (ch == '!' && *b == ch)
 6998:                     b++;                /* XOR */
 6999:                 if (ch == ']') {
 7000:                     if (*b == ch)
 7001:                         b++;        /* SORTSAFTER */
 7002:                     if (*b == '=')
 7003:                         b++;        /* EQFOLLOWS or EQSORTS */
 7004:                 }
 7005:                 if (ch == '"') {
 7006:                     toggle (i);
 7007:                     continue;
 7008:                 }
 7009:                 if (i)
 7010:                     continue;
 7011:                 if (ch == SP)
 7012:                     break;
 7013:                 if (ch == '$') {
 7014:                     ch = *b++;
 7015:                     if (ch >= 'A' && ch <= 'Z')
 7016:                         ch += 32;
 7017:                     if ((ch < 'a' || ch > 'z' || ch == 'b' ||
 7018:                          ch == 'm' || ch == 'u' || ch == 'w') && ch != '$') {
 7019:                         j = ILLFUN;
 7020:                         goto zserr;
 7021:                     }
 7022:                     if (ch == 's') {    /* $SELECT */
 7023:                         int     xch,
 7024:                             xi,
 7025:                             xj;
 7026:                         char   *xb;
 7027:                         int     sfl;
 7028:                         
 7029:                         xi = 0;     /* quotes */
 7030:                         xj = 0;     /* brackets */
 7031:                         xb = b;     /* do not change old 'b' pointer */
 7032:                         sfl = TRUE; /* first ':' expected */
 7033:                         for (;;)
 7034:                         {
 7035:                             if ((xch = *xb++) == EOL ||
 7036:                                 ((xch == SP || xch == ',') && xj == 0)) {
 7037:                                 if (xj == 0)
 7038:                                     break;  /* $STORAGE */
 7039:                                 j = SELER;
 7040:                                 b = xb;
 7041:                                 goto zserr;
 7042:                             }
 7043:                             if (xch == '"') {
 7044:                                 toggle (xi);
 7045:                                 continue;
 7046:                             }
 7047:                             if (xi)
 7048:                                 continue;
 7049:                             if (xch == ':') {
 7050:                                 if (xj > 1)
 7051:                                     continue;
 7052:                                 if (sfl) {
 7053:                                     sfl = FALSE;
 7054:                                     continue;
 7055:                                 }
 7056:                                 j = SELER;
 7057:                                 b = xb;
 7058:                                 goto zserr;
 7059:                             }
 7060:                             if (xch == ',') {
 7061:                                 if (xj > 1)
 7062:                                     continue;
 7063:                                 if (!sfl) {
 7064:                                     sfl = TRUE;
 7065:                                     continue;
 7066:                                 }
 7067:                                 j = SELER;
 7068:                                 b = xb;
 7069:                                 goto zserr;
 7070:                             }
 7071:                             if (xch == '(') {
 7072:                                 xj++;
 7073:                                 continue;
 7074:                             }
 7075:                             if (xch == ')') {
 7076:                                 if ((xj--) > 1)
 7077:                                     continue;
 7078:                                 if (sfl) {
 7079:                                     j = SELER;
 7080:                                     b = xb;
 7081:                                     goto zserr;
 7082:                                 }
 7083:                                 break;
 7084:                             }
 7085:                         }
 7086:                     }
 7087: /* end select check */
 7088:                     else if (ch == 'd' ||   /* $DATA */
 7089:                              ch == 'g' ||    /* $GET */
 7090:                              ch == 'o' ||    /* $ORDER */
 7091:                              ch == 'n' ||    /* $NEXT */
 7092:                              ch == 'q' ||    /* $QUERY */
 7093:                              ch == 'i') {    /* $INCREMENT */
 7094:                         int     xch,
 7095:                             xi,
 7096:                             xj;
 7097:                         char   *xb;
 7098:                         
 7099:                         xb = b;     /* do not change old 'b' pointer */
 7100: /* skip name */
 7101:                         while (((xch = (*xb)) >= 'A' && xch <= 'Z') ||
 7102:                                (xch >= 'a' && xch <= 'z'))
 7103:                             xb++;
 7104:                         if (xch == '(') {
 7105:                             if ((xch = (*++xb)) == '^' || xch == '%' ||
 7106:                                 (xch >= 'A' && xch <= 'Z') ||
 7107:                                 (xch >= 'a' && xch <= 'z')) {
 7108:                                 xi = xch;
 7109:                                 if (xch == '^' && *(xb + 1) == '%')
 7110:                                     xb++;
 7111:                                 while
 7112:                                     (((xch = (*++xb)) >= 'A' && xch <= 'Z') ||
 7113:                                      (xch >= 'a' && xch <= 'z') ||
 7114:                                      (xch >= '0' && xch <= '9') ||
 7115:                                      (xch == '.') ||
 7116:                                      (xch == '/' && xi <= '^') ||
 7117:                                      (xch == '%' && *(xb - 1) == '/')) ;
 7118:                             } else {
 7119:                                 if (xch == '@')
 7120:                                     continue;
 7121:                                 j = INVEXPR;
 7122:                                 b = xb;
 7123:                                 goto zserr;
 7124:                             }
 7125:                             xi = 0; /* quotes */
 7126:                             xj = 0; /* brackets */
 7127:                             for (;;)
 7128:                             {
 7129:                                 xch = *xb++;
 7130:                                 if (xch == '"' && xj) {
 7131:                                     toggle (xi);
 7132:                                     continue;
 7133:                                 }
 7134:                                 if (xi && (xch != EOL))
 7135:                                     continue;
 7136:                                 if (xch == '(') {
 7137:                                     xj++;
 7138:                                     continue;
 7139:                                 }
 7140:                                 if (xch == ')') {
 7141:                                     if (xj-- > 0)
 7142:                                         continue;
 7143:                                     break;
 7144:                                 }
 7145:                                 if (xj && xch != EOL)
 7146:                                     continue;
 7147:                                 if (xch == ',' &&
 7148:                                     (ch == 'g' || ch == 'q' || ch == 'o'))
 7149:                                     break;
 7150:                                 j = INVEXPR;
 7151:                                 b = xb;
 7152:                                 goto zserr;
 7153:                             }
 7154:                         }
 7155:                     }           /* end data/order/query check */
 7156:                     if (ch == 'e' ||    /* $EXTRACT */
 7157:                         ch == 'p' ||    /* $PIECE */
 7158:                         ch == 'a' ||    /* $ASCII */
 7159:                         ch == 'g' ||    /* $GET */
 7160:                         ch == 'j' ||    /* $JUSTIFY */
 7161:                         ch == 'l' ||    /* $LENGTH */
 7162:                         ch == 'r' ||    /* $RANDOM/REVERSE */
 7163:                         ch == 't' ||    /* $TEXT/TRANSLATE */
 7164:                         ch == 'f') {    /* $FIND/FNUMBER */
 7165:                         int     xch,
 7166:                             xi,
 7167:                             xj,
 7168:                             xa;
 7169:                         char   *xb;
 7170:                         
 7171:                         xb = b;     /* do not change old 'b' pointer */
 7172: /* skip name */
 7173:                         while (((xch = (*xb)) >= 'A' && xch <= 'Z') ||
 7174:                                (xch >= 'a' && xch <= 'z'))
 7175:                             xb++;
 7176:                         if (xch == '(') {
 7177:                             xi = 0; /* quotes */
 7178:                             xj = 0; /* brackets */
 7179:                             xa = 1;
 7180:                             for (;;)
 7181:                             {
 7182:                                 xch = (*++xb);
 7183:                                 if (xch == EOL)
 7184:                                     break;
 7185:                                 if (xch == '"') {
 7186:                                     toggle (xi);
 7187:                                     continue;
 7188:                                 }
 7189:                                 if (xi)
 7190:                                     continue;
 7191:                                 if (xch == '(') {
 7192:                                     xj++;
 7193:                                     continue;
 7194:                                 }
 7195:                                 if (xch == ')') {
 7196:                                     if (xj-- > 0)
 7197:                                         continue;
 7198:                                     break;
 7199:                                 }
 7200:                                 if (xj == 0 && xch == ',') {
 7201:                                     xa++;
 7202:                                     continue;
 7203:                                 }
 7204:                             }
 7205:                             if ((ch == 'e' && (xa > 3)) ||  /* $EXTRACT */
 7206:                                 (ch == 'p' && (xa < 2 || xa > 4)) ||    /* $PIECE */
 7207:                                 (ch == 'a' && (xa > 2)) ||  /* $ASCII */
 7208:                                 (ch == 'g' && (xa > 2)) ||  /* $GET */
 7209:                                 (ch == 'j' && (xa < 2 || xa > 3)) ||    /* $JUSTIFY */
 7210:                                 (ch == 'l' && (xa > 2)) ||  /* $LENGTH */
 7211:                                 (ch == 'r' && (xa > 1)) ||  /* $RANDON/$REVERSE */
 7212:                                 (ch == 't' && (xa > 3)) ||  /* $TEXT/TRANSLATE */
 7213:                                 (ch == 'f' && (xa < 2 || xa > 3))) {    /* $FIND/FNUMBER */
 7214:                                 j = FUNARG;
 7215:                                 b = xb;
 7216:                                 goto zserr;
 7217:                             }
 7218:                         }
 7219:                     }           /* end number of args check */
 7220:                     continue;
 7221:                 }
 7222:                 if (ch == '(') {
 7223:                     j++;
 7224:                     continue;
 7225:                 }
 7226:                 if (ch == ')') {
 7227:                     if (j--)
 7228:                         continue;
 7229:                     break;
 7230:                 }
 7231:                 if (ch == ',') {
 7232:                     if ((ch = *b) == SP || ch == EOL || ch == ',') {
 7233:                         j = ARGLIST;
 7234:                         goto zserr;
 7235:                     }
 7236:                 }
 7237:             }
 7238:             if (i)
 7239:                 j = QUOTER;
 7240:             else if (j)
 7241:                 j = j < 0 ? INVEXPR : BRAER;
 7242:             if (j == OK && ch != EOL && ch != SP)
 7243:                 j = SPACER;
 7244:             if (j)
 7245:                 goto zserr;
 7246:         }               /* end postcond */
 7247:         if (ch == SP)
 7248:             ch = *b;
 7249:         else if (ch != EOL) {
 7250:             j = SPACER;
 7251:             goto zserr;
 7252:         }
 7253:         if ((ch == SP || ch == EOL) &&  /* never argumentless */
 7254:             (f == 'j' || f == 'o' || f == 'r' ||
 7255:              f == 's' || f == 'u' || f == 'x' ||
 7256:              f == 'g')) {
 7257:             j = ARGLIST;
 7258:             goto zserr;
 7259:         }
 7260: /* or.. always argumentless */
 7261:         if ((ch != SP && ch != EOL) && (f == 'e' || (f == 'q' && forline))) {
 7262:             j = SPACER;
 7263:             goto zserr;
 7264:         }
 7265:         if (f == 'f')
 7266:             forline = TRUE;
 7267:         if (ch == EOL)
 7268:             break;
 7269: /* scan argument */
 7270:         i = 0;              /* quotes */
 7271:         j = 0;              /* brackets */
 7272:         ch = SP;            /* init: previous character */
 7273:         for (;;)                /* scan argument */
 7274:         {
 7275:             f = ch;         /* f=previous character */
 7276:             if ((ch = *b++) == EOL)
 7277:                 break;
 7278:             if (ch == '*' && *b == ch)
 7279:                 b++;            /* exponentiation */
 7280:             if (ch == '!' && *b == ch)
 7281:                 b++;                /* XOR */
 7282:             if (ch == ']') {
 7283:                 if (*b == ch)
 7284:                     b++;        /* SORTSAFTER */
 7285:                 if (*b == '=')
 7286:                     b++;        /* EQFOLLOWS or EQSORTS */
 7287:             }
 7288:             if (ch == '"') {
 7289:                 toggle (i);
 7290:                 continue;
 7291:             }
 7292:             if (i)
 7293:                 continue;
 7294:             if (ch == '$') {
 7295:                 ch = *b++;
 7296:                 if (ch >= 'A' && ch <= 'Z')
 7297:                     ch += 32;
 7298:                 if ((ch < 'a' || ch > 'z' || ch == 'b' ||
 7299:                      ch == 'm' || ch == 'u' || ch == 'w') && ch != '$') {
 7300:                     j = ILLFUN;
 7301:                     goto zserr;
 7302:                 }
 7303:                 if (ch == 's') {    /* $SELECT */
 7304:                     int     xch,
 7305:                         xi,
 7306:                         xj;
 7307:                     char   *xb;
 7308:                     int     sfl;
 7309:                     
 7310:                     xi = 0;     /* quotes */
 7311:                     xj = 0;     /* brackets */
 7312:                     xb = b;     /* do not change old 'b' pointer */
 7313:                     sfl = TRUE;     /* first ':' expected */
 7314:                     for (;;)
 7315:                     {
 7316:                         if ((xch = *xb++) == EOL ||
 7317:                             ((xch == SP || xch == ',') && xj == 0)) {
 7318:                             if (xj == 0)
 7319:                                 break;  /* $STORAGE */
 7320:                             j = SELER;
 7321:                             b = xb;
 7322:                             goto zserr;
 7323:                         }
 7324:                         if (xch == '"') {
 7325:                             toggle (xi);
 7326:                             continue;
 7327:                         }
 7328:                         if (xi)
 7329:                             continue;
 7330:                         if (xch == ':') {
 7331:                             if (xj > 1)
 7332:                                 continue;
 7333:                             if (sfl) {
 7334:                                 sfl = FALSE;
 7335:                                 continue;
 7336:                             }
 7337:                             j = SELER;
 7338:                             b = xb;
 7339:                             goto zserr;
 7340:                         }
 7341:                         if (xch == ',') {
 7342:                             if (xj > 1)
 7343:                                 continue;
 7344:                             if (!sfl) {
 7345:                                 sfl = TRUE;
 7346:                                 continue;
 7347:                             }
 7348:                             j = SELER;
 7349:                             b = xb;
 7350:                             goto zserr;
 7351:                         }
 7352:                         if (xch == '(') {
 7353:                             xj++;
 7354:                             continue;
 7355:                         }
 7356:                         if (xch == ')') {
 7357:                             if ((xj--) > 1)
 7358:                                 continue;
 7359:                             if (sfl) {
 7360:                                 j = SELER;
 7361:                                 b = xb;
 7362:                                 goto zserr;
 7363:                             }
 7364:                             break;
 7365:                         }
 7366:                     }
 7367:                 }
 7368: /* end select check */
 7369:                 else if (ch == 'd' ||   /* $DATA */
 7370:                          ch == 'g' ||    /* $GET */
 7371:                          ch == 'o' ||    /* $ORDER */
 7372:                          ch == 'n' ||    /* $NEXT */
 7373:                          ch == 'q') {    /* $QUERY */
 7374:                     int     xch,
 7375:                         xi,
 7376:                         xj;
 7377:                     char   *xb;
 7378:                     
 7379:                     xb = b;     /* do not change old 'b' pointer */
 7380: /* skip name */
 7381:                     while (((xch = (*xb)) >= 'A' && xch <= 'Z') ||
 7382:                            (xch >= 'a' && xch <= 'z'))
 7383:                         xb++;
 7384:                     if (xch == '(') {
 7385:                         if ((xch = (*++xb)) == '^' || xch == '%' ||
 7386:                             (xch >= 'A' && xch <= 'Z') ||
 7387:                             (xch >= 'a' && xch <= 'z')) {
 7388:                             xi = xch;
 7389:                             if (xch == '^' && *(xb + 1) == '%')
 7390:                                 xb++;
 7391:                             while
 7392:                                 (((xch = (*++xb)) >= 'A' && xch <= 'Z') ||
 7393:                                  (xch >= 'a' && xch <= 'z') ||
 7394:                                  (xch >= '0' && xch <= '9') ||
 7395:                                  (xch == '.') ||
 7396:                                  (xch == '/' && xi <= '^') ||
 7397:                                  (xch == '%' && *(xb - 1) == '/')) ;
 7398:                             
 7399:                         } else {
 7400:                             if (xch == '@')
 7401:                                 continue;
 7402:                             j = INVEXPR;
 7403:                             b = xb;
 7404:                             goto zserr;
 7405:                         }
 7406:                         xi = 0;     /* quotes */
 7407:                         xj = 0;     /* brackets */
 7408:                         for (;;)
 7409:                         {
 7410:                             xch = *xb++;
 7411:                             if (xch == '"' && xj) {
 7412:                                 toggle (xi);
 7413:                                 continue;
 7414:                             }
 7415:                             if (xi && (xch != EOL))
 7416:                                 continue;
 7417:                             if (xch == '(') {
 7418:                                 xj++;
 7419:                                 continue;
 7420:                             }
 7421:                             if (xch == ')') {
 7422:                                 if (xj-- > 0)
 7423:                                     continue;
 7424:                                 break;
 7425:                             }
 7426:                             if (xj && xch != EOL)
 7427:                                 continue;
 7428:                             if (xch == ',' &&
 7429:                                 (ch == 'g' || ch == 'q' || ch == 'o'))
 7430:                                 break;
 7431:                             j = INVEXPR;
 7432:                             b = xb;
 7433:                             goto zserr;
 7434:                         }
 7435:                     }
 7436:                 }           /* end data/order/query check */
 7437:                 if (ch == 'e' ||    /* $EXTRACT */
 7438:                     ch == 'p' ||    /* $PIECE */
 7439:                     ch == 'a' ||    /* $ASCII */
 7440:                     ch == 'g' ||    /* $GET */
 7441:                     ch == 'j' ||    /* $JUSTIFY */
 7442:                     ch == 'l' ||    /* $LENGTH */
 7443:                     ch == 'r' ||    /* $RANDON/$REVERSE */
 7444:                     ch == 't' ||    /* $TEXT/TRANSLATE */
 7445:                     ch == 'f') {    /* $FIND/FNUMBER */
 7446:                     int     xch,
 7447:                         xi,
 7448:                         xj,
 7449:                         xa;
 7450:                     char   *xb;
 7451:                     
 7452:                     xb = b;     /* do not change old 'b' pointer */
 7453: /* skip name */
 7454:                     while (((xch = (*xb)) >= 'A' && xch <= 'Z') ||
 7455:                            (xch >= 'a' && xch <= 'z'))
 7456:                         xb++;
 7457:                     if (xch == '(') {
 7458:                         xi = 0;     /* quotes */
 7459:                         xj = 0;     /* brackets */
 7460:                         xa = 1;
 7461:                         for (;;)
 7462:                         {
 7463:                             xch = (*++xb);
 7464:                             if (xch == EOL)
 7465:                                 break;
 7466:                             if (xch == '"') {
 7467:                                 toggle (xi);
 7468:                                 continue;
 7469:                             }
 7470:                             if (xi)
 7471:                                 continue;
 7472:                             if (xch == '(') {
 7473:                                 xj++;
 7474:                                 continue;
 7475:                             }
 7476:                             if (xch == ')') {
 7477:                                 if (xj-- > 0)
 7478:                                     continue;
 7479:                                 break;
 7480:                             }
 7481:                             if (xj == 0 && xch == ',') {
 7482:                                 xa++;
 7483:                                 continue;
 7484:                             }
 7485:                         }
 7486:                         if ((ch == 'e' && (xa > 3)) ||  /* $EXTRACT */
 7487:                             (ch == 'p' && (xa < 2 || xa > 4)) ||    /* $PIECE */
 7488:                             (ch == 'a' && (xa > 2)) ||  /* $ASCII */
 7489:                             (ch == 'o' && (xa > 2)) ||  /* $ORDER */
 7490:                             (ch == 'q' && (xa > 2)) ||  /* $QUERY */
 7491:                             (ch == 'g' && (xa > 2)) ||  /* $GET */
 7492:                             (ch == 'j' && (xa < 2 || xa > 3)) ||    /* $JUSTIFY */
 7493:                             (ch == 'l' && (xa > 2)) ||  /* $LENGTH */
 7494:                             (ch == 't' && (xa > 3)) ||  /* $TEXT/TRANSLATE */
 7495:                             (ch == 'f' && (xa < 2 || xa > 3))) {    /* $FIND/FNUMBER */
 7496:                             j = FUNARG;
 7497:                             b = xb;
 7498:                             goto zserr;
 7499:                         }
 7500:                     }
 7501:                 }           /* end number of args check */
 7502:                 continue;
 7503:             }
 7504:             if (ch == '(') {
 7505:                 if (f == ')' || f == '"') {
 7506:                     j = ARGLIST;
 7507:                     goto zserr;
 7508:                 }
 7509:                 j++;
 7510:                 continue;
 7511:             }
 7512:             if (ch == ')') {
 7513:                 tmp[0] = f;
 7514:                 tmp[1] = EOL;
 7515:                 if (find (" !#&'(*+,-/:<=>?@[\\]_\201", tmp)) {
 7516:                     j = MISSOPD;
 7517:                     goto zserr;
 7518:                 }
 7519:                 if (j--)
 7520:                     continue;
 7521:                 break;
 7522:             }
 7523:             if (ch == SP)
 7524:                 break;
 7525:             tmp[0] = ch;
 7526:             tmp[1] = EOL;
 7527:             if (ch == '/' && (cmnd == 'r' || cmnd == 'w') && (f == SP || f == ',')) {
 7528:                 int     xch,
 7529:                     xi,
 7530:                     xj;
 7531:                 char   *xb;
 7532:                 
 7533:                 xi = 0;         /* quotes */
 7534:                 xj = 0;         /* brackets */
 7535:                 xb = b;         /* do not change old 'b' pointer */
 7536:                 while ((xch = *xb++) != EOL) {
 7537:                     if (xch == '"') {
 7538:                         toggle (xi);
 7539:                         continue;
 7540:                     }
 7541:                     if (xi)
 7542:                         continue;
 7543:                     if (xch == '(') {
 7544:                         xj++;
 7545:                         continue;
 7546:                     }
 7547:                     if (xch == ')') {
 7548:                         if ((xj--) > 1)
 7549:                             continue;
 7550:                         xch = *xb++;
 7551:                         break;
 7552:                     }
 7553:                     if (xj)
 7554:                         continue;
 7555:                     if ((xch < 'A' || xch > 'Z') &&
 7556:                         (xch < '1' || xch > '3'))
 7557:                         break;
 7558:                 }
 7559:                 if (xch != ',' && xch != SP && xch != EOL) {
 7560:                     b = xb;
 7561:                     j = SPACER;
 7562:                     goto zserr;
 7563:                 }
 7564:                 if (--xb == b) {
 7565:                     j = ARGLIST;
 7566:                     goto zserr;
 7567:                 }
 7568:             }
 7569:             if (f == '?' && cmnd != 'r' && cmnd != 'w' &&
 7570:                 find ("@1234567890.\201", tmp) == 0) {  /* pattern match */
 7571:                 j = MISSOPD;
 7572:                 goto zserr;
 7573:             }
 7574: /* note: write/read may have !?*#/ not as binary op */
 7575:             if (find ("&<=>[\\]_\201", tmp) ||  /* binary operator */
 7576:                 (find ("!?*#/\201", tmp) && cmnd != 'r' && cmnd != 'w'))
 7577: /* some may be negated */
 7578:             {
 7579:                 if (find ("#*/\\_\201", tmp) || f != NOT) {
 7580:                     tmp[0] = f;
 7581:                     if (find (" &'(+-<=>[\\]_\201", tmp) ||
 7582:                         (find ("!?*#/\201", tmp) && cmnd != 'r' && cmnd != 'w')) {
 7583:                         j = MISSOPD;
 7584:                         goto zserr;
 7585:                     }
 7586:                 }
 7587:                 continue;
 7588:             }
 7589:             if (ch == '+' || ch == '-') {
 7590:                 if (f == NOT) {
 7591:                     j = MISSOPD;
 7592:                     goto zserr;
 7593:                 }
 7594:                 continue;
 7595:             }
 7596:             if (ch == ':') {
 7597:                 if (f == ',') {
 7598:                     j = MISSOPD;
 7599:                     goto zserr;
 7600:                 }
 7601:                 continue;
 7602:             }
 7603:             if (ch == '`' || ch == ';' || ch == '{' || ch == '|' ||
 7604:                 ch == '}' || ch == '~') {   /* illegal characters */
 7605:                 j = ILLOP;
 7606:                 goto zserr;
 7607:             }
 7608:             if (ch == '$') {        /* check function */
 7609:                 if (((f = *b | 0140) < 'a' || f > 'z') && f != '$') {
 7610:                     j = ILLFUN;
 7611:                     goto zserr;
 7612:                 }
 7613:                 continue;
 7614:             }
 7615:             if (ch == ',') {        /* comma is a delimiter! */
 7616:                 if (*(b - 2) == SP || (f = *b) == SP || f == EOL || f == ',') {
 7617:                     j = ARGLIST;
 7618:                     goto zserr;
 7619:                 }
 7620:             }
 7621:         }
 7622:         if (i)
 7623:             j = QUOTER;
 7624:         else if (j)
 7625:             j = j > 0 ? INVEXPR : BRAER;
 7626:         if (j)
 7627:             goto zserr;
 7628:         if (ch == EOL)
 7629:             break;
 7630: /* skip spaces before next command */
 7631:         while (ch == SP || ch == TAB)
 7632:             ch = *b++;
 7633:         b--;
 7634:     }
 7635:     *a = EOL;               /* no error found */
 7636:     return;
 7637: }                   /* end zsyntax() */
 7638: 
 7639: time_t horolog_to_unix (char *horo)
 7640: {
 7641:     
 7642:     char *ptr = horo;
 7643:     register char ch;
 7644:     register short i;
 7645:     
 7646:     char horo_days[10];
 7647:     char horo_seconds[10];
 7648: 
 7649:     time_t seconds;
 7650: 
 7651:     i = 0;
 7652:     
 7653:     while ((ch = *(ptr++)) != ',') {
 7654:         horo_days[i++] = ch;
 7655:     }
 7656:     horo_days[i] = '\0';
 7657: 
 7658:     i = 0;
 7659:     while ((ch = *(ptr++)) != EOL) {
 7660:         horo_seconds[i++] = ch;
 7661:     }
 7662:     horo_seconds[i] = '\0';
 7663: 
 7664:     seconds = (((atol (horo_days) - 47117L) * 86400L) + 43200 + atol (horo_seconds) + tzoffset);
 7665: 
 7666:     return (time_t) seconds;
 7667:     
 7668: }
 7669: 
 7670: 
 7671: /* a    = result string
 7672:  * type = type of transform
 7673:  */
 7674: void zkey (char *a, long type)
 7675: {
 7676: 
 7677:     char del0;
 7678:     char del1;
 7679:     char del2;
 7680:     char del3;
 7681:     char del4;
 7682: 
 7683:     int f;
 7684:     char prod_rule[256];
 7685:     int i;
 7686:     int ncs;            /* flag: non_collating_substring */
 7687: 
 7688:     if (type == 0) type = (-v93);          /* zero is reverse of default type */
 7689:     if ((f = (type < 0))) type = (-type);
 7690:     
 7691:     if (type-- > NO_V93) {
 7692:         merr_raise (ARGER);
 7693:         return;
 7694:     }
 7695:     
 7696:     del2 = v93a[type][0];       /* delimiter between primary/seconary key */
 7697:     del0 = v93a[type][1];       /* delimiter between 'from' and 'to' substring */
 7698:     del3 = '(';             /* introducer for 'non-collating' substrings */
 7699:     del4 = ')';             /* terminator for 'non-collating' substring */
 7700:     ncs = FALSE;            /* non_collating_substring flag */
 7701: 
 7702:     if (del0 == EOL) return;             /* no rule under of this type */
 7703: 
 7704:     del1 = v93a[type][2];       /* delimiter between different from/to pairs */
 7705: /* production rule, stripped from delimiter declaration */
 7706: /* with an added separator character at both ends */
 7707: 
 7708:     i = stcpy (prod_rule, &v93a[type][2]);
 7709:     prod_rule[i] = del1;
 7710:     prod_rule[++i] = EOL;
 7711: 
 7712:     if (f) goto backw;         /* negative is backward transform */
 7713:     
 7714: /* forward transform */
 7715:     i = stlen (a);
 7716: 
 7717:     if (i == 0) return;             /* string empty - nothing to do */
 7718:     
 7719:     {
 7720:         char ct0[256];
 7721:         char ct1[256];
 7722:         int ch = 0;
 7723:         int d = 0;
 7724:         int i1 = 0;
 7725:         int j = 0;
 7726:         int n0 = 0;
 7727:         int n1 = 0;
 7728:         int pos = 0;
 7729:         char c;
 7730:         
 7731:         i = 0;
 7732:         n0 = 0;
 7733:         n1 = 0;
 7734:         
 7735:         while ((c = a[i]) != EOL) { /* non-collating substring? */
 7736: 
 7737:             if (c == del3) {        /* introducer valid only with matching terminator! */
 7738: 
 7739:                 j = i;
 7740: 
 7741:                 while ((ch = a[++j]) != EOL) {
 7742:                     if (ch == del4) break;
 7743:                 }
 7744:                 
 7745:                 if (ch == del4) {
 7746: 
 7747:                     while (i <= j) ct1[n1++] = a[i++];
 7748:                     continue;
 7749:                     
 7750:                 }
 7751:                 
 7752:             }
 7753:             
 7754:             j = 0;
 7755:             d = 0;
 7756:             
 7757: /* search for longest matching string */
 7758:             while ((ch = prod_rule[j++]) != EOL) {
 7759: 
 7760:                 if (ch == del1) {
 7761:                     
 7762:                     if (prod_rule[j] != c) continue;
 7763:                     
 7764:                     i1 = i;
 7765: 
 7766:                     while ((ch = prod_rule[j++]) != del0 && ch == a[i1++]) ;
 7767: 
 7768:                     if (ch != del0) continue;
 7769:                     
 7770:                     if ((ch = i1 - i) > d) {
 7771:                         d = ch;
 7772:                         pos = j;
 7773:                     }
 7774:                     
 7775:                 }
 7776:                 
 7777:             }
 7778:             
 7779:             if (n0 > STRLEN) {
 7780:                 merr_raise (M75);
 7781:                 return;
 7782:             }               /* string too long */
 7783:             
 7784:             if (d == 0) {
 7785: 
 7786:                 ct0[n0++] = c;
 7787:                 ct1[n1++] = '0';
 7788:                 i++;
 7789: 
 7790:                 continue;
 7791:                 
 7792:             }
 7793:             
 7794:             j = 0;
 7795:             c = prod_rule[pos];
 7796:             ch = '0';
 7797: 
 7798:             if (c == del1) {
 7799:                 
 7800:                 ct1[n1++] = ' ';
 7801:                 
 7802:                 while (j <= pos) {
 7803: 
 7804:                     if (prod_rule[j] == del0) ch++;
 7805: 
 7806:                     j++;
 7807:                     
 7808:                 }
 7809:                 
 7810:             }
 7811:             else {
 7812: 
 7813:                 while (j <= pos) {
 7814: 
 7815:                     if (prod_rule[j] == del0 && prod_rule[j + 1] == c) ch++;
 7816:                     
 7817:                     j++;
 7818:                     
 7819:                 }
 7820:                 
 7821:             }
 7822:             
 7823:             j = 0;
 7824:             i += d;
 7825:             ct1[n1++] = ch;
 7826: 
 7827:             while ((ct0[n0++] = prod_rule[pos++]) != del1) {
 7828: 
 7829:                 if (n1 > STRLEN) {
 7830:                     merr_raise (M75);
 7831:                     return;
 7832:                 }           /* string too long */
 7833:                 
 7834:             }
 7835:             
 7836:             n0--;
 7837:             
 7838:         }
 7839:         
 7840:         ct0[n0++] = del2;
 7841:         ct0[n0] = EOL;
 7842:         ct1[n1] = EOL;
 7843: 
 7844: /* purge trailing zeroes */
 7845:         while (ct1[--n1] == '0') {
 7846: 
 7847:             ct1[n1] = EOL;
 7848: 
 7849:             if (n1 == 0) {
 7850:                 n0--;
 7851:                 break;
 7852:             }
 7853:             
 7854:         }
 7855:         
 7856:         if (n0 + n1 > STRLEN) {
 7857:             merr_raise (M75);
 7858:             return;
 7859:         }               /* string too long */
 7860:         
 7861:         stcpy (a, ct0);
 7862:         stcpy (&a[n0], ct1);
 7863:         
 7864:     }
 7865:     
 7866:     return;
 7867: 
 7868:     
 7869: /* backward transform */
 7870: backw:
 7871: 
 7872:     i = stlen (a);
 7873: 
 7874:     if (i == 0) return;             /* string empty */
 7875:     
 7876:     {
 7877:         int c;
 7878:         int ch;
 7879:         int d;
 7880:         int n0;
 7881:         int n1;
 7882:         int n2;
 7883:         int j;
 7884:         char z[256];
 7885:         
 7886:         stcpy (z, a);
 7887:         n0 = 0;
 7888:         n1 = 0;
 7889:         n2 = 0;
 7890:         
 7891:         while ((d = z[n1++]) != EOL && (d != del2)) ;
 7892: 
 7893:         if (d == EOL) return;         /* nothing to change */
 7894: 
 7895:         for (;;) {
 7896:             
 7897:             c = z[n0];
 7898:             d = z[n1];
 7899: 
 7900:             if (c == del2 && d == EOL) break;
 7901: 
 7902:             if (d == EOL) {
 7903:                 d = '0';
 7904:             }
 7905:             else {
 7906:                 n1++;
 7907:             }
 7908: 
 7909:             
 7910:             if (d == del3) {
 7911: 
 7912:                 a[n2++] = d;
 7913:                 ncs = TRUE;
 7914:                 
 7915:                 continue;
 7916:                 
 7917:             }
 7918: 
 7919:             if (ncs) {
 7920: 
 7921:                 a[n2++] = d;
 7922:                 
 7923:                 if (d == del4) ncs = FALSE;
 7924:                 
 7925:                 continue;
 7926:                 
 7927:             }
 7928:             
 7929:             if (d == ' ') {     /* replacement with no chars */
 7930: 
 7931:                 d = z[n1++] - '0';
 7932:                 j = 1;
 7933: 
 7934:                 while ((ch = prod_rule[j++]) != EOL) {
 7935:                     if (ch == del0 && (--d) == 0) break;
 7936:                 }
 7937:                 
 7938:             }
 7939:             else {
 7940: 
 7941:                 if ((d -= '0') == 0) {
 7942: 
 7943:                     a[n2++] = c;
 7944:                     n0++;
 7945: 
 7946:                     continue;
 7947:                     
 7948:                 }
 7949:                 
 7950:                 j = 1;
 7951: 
 7952:                 while ((ch = prod_rule[j++]) != EOL) {
 7953:                     if (ch == del0 && prod_rule[j] == c && (--d) == 0) break;
 7954:                 }
 7955:                 
 7956:             }
 7957:             
 7958:             d = j;
 7959: 
 7960:             while ((ch = prod_rule[j++]) != EOL) {
 7961: 
 7962:                 if (ch == del1) break;
 7963:                 
 7964:                 n0++;
 7965:                 
 7966:             }
 7967:             
 7968:             d--;
 7969: 
 7970:             while (prod_rule[d--] != del1) ;
 7971: 
 7972:             if (prod_rule[d + 2] == EOL) {
 7973:                 merr_raise (ARGER);
 7974:                 return;
 7975:             }               /* string is not of proper format */
 7976: 
 7977:             d++;
 7978: 
 7979:             while ((ch = prod_rule[++d]) != del0) a[n2++] = ch;
 7980:             
 7981:         }
 7982:         
 7983:         a[n2] = EOL;
 7984:         
 7985:     }
 7986:     
 7987:     return;
 7988: }                   /* end zkey() */
 7989: 
 7990: int levenshtein (char *word1, char *word2)
 7991: {
 7992:     int l1 = 0;
 7993:     int l2 = 0;
 7994:     int i = 0;
 7995:     int j = 0;
 7996:     int m = 0;
 7997:     int t = 0;
 7998:     int x = 0;
 7999:     char    d[2][256];
 8000: 
 8001:     l1 = stlen (word1);
 8002:     word1--;
 8003:     
 8004:     l2 = stlen (word2);
 8005:     word2--;
 8006:     
 8007:     if (l1 == 0) return (l2);
 8008:     if (l2 == 0) return (l1);
 8009:     
 8010:     t = 0;
 8011: 
 8012:     for (i = 0; i <= l1; i++) d[0][i] = i;
 8013:     
 8014:     for (j = 1; j <= l2; j++) {
 8015: 
 8016:         t ^= 1;
 8017:         d[t][0] = j;
 8018: 
 8019:         for (i = 1; i <= l1; i++) {
 8020: 
 8021:             m = d[t ^ 1][i - 1];
 8022:             if (word1[i] != word2[j]) m++;
 8023: 
 8024:             x = d[t ^ 1][i];
 8025:             if (++x < m) m = x;
 8026: 
 8027:             x = d[t][i - 1];
 8028:             if (++x < m) m = x;
 8029: 
 8030:             d[t][i] = m;
 8031:             
 8032:         }
 8033:         
 8034:     }
 8035:     
 8036:     return (m);
 8037: }
 8038: 
 8039: /* conditional rounding */
 8040: /* 'a' is assumed to be a 'canonic' numeric string           */
 8041: /* it is rounded to 'digits' fractional digits provided that */
 8042: /* the canonic result has at most (digits-2) frac.digits     */
 8043: void cond_round (char *a, int digits)
 8044: {
 8045:     int ch;
 8046:     int i;
 8047:     int point;
 8048:     int lena;
 8049: 
 8050:     point = -1;
 8051: 
 8052:     i = 0;
 8053:     i = 0;
 8054: 
 8055:     while (a[i] != EOL) {
 8056: 
 8057:         if (a[i] == '.') point = i;
 8058:         i++;
 8059:         
 8060:     }
 8061:     
 8062:     lena = i;
 8063: 
 8064:     if (point < 0) point = i;
 8065:     if ((point + digits + 1) >= i) return;             /* nothing to round */
 8066:     
 8067:     i = point + digits + 1;
 8068: 
 8069:     if (a[i] < '5') {
 8070: 
 8071:         if ((a[i - 1] != '0') || (a[i - 2] != '0')) return;         /* condition! */
 8072:         
 8073:         a[i] = EOL;
 8074: 
 8075:         while (a[--i] == '0') a[i] = EOL;
 8076:         
 8077:         if (a[i] == '.') {
 8078: 
 8079:             a[i] = EOL;
 8080: 
 8081:             if (i == 0 || (i == 1 && a[0] == '-')) a[0] = '0';
 8082:             
 8083:         }
 8084:         
 8085:         return;
 8086:         
 8087:     }
 8088:     
 8089:     if (a[i - 1] != '9' || a[i - 2] != '9') return;             /* condition */
 8090:     
 8091:     for (;;) {
 8092:         
 8093:         if (i >= point) {
 8094:             a[i] = EOL;
 8095:         }
 8096:         else {
 8097:             a[i] = '0';
 8098:         }
 8099:         
 8100:         if (--i < (a[0] == '-')) {
 8101: 
 8102:             for (i = lena; i >= 0; i--) a[i + 1] = a[i];
 8103: 
 8104:             a[a[0] == '-'] = '1';
 8105: 
 8106:             break;
 8107:             
 8108:         }
 8109:         
 8110:         if ((ch = a[i]) == '.') continue;
 8111:         
 8112:         if (a[i] < '9' && ch >= '0') {
 8113:             a[i] = ++ch;
 8114:             break;
 8115:         }
 8116:         
 8117:     }
 8118: 
 8119:     return;
 8120:     
 8121: }                   /* end cond_round */
 8122: 
 8123: short is_horolog(char *s)
 8124: {
 8125:     
 8126:     register int i;
 8127:     char ch;
 8128:     int commata = 0;
 8129:     int digits = 0;   
 8130: 
 8131:     if (!isdigit (s[0])) return FALSE;
 8132: 
 8133:     for (i = 0; i < stlen (s); i++) {
 8134: 
 8135:         ch = s[i];
 8136: 
 8137:         if (isdigit (ch)) {
 8138:             digits++;
 8139:         }
 8140:         else if (ch == ',' && commata == 0) {
 8141:             commata++;
 8142:         }
 8143:         else if (ch == ',' && commata > 0) {
 8144:             return FALSE;         
 8145:         }
 8146:         else {
 8147:             return FALSE;
 8148:         }
 8149: 
 8150:     }
 8151: 
 8152:     if (commata != 1) {
 8153:         return FALSE;
 8154:     }
 8155:     else {
 8156:         return TRUE;
 8157:     }
 8158:     
 8159: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>