File:  [Coherent Logic Development] / freem / src / routine.c
Revision 1.1: download - view: text, annotated - select for diffs
Sun Jan 19 02:04:04 2025 UTC (14 months, 2 weeks ago) by snw
Branches: MAIN
CVS tags: HEAD
Initial revision

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

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