Annotation of freem/src/routine.c, revision 1.1.1.1
1.1 snw 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>