File:  [Coherent Logic Development] / freem / src / expr.c
Revision 1.18: download - view: text, annotated - select for diffs
Fri May 2 16:30:16 2025 UTC (3 months ago) by snw
Branches: MAIN
CVS tags: HEAD
Fix broken build due to time issues

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

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