Annotation of freem/src/routine.c, revision 1.5

1.1       snw         1: /*
1.5     ! snw         2:  *   $Id: routine.c,v 1.4 2025/03/27 03:27:35 snw Exp $
1.1       snw         3:  *    Routine buffer management
                      4:  *
                      5:  *  
1.2       snw         6:  *   Author: Serena Willis <snw@coherent-logic.com>
1.1       snw         7:  *    Copyright (C) 1998 MUG Deutschland
1.3       snw         8:  *    Copyright (C) 2023, 2025 Coherent Logic Development LLC
1.1       snw         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:  *
1.4       snw        26:  *   $Log: routine.c,v $
1.5     ! snw        27:  *   Revision 1.4  2025/03/27 03:27:35  snw
        !            28:  *   Install init scripts to share/freem/examples/init and fix regression in method dispatch
        !            29:  *
1.4       snw        30:  *   Revision 1.3  2025/03/09 19:50:47  snw
                     31:  *   Second phase of REUSE compliance and header reformat
                     32:  *
1.3       snw        33:  *
                     34:  * SPDX-FileCopyrightText:  (C) 2025 Coherent Logic Development LLC
                     35:  * SPDX-License-Identifier: AGPL-3.0-or-later
1.1       snw        36:  **/
                     37: 
                     38: #include <string.h>
                     39: #include <errno.h>
                     40: #include <sys/types.h>
                     41: 
                     42: #if !defined(__OpenBSD__) && !defined(__FreeBSD__)
                     43: # include <sys/timeb.h>
                     44: #endif
                     45: 
                     46: #include <sys/ioctl.h>
                     47: #include <unistd.h>
                     48: #include <stdlib.h>
                     49: #include <ctype.h>
                     50: 
                     51: #ifdef AMIGA68K
                     52: #include <sys/fcntl.h>
                     53: #endif
                     54: 
                     55: #include "mpsdef.h"
                     56: 
                     57: #include <time.h>
                     58: 
                     59: #ifdef USE_SYS_TIME_H
                     60: #include <sys/time.h>
                     61: #endif
                     62: 
                     63: #include "events.h"
                     64: 
                     65: short rtn_get_offset(char *buf)
                     66: {
                     67:     char *rp;
                     68:     char *rc;
                     69:     char *p;
                     70:     char otag[256];
                     71:     char ortn[256];
                     72:     char oline[256];    
                     73:     
                     74:     register int i = 0;
                     75:     register int j = 0;
                     76:     register int k = 0;
                     77:     
                     78:     int os = 0;
                     79:     
                     80:     stcpy (ortn, rou_name);
                     81: 
                     82:     rp = rouptr;
                     83:     rc = roucur;
                     84: 
                     85:     stcnv_m2c (ortn);
                     86:     
                     87:     while (rp < rc) {
                     88: 
                     89:         i = 0;
                     90:         for (p = rp + 1; p < rc && *p != EOL && *p != '\0'; p++) {
                     91:             if (i < 256) {
                     92:                 oline[i++] = *p;
                     93:             }
                     94:         }
                     95:         oline[i] = '\0';
                     96: 
                     97:         if (isalpha (oline[0]) || oline[0] == '%') {
                     98: 
                     99:             os = 0;
                    100:             k = 0;
                    101: 
                    102:             for (j = 0; j < strlen (oline); j++) {
                    103: 
                    104:                 switch (oline[j]) {
                    105: 
                    106:                     case ' ':
                    107:                     case '(':
                    108:                     case ';':
                    109:                     case EOL:
                    110:                         otag[k] = '\0';
                    111:                         
                    112:                         break;
                    113: 
                    114:                     default:
                    115:                         otag[k++] = oline[j];
                    116:                 }
                    117: 
                    118:                 if (oline[j] == ' ' || oline[j] == '(' || oline[j] == ';' || oline[j] == EOL) break;
                    119:             }
                    120:         }
                    121:         else {
                    122:             os++;
                    123:         }
                    124: 
                    125:         rp = p + 1;
                    126:     }
                    127: 
                    128:     if (os) {
                    129:         sprintf (buf, "%s+%d^%s\201", otag, os, ortn);
                    130:     }
                    131:     else {
                    132:         sprintf (buf, "%s^%s\201", otag, ortn);
                    133:     }
                    134: 
                    135:     
                    136:     return TRUE;
                    137: }
                    138: 
                    139: char *rtn_resolve(char *rou, char *tag, char *buf)
                    140: {
                    141:     char superclass[255];
                    142:   
                    143:     if (rtn_has_tag (rou, tag)) {
                    144:         strcpy (buf, rou);
                    145:         return buf;
                    146:     }
                    147:     else {
                    148:         if (rtn_get_superclass (rou, superclass)) {
                    149:             return rtn_resolve (superclass, tag, buf);
                    150:         }
                    151:         else {
                    152:             buf = NULL;
                    153:             return NULL;
                    154:         }
                    155:     }
                    156:     
                    157: }
                    158: 
                    159: short rtn_get_superclass(char *rou, char *buf)
                    160: {
                    161:     FILE *fp;
                    162:     char pth[PATHLEN];
                    163:     char line[255];
                    164:     char *s;
                    165:     short rtn_exists;
                    166:     short after_parens;
                    167:     short found_super;
                    168:     char *p;
                    169:     register char ch;
                    170: 
                    171:     if (strcmp (rou, "%OBJECT") == 0) {
                    172:         buf = NULL;
                    173:         return FALSE;
                    174:     }
                    175:     
                    176:     rtn_exists = rtn_get_path (rou, pth);
                    177: 
                    178:     if (rtn_exists == FALSE) {
                    179:         buf = NULL;
                    180:         return FALSE;
                    181:     }
                    182: 
                    183:     fp = fopen (pth, "r");
                    184:     if (fp == NULL) {
                    185:         buf = NULL;
                    186:         return FALSE;
                    187:     }
                    188:     
                    189:     s = fgets (line, 255, fp);
                    190: 
                    191:     fclose (fp);
                    192:     
                    193:     if (s == NULL) {
                    194:         buf = NULL;
                    195:         return FALSE;
                    196:     }
                    197:     
                    198:     if ((!isalpha (line[0])) && (line[0] != '%')) {
                    199:         buf = NULL;
                    200:         return FALSE;
                    201:     }
                    202: 
                    203:     p = line;
                    204:     after_parens = FALSE;
                    205:     found_super = FALSE;
                    206:     
                    207:     while ((ch = *p++) != '\0') {
                    208:         
                    209:         if (ch == ')') after_parens = TRUE;
                    210: 
1.4       snw       211:         /* ignore comments in search for superclass */
                    212:         if (ch == ';' && after_parens == TRUE) {
                    213:             found_super = FALSE;
                    214:             break;
                    215:         }
                    216:         
1.1       snw       217:         if (ch == ':' && after_parens == TRUE) {
                    218:             strcpy (buf, p);
                    219:             found_super = TRUE;
                    220:             break;
                    221:         }
                    222:         
                    223:     }
                    224: 
                    225:     if (!found_super) {
                    226:         sprintf (buf, "%%OBJECT");
                    227:         return TRUE;
                    228:     }
                    229: 
                    230:     p = buf;
                    231:     for (;;) {
                    232:         ch = *p;
                    233: 
                    234:         if (ch == SP || ch == TAB || ch == ';' || ch == '\0' || ch == '\r' || ch == '\n') {
                    235:             *p = '\0';
                    236:             break;
                    237:         }
                    238: 
                    239:         p++;
                    240:     }
                    241:     
                    242:     return TRUE;
                    243: }
                    244: 
                    245: short rtn_get_path(char *rou, char *buf)
                    246: {
                    247:     FILE *fp;
                    248:     char pth[PATHLEN];
                    249:     
                    250:     if (rou[0] == '%') {
                    251:         stcpy (pth, rou0plib);        
                    252:         stcnv_m2c (pth);
                    253:     }
                    254:     else {
                    255:         stcpy (pth, rou0path);
                    256:         stcnv_m2c (pth);
                    257:     }
                    258:     
                    259:     snprintf (buf, PATHLEN, "%s/%s.m", pth, rou);
1.4       snw       260:     
1.1       snw       261:     if ((fp = fopen (buf, "r")) != NULL) {
                    262:         (void) fclose (fp);
                    263: 
                    264:         return TRUE;
                    265:     }
                    266:     else {
                    267:         return FALSE;
                    268:     }
                    269:             
                    270: }
                    271: 
                    272: short rtn_has_tag(char *rou, char *tag)
                    273: {
                    274:     m_entry *entries;
                    275:     m_entry *e;
                    276: 
                    277:     entries = rtn_get_entries (rou);
                    278: 
                    279:     for (e = entries; e != NULL; e = e->next) {
                    280:         if (strcmp (tag, e->tag) == 0) {
                    281:             rtn_free_entries (entries);
                    282:             return TRUE;
                    283:         }
                    284:     }
                    285: 
                    286:     rtn_free_entries (entries);
                    287:     return FALSE;    
                    288: }
                    289: 
                    290: void rtn_free_entries(m_entry *head)
                    291: {
                    292:     m_entry *tmp;
                    293: 
                    294:     while (head != NULL) {
                    295:         tmp = head;
                    296:         head = head->next;
                    297:         free (tmp);
                    298:     }
                    299: 
                    300:     head = NULL;
                    301: }
                    302: 
                    303: m_entry *rtn_get_entries(char *rou)
                    304: {
                    305:     FILE *fp;
                    306:     char rou_path[PATHLEN];
                    307:     m_entry *head = NULL;
                    308:     m_entry *t;
                    309:     register char ch;
                    310:     register int i = 0;
                    311:     register int j = 0;
                    312:     char cur_line[255];
                    313:     char cur_label[255];
                    314:     int has_args = 0;
                    315:     char *paren_pos;
                    316:     
                    317:     if (rtn_get_path (rou, rou_path) == FALSE) {
                    318:         return (m_entry *) NULL;
                    319:     }
                    320: 
                    321:     fp = fopen (rou_path, "r");
                    322: 
                    323:     while (fgets (cur_line, 255, fp) != NULL) {
                    324:         
                    325:         if (isalpha (cur_line[0]) || cur_line[0] == '%') {
                    326:             has_args = 0;
                    327:             j = 0;
                    328:             
                    329:             for (i = 0; i < strlen (cur_line); i++) {
                    330:                 ch = cur_line[i];
                    331:                 
                    332:                 switch (ch) {
                    333:                     
                    334:                     case ')':
                    335:                         cur_label[j++] = ')';                          
                    336:                         
                    337:                     case SP:
                    338:                     case TAB:
                    339:                     case EOL:
                    340:                         cur_label[j] = '\0';
                    341:                         j = 0;
                    342:                         if (strlen (cur_label)) {
                    343:                             t = (m_entry *) malloc (sizeof (m_entry));
                    344:                             NULLPTRCHK(t,"rtn_get_entries");
                    345:                             
                    346:                             paren_pos = strchr (cur_label, '(');
                    347:                             if (paren_pos == NULL) {
                    348:                                 /* not a formallist */
                    349:                                 t->tag = (char *) malloc (sizeof (char) * (strlen (cur_label) + 1));
                    350:                                 NULLPTRCHK(t->tag,"rtn_get_entries");
                    351:                                 
                    352:                                 strcpy (t->tag, cur_label);
                    353:                             }                                    
                    354:                             else {
                    355:                                 /* a formallist */
                    356:                                 char *toktmp;
                    357:                                 
                    358:                                 toktmp = strdup (cur_label);
                    359:                                 NULLPTRCHK(toktmp,"rtn_get_entries");
                    360:                                 
                    361:                                 (void) strtok (toktmp, "(");
                    362:                                 
                    363:                                 t->tag = malloc (sizeof (char) * (strlen (toktmp) + 1));                                        
                    364:                                 NULLPTRCHK(t->tag,"rtn_get_entries");
                    365:                                 
                    366:                                 strcpy (t->tag, toktmp);
                    367:                                 
                    368:                                 free (toktmp);
                    369:                             }
                    370:                             
                    371:                             t->next = head;
                    372:                             head = t;
                    373:                         }
                    374:                         break;
                    375:                         
                    376:                     case '(':
                    377:                         has_args++;
                    378:                     default:
                    379:                         cur_label[j++] = ch;
                    380:                 }
                    381:                 
                    382:                 if (ch == SP || ch == TAB || ch == EOL) break;
                    383:             }
                    384:         }
                    385:     }
                    386: 
                    387:     fclose (fp);
                    388:     return head;
                    389:     
                    390: }
                    391: 
                    392: void zload (char *rou)                         /* load routine in buffer */
                    393: {
                    394:     FILE   *infile;
                    395:     short   linelen;
                    396:     char    pgm[256];
                    397:     char    tmp1[256];
                    398: 
                    399:     register long int i;
                    400:     register long int j;
                    401:     register long int ch;
                    402: 
                    403:     char   *savptr;                    /* save routine pointer */
                    404:     long    timex;
                    405:     short   altern = 0;
                    406: 
                    407:     /* Routines are stored in routine buffers. If a routine is called
                    408:      * we first look whether it's already loaded. If not, we look for
                    409:      * the least recently used buffer and load it there. Besides
                    410:      * dramatically improved performance there is little effect on
                    411:      * the user. Sometimes you see an effect: if the program is changed
                    412:      * by some other user or by yourself using the 'ced' editor you
                    413:      * may get the old version for some time with DO, GOTO or ZLOAD.
                    414:      * A ZREMOVE makes sure the routine is loaded from disk.
                    415:      */
                    416:     if (*rou == EOL || *rou == 0) {    /* routine name empty */
                    417:         
                    418:         pgms[0][0] = EOL;
                    419:         rouend = rouins = rouptr = buff;
                    420:         roucur = buff + (NO_OF_RBUF * PSIZE0 + 1);
                    421:         
                    422:         *rouptr = EOL;
                    423:         *(rouptr + 1) = EOL;
                    424:         *(rouptr + 2) = EOL;
                    425:         
                    426:         dosave[0] = 0;
                    427:         
                    428:         return;
                    429: 
                    430:     }
                    431: 
                    432:     savptr = rouptr;
                    433:     
                    434:     /* what time is it ? */
                    435:     timex = time (0L);
                    436:     
                    437:     /* FreeM: it takes a lickin' and keeps on tickin' */
                    438: 
                    439:     /* let's have a look whether we already have the stuff */
                    440:     for (i = 0; i < NO_OF_RBUF; i++) {
                    441: 
                    442:         if (pgms[i][0] == 0) {
                    443:             altern = i;
                    444:             break;
                    445:         }                              /* buffer empty */
                    446:         
                    447:         j = 0;
                    448:         
                    449:         while (rou[j] == pgms[i][j]) {
                    450: 
                    451:             if (rou[j++] == EOL) {
                    452:                 
                    453:                 rouptr = buff + (i * PSIZE0);
                    454:                 ages[i] = time (0L);
                    455:                 rouend = ends[i];
                    456:                 rouins = rouend - 1;
                    457:                 
                    458:                 return;
                    459: 
                    460:             }
                    461: 
                    462:         }
                    463: 
                    464:         if (ages[i] <= timex) timex = ages[altern = i];
                    465: 
                    466:     }
                    467: 
                    468:     /* clear DO-label stored under FOR */
                    469:     dosave[0] = 0;
                    470:     j = 0;
                    471:     ch = EOL;                          /* init for multiple path search */
                    472:     tmp1[0] = EOL;
                    473: 
                    474: 
                    475: nextpath:                              /* entry point for retry */
                    476: 
                    477:     i = 0;
                    478:     
                    479:     if (rou[0] == '%') {               /* %_routines are in special directory */
                    480:         
                    481:         if (mcmnd >= 'a') {            /* DO GOTO JOB */
                    482:             
                    483:             if (rou0plib[j] != EOL) {
                    484:                 while ((ch = pgm[i++] = rou0plib[j++]) != ':' && ch != EOL);
                    485:             }
                    486: 
                    487:         } 
                    488:         else if (rou1plib[j] != EOL) {
                    489:             while ((ch = pgm[i++] = rou1plib[j++]) != ':' && ch != EOL);
                    490:         }
                    491: 
                    492:     } 
                    493:     else {
                    494: 
                    495:         if (mcmnd >= 'a') {            /* DO GOTO JOB */
                    496: 
                    497:             if (rou0path[j] != EOL) {
                    498:                 while ((ch = pgm[i++] = rou0path[j++]) != ':' && ch != EOL);
                    499:             }
                    500: 
                    501:         } 
                    502:         else if (rou1path[j] != EOL) {
                    503:             while ((ch = pgm[i++] = rou1path[j++]) != ':' && ch != EOL);
                    504:         }
                    505: 
                    506:     }
                    507: 
                    508:     if (i > 0) {
                    509: 
                    510:         if (i == 1 || (i == 2 && pgm[0] == '.'))  {
                    511:             i = 0;
                    512:         }
                    513:         else {
                    514:             pgm[i - 1] = '/';
                    515:         }
                    516: 
                    517:     }
                    518:     
                    519:     pgm[i] = EOL;
                    520:     
                    521:     stcpy (tmp1, pgm);                 /* directory where we search for the routine */
                    522:     stcpy (&pgm[i], rou);
                    523:     
                    524:     rouptr = buff + (altern * PSIZE0);
                    525:     
                    526:     stcat (pgm, rou_ext);
                    527:     
                    528:     pgm[stlen (pgm)] = NUL;            /* append routine extension */
                    529: 
                    530:     if ((infile = fopen (pgm, "r")) == NULL) {
                    531:     
                    532:         rouptr = savptr;
                    533:     
                    534:         if (ch != EOL) goto nextpath;          /* try next access path */
                    535:     
                    536:         stcpy (varerr, rou);
                    537:     
                    538:         merr_raise (NOPGM);
                    539:         
                    540:         return;
                    541:     
                    542:     }
                    543:     
                    544: again:
                    545:     
                    546:     linelen = 0;
                    547:     savptr = rouend = rouptr;
                    548:     
                    549:     for (i = 1; i < (PSIZE0 - 1); i++) {
                    550:     
                    551:         *++rouend = ch = getc (infile);
                    552:     
                    553:         if (ch == LF || ch == EOF) {
                    554:             
                    555:             *rouend++ = EOL;
                    556:             i++;
                    557:             *savptr = i - linelen - 2;
                    558: 
                    559:             savptr = rouend;
                    560:             linelen = i;
                    561:             
                    562:             if (ch == EOF) {
                    563:     
                    564:                 fclose (infile);
                    565:     
                    566:                 *rouend-- = EOL;
                    567:                 rouins = rouend - 1;
                    568:                 ends[altern] = rouend;
                    569:                 ages[altern] = time (0L);
                    570:                 
                    571:                 stcpy (pgms[altern], rou);
                    572:                 stcpy (path[altern], tmp1);
                    573: 
                    574:                 rbuf_flags[altern].dialect = standard;
                    575:                 if (standard == D_FREEM) {
                    576:                     rbuf_flags[altern].standard = FALSE;
                    577:                 }
                    578:                 else {
                    579:                     rbuf_flags[altern].standard = TRUE;
                    580:                 }
                    581:                 
                    582:                 return;
                    583:             }
                    584:         }
                    585:     }
                    586: 
                    587:     rouptr = savptr;
                    588:     
                    589:     if (autorsize) {
                    590:         
                    591:         while ((ch = getc (infile)) != EOF) {
                    592:             
                    593:             i++;
                    594:     
                    595:             if (ch == LF) i++;
                    596:     
                    597:         }                              /* how big? */
                    598:     
                    599:         i = ((i + 3) & ~01777) + 02000;        /* round for full kB; */
                    600:     
                    601:         if (newrsize (i, NO_OF_RBUF) == 0) {   /* try to get more routine space. */
                    602:     
                    603:             altern = 0;
                    604:             ch = EOL;
                    605:     
                    606:             fseek (infile, 0L, 0);
                    607:     
                    608:             goto again;
                    609:         
                    610:         }
                    611: 
                    612:     }
                    613:     
                    614:     fclose (infile);
                    615:     
                    616:     goto pgmov;
                    617:     
                    618: pgmov:
                    619: 
                    620:     /* program overflow error */
                    621:     rouptr = rouins = rouend = savptr;
                    622:     (*savptr++) = EOL;
                    623:     *savptr = EOL;
                    624: 
                    625:     for (i = 0; i < NO_OF_RBUF; i++) {
                    626:         ages[i] = 0;
                    627:         pgms[i][0] = 0;
                    628:     }
                    629: 
                    630:     pgms[i][0] = EOL;
                    631:     rou_name[0] = EOL;
                    632:     merr_raise (PGMOV);
                    633: 
                    634:     return;
                    635: 
                    636: }                                      /* end of zload() */
                    637: 
                    638: void zsave (char *rou)                         /* save routine on disk */
                    639: {
                    640:     register int i;
                    641:     register int j;
                    642:     register int ch;
                    643:     char tmp[256];
                    644: 
                    645:     stcpy (tmp, rou);                  /* save name without path */
                    646: 
                    647:     /* look whether we know where the routine came from */
                    648: 
                    649:     if (zsavestrategy) {               /* VIEW 133: remember ZLOAD directory on ZSAVE */
                    650:         
                    651:         for (i = 0; i < NO_OF_RBUF; i++) {
                    652: 
                    653:             if (pgms[i][0] == 0) break;                        /* buffer empty */
                    654:             
                    655:             j = 0;
                    656:             
                    657:             while (rou[j] == pgms[i][j]) {
                    658:                 
                    659:                 if (rou[j++] == EOL) {
                    660:                     
                    661:                     stcpy (rou, path[i]);
                    662:                     stcat (rou, tmp);
                    663:             
                    664:                     j = 0;
                    665:                     ch = 1;            /* init for multiple path search */
                    666:                     
                    667:                     goto try;
                    668:             
                    669:                 }
                    670:             
                    671:             }
                    672:         
                    673:         }
                    674: 
                    675:     }
                    676: 
                    677:     /* not found */
                    678:     j = 0;
                    679:     ch = EOL;                          /* init for multiple path search */
                    680: 
                    681: 
                    682: nextpath:                              /* entry point for retry */
                    683:     
                    684:     if (tmp[0] == '%') {
                    685:         
                    686:         if (rou1plib[0] != EOL) {
                    687: 
                    688:             i = 0;
                    689:             
                    690:             while ((ch = rou[i++] = rou1plib[j++]) != ':' && ch != EOL);
                    691:             
                    692:             if (i == 1 || (i == 2 && rou[0] == '.')) {
                    693:                 i = 0;
                    694:             }
                    695:             else {
                    696:                 rou[i - 1] = '/';
                    697:             }
                    698:             
                    699:             stcpy (&rou[i], tmp);
                    700: 
                    701:         }
                    702: 
                    703:     } 
                    704:     else {
                    705:     
                    706:         if (rou1path[0] != EOL) {
                    707: 
                    708:             i = 0;
                    709:             
                    710:             while ((ch = rou[i++] = rou1path[j++]) != ':' && ch != EOL);
                    711:             
                    712:             if (i == 1 || (i == 2 && rou[0] == '.')) {
                    713:                 i = 0;
                    714:             }
                    715:             else {
                    716:                 rou[i - 1] = '/';
                    717:             }
                    718:             
                    719:             stcpy (&rou[i], tmp);
                    720: 
                    721:         }
                    722: 
                    723:     }
                    724: 
                    725: 
                    726: try:
                    727: 
                    728:     stcat (rou, rou_ext);
                    729:     rou[stlen (rou)] = NUL;            /* append routine extention */
                    730: 
                    731:     if (rouend <= rouptr) {
                    732:         unlink (rou);
                    733:         rou_name[0] = EOL;
                    734:     } 
                    735:     else {
                    736:         FILE *outfile;
                    737:         char *i0;
                    738: 
                    739:         for (;;) {
                    740: 
                    741:             errno = 0;
                    742:             
                    743:             if ((outfile = fopen (rou, "w")) != NULL) break;
                    744:             
                    745:             if (errno == EINTR) continue;              /* interrupt */
                    746:             
                    747:             if (errno == EMFILE || errno == ENFILE) {
                    748:                 close_all_globals ();
                    749:                 continue;
                    750:             }                          /* free file_des */
                    751:             
                    752:             if (ch != EOL) goto nextpath;              /* try next access path */
                    753:             
                    754:             merr_raise (PROTECT);
                    755:             return;
                    756:             
                    757:         }
                    758:         
                    759:         i0 = rouptr;
                    760:         
                    761:         while (++i0 < (rouend - 1)) {
                    762:             
                    763:             if ((ch = (*(i0))) == EOL) {
                    764:                 ch = LF;
                    765:                 i0++;
                    766:             }
                    767:             
                    768:             putc (ch, outfile);
                    769:             
                    770:         }
                    771:         
                    772:         if (ch != LF) putc (LF, outfile);
                    773:         
                    774:         fclose (outfile);
                    775:         
                    776:     }
                    777: 
                    778:     return;
                    779: 
                    780: }                                      /* end of zsave() */
                    781: 
                    782: /* insert 'line' in routine at 'position' */
                    783: void zi (char *line, char *position)                   
                    784: {
                    785:     short offset;
                    786:     short label;
                    787:     short i;
                    788:     short i0;
                    789:     short ch;
                    790:     char *reg;
                    791:     char *end;
                    792:     char line0[256];
                    793: 
                    794:     if (rouend - rouptr + stlen (line) + 1 > PSIZE0) { /* sufficient space ??? */
                    795:         
                    796:         reg = buff;
                    797:         
                    798:         if (getrmore () == 0L) return;                 /* PGMOV */
                    799:         
                    800:         position += buff - reg;
                    801: 
                    802:     }
                    803: 
                    804:     label = TRUE;
                    805:     i = 0;
                    806:     i0 = 0;
                    807:     
                    808:     while ((ch = line[i]) != EOL) {
                    809: 
                    810:         if (label) {
                    811:             
                    812:             if (ch == SP) ch = TAB;
                    813:             
                    814:             if (ch == TAB) {
                    815:                 label = FALSE;
                    816:             }
                    817:             else if (ch == '(') {
                    818:                 
                    819:                 line0[i0++] = ch;
                    820:                 i++;
                    821:                 
                    822:                 while (((ch = line[i]) >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '%' || ch == ',') {
                    823:                     line0[i0++] = ch;
                    824:                     i++;
                    825:                 }
                    826: 
                    827:                 if (ch != ')') {
                    828:                     merr_raise (ISYNTX);
                    829:                     return;
                    830:                 }
                    831: 
                    832:                 line0[i0++] = ch;
                    833:                 i++;
                    834:                 
                    835:                 if ((ch = line[i]) != SP && ch != TAB) {
                    836:                     merr_raise (ISYNTX);
                    837:                     return;
                    838:                 }
                    839: 
                    840:                 continue;
                    841: 
                    842:             } 
                    843:             else if ((ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z') && (ch < '0' || ch > '9') && (ch != '%' || i)) {
                    844:                 merr_raise (ISYNTX);
                    845:                 return;
                    846:             }
                    847: 
                    848:             line0[i0++] = ch;
                    849:             i++;
                    850:             
                    851:             continue;
                    852: 
                    853:         }
                    854: 
                    855:         if (ch < SP || (ch >= DEL && (eightbit == FALSE))) {
                    856:             merr_raise (ISYNTX);
                    857:             return;
                    858:         }
                    859: 
                    860:         line0[i0++] = ch;
                    861:         i++;
                    862: 
                    863:     }
                    864: 
                    865:     if (label) {
                    866:         merr_raise (ISYNTX);
                    867:         return;
                    868:     }
                    869:     
                    870:     line0[i0] = EOL;
                    871:     offset = i0;
                    872:     
                    873:     if (offset > 0) {
                    874: 
                    875:         offset += 2;
                    876:         end = rouend;
                    877:         rouend += offset;
                    878:         
                    879:         if (roucur > position || roucur > end) roucur += offset;
                    880:         
                    881:         reg = rouend;
                    882:         
                    883:         while (position <= end) {
                    884:             (*reg--) = (*end--);
                    885:         }
                    886: 
                    887:         (*(position++)) = (UNSIGN (offset) - 2);
                    888:         
                    889:         reg = line0;
                    890:         
                    891:         while (((*(position++)) = (*(reg++))) != EOL);
                    892:         
                    893:         *(rouend + 1) = EOL;
                    894:         *(rouend + 2) = EOL;
                    895:         
                    896:         for (i = 0; i < NO_OF_RBUF; i++) {
                    897:             
                    898:             if (rouptr == (buff + (i * PSIZE0))) {
                    899:                 ends[i] = rouend;
                    900:                 break;
                    901:             }
                    902: 
                    903:         }
                    904: 
                    905:     }
                    906: 
                    907:     rouins = position;
                    908:     
                    909:     return;
                    910: }                                      /* end of zi() */
                    911: 
                    912: /*
                    913:  * getraddress(char *a, short lvl):
                    914:  *
                    915:  *     returns the 'canonical' address of the line at the specified DO/FOR/XEC level
                    916:  *     
                    917:  *     char *a (out param):    pointer to the address of the line
                    918:  *     short lvl:                              process this level           
                    919:  *
                    920:  */
                    921: void getraddress (char *a, short lvl)                  
                    922: {
                    923: 
                    924:     char *rcur;                        /* cursor into routine         */
                    925:     short f;
                    926:     char tmp3[256];
                    927:     char *j0;
                    928:     char *j1;
                    929:     short rlvl;                        /* lower level, where to find routine name */
                    930:     register int i;
                    931:     register int j;
                    932: 
                    933:     f = mcmnd;
                    934:     mcmnd = 'd';                       /* make load use standard-path */
                    935:     rlvl = lvl;
                    936: 
                    937:     if (nestn[rlvl] == 0 && rlvl < nstx) rlvl++;
                    938: 
                    939:     if (nestn[rlvl]) zload (nestn[rlvl]);
                    940: 
                    941:     mcmnd = f;
                    942: 
                    943:     /* command on stack: 2 == DO_BLOCK; other: make uppercase */
                    944:     i = nestc[lvl];
                    945: 
                    946:     if (i != '$') i = ((i == 2) ? 'd' : i - 32);
                    947: 
                    948:     a[0] = '(';
                    949:     a[1] = i;
                    950:     a[2] = ')';
                    951:     a[3] = EOL;                                /* command */
                    952: 
                    953:     rcur = nestr[lvl] + rouptr;                /* restore rcur */
                    954:     j0 = (rouptr - 1);
                    955:     j = 0;
                    956:     tmp3[0] = EOL;
                    957: 
                    958:     j0++;
                    959: 
                    960:     if (rcur < rouend) {
                    961: 
                    962:         while (j0 < (rcur - 1)) {
                    963: 
                    964:             j1 = j0++;
                    965:             j++;
                    966: 
                    967:             if ((*j0 != TAB) && (*j0 != SP)) {
                    968: 
                    969:                 j = 0;
                    970: 
                    971:                 while ((tmp3[j] = (*(j0++))) > SP) {
                    972: 
                    973:                     if (tmp3[j] == '(') tmp3[j] = EOL;
                    974: 
                    975:                     j++;
                    976: 
                    977:                 }
                    978: 
                    979:                 tmp3[j] = EOL;
                    980:                 j = 0;
                    981: 
                    982:             }
                    983: 
                    984:             j0 = j1;
                    985:             j0 += (UNSIGN (*j1)) + 2;
                    986: 
                    987:         }
                    988: 
                    989:     }
                    990: 
                    991:     stcat (a, tmp3);
                    992: 
                    993:     if (j > 0) {
                    994: 
                    995:         i = stlen (a);
                    996:         a[i++] = '+';
                    997: 
                    998:         intstr (&a[i], j);
                    999: 
                   1000:     }
                   1001: 
                   1002:     if (nestn[rlvl]) {
                   1003: 
                   1004:         stcat (a, "^\201");
                   1005:         stcat (a, nestn[rlvl]);
                   1006: 
                   1007:     } 
                   1008:     else if (rou_name[0] != EOL) {
                   1009: 
                   1010:         stcat (a, "^\201");
                   1011:         stcat (a, rou_name);
                   1012: 
                   1013:     }
                   1014: 
                   1015:     f = mcmnd;
                   1016:     mcmnd = 'd';                       /* make load use standard-path */
                   1017: 
                   1018:     zload (rou_name);
                   1019: 
                   1020:     mcmnd = f;
                   1021: 
                   1022:     return;
                   1023: 
                   1024: }                                      /* end getraddress() */
                   1025: 
                   1026: /* parse lineref and return pos.in routine */
                   1027: /* result: [pointer to] pointer to line */
                   1028: void lineref (char **adrr)                             
                   1029: {
                   1030:     long offset;
                   1031:     long j;
                   1032:     char *reg;
                   1033:     char *beg;
                   1034: 
                   1035:     while (*codptr == '@') {           /* handle indirection */
                   1036:         
                   1037:         codptr++;
                   1038:         
                   1039:         expr (ARGIND);
                   1040:         
                   1041:         if (merr () > 0) return;
                   1042:         
                   1043:         stcat (argptr, codptr);
                   1044:         stcpy (code, argptr);
                   1045:         
                   1046:         codptr = code;
                   1047: 
                   1048:     }
                   1049: 
                   1050:     offset = 0;
                   1051:     beg = rouptr;
                   1052: 
                   1053:     if (*codptr == '+') {
                   1054: 
                   1055:         codptr++;
                   1056:         
                   1057:         expr (STRING);
                   1058:         
                   1059:         if (merr () > 0) return;
                   1060: 
                   1061:         if ((offset = intexpr (argptr)) <= 0) {
                   1062:             *adrr = 0;
                   1063:             return;
                   1064:         }
                   1065:         
                   1066:         offset--;
                   1067:     
                   1068:     } 
                   1069:     else {
                   1070:         
                   1071:         expr (LABEL);
                   1072:         
                   1073:         if (merr () > 0) return;
                   1074:         
                   1075:         reg = beg;
                   1076:         
                   1077:         while (beg < rouend) {
                   1078: 
                   1079:             reg++;
                   1080:             
                   1081:             if ((*reg) != TAB && (*reg) != SP) {
                   1082:                 
                   1083:                 j = 0;
                   1084:             
                   1085:                 while ((*reg) == varnam[j]) {
                   1086:                     reg++;
                   1087:                     j++;
                   1088:                 }
                   1089:                 
                   1090:                 if (((*reg) == TAB || (*reg) == SP || (*reg) == '(') && varnam[j] == EOL) break;
                   1091:             
                   1092:             }
                   1093:             
                   1094:             reg = (beg = beg + UNSIGN (*beg) + 2);
                   1095: 
                   1096:         }
                   1097: 
                   1098:         stcpy (varerr, varnam);
                   1099:         
                   1100:         varnam[0] = EOL;
                   1101:         codptr++;
                   1102:         
                   1103:         if (*codptr == '+') {
                   1104:             
                   1105:             codptr++;
                   1106:             
                   1107:             expr (STRING);
                   1108:         
                   1109:             if (merr () > 0) return;
                   1110:         
                   1111:             offset = intexpr (argptr);
                   1112:         
                   1113:         }
                   1114: 
                   1115:     }
                   1116:     
                   1117:     if (offset < 0) {
                   1118: 
                   1119:         reg = rouptr;
                   1120:         
                   1121:         while (reg < beg) {
                   1122:             reg += UNSIGN (*reg) + 2;
                   1123:             offset++;
                   1124:         }
                   1125: 
                   1126:         if (offset < 0) {
                   1127:             *adrr = 0;
                   1128:             return;
                   1129:         }
                   1130: 
                   1131:         beg = rouptr;
                   1132: 
                   1133:     }
                   1134: 
                   1135:     while (offset-- > 0 && beg <= rouend) beg += UNSIGN (*beg) + 2;
                   1136:     
                   1137:     *adrr = beg;
                   1138:     
                   1139:     return;
                   1140: }                                      /* end of lineref() */

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