File:  [Coherent Logic Development] / freem / src / expr.c
Revision 1.8: download - view: text, annotated - select for diffs
Sat Mar 22 04:47:18 2025 UTC (7 months ago) by snw
Branches: MAIN
CVS tags: v0-62-2, HEAD
Silently truncate long names in STRING exprs when  evaluates to an obsolete MDC standard

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

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