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

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

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