File:  [Coherent Logic Development] / freem / src / expr.c
Revision 1.19: download - view: text, annotated - select for diffs
Fri Jan 16 20:31:56 2026 UTC (2 months, 1 week ago) by snw
Branches: MAIN
CVS tags: HEAD
Fix LBLUNDEF error on reverse $QUERY

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

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