|
|
1.1 root 1: /*
2: * File: rconv.c
3: * Contents: ctype, cvcset, cvint, cvnum, cvpos, cvreal, cvstr, gcvt, mkint,
4: * mkreal, mksubs, strprc
5: */
6:
7: #include "../h/rt.h"
8: #include <math.h>
9:
10: /*
11: * Structure for mapping string names of procedures to block addresses.
12: */
13: struct pstrnm {
14: char *pstrep;
15: struct b_proc *pblock;
16: };
17:
18: extern struct b_proc
19: #define FncDef(p) Cat(B,p),
20: #include "../h/fdef.h"
21: Bnoproc; /* Hack to avoid ,; in expansion */
22: #undef FncDef
23:
24: extern struct b_proc
25: Basgn,
26: Bbang,
27: Bcat,
28: Bcompl,
29: Bdiff,
30: Bdiv,
31: Beqv,
32: Binter,
33: Blconcat,
34: Blexeq,
35: Blexge,
36: Blexgt,
37: Blexle,
38: Blexlt,
39: Blexne,
40: Bminus,
41: Bmod,
42: Bmult,
43: Bneg,
44: Bneqv,
45: Bnonnull,
46: Bnull,
47: Bnumber,
48: Bnumeq,
49: Bnumge,
50: Bnumgt,
51: Bnumle,
52: Bnumlt,
53: Bnumne,
54: Bplus,
55: Bpower,
56: Brandom,
57: Brasgn,
58: Brefresh,
59: Brswap,
60: Bsect,
61: Bsize,
62: Bsubsc,
63: Bswap,
64: Btabmat,
65: Btoby,
66: Bunions,
67: Bvalue;
68:
69: struct pstrnm pntab[] = {
70: #define FncDef(p) "p", Cat(&B,p),
71: #include "../h/fdef.h"
72: #undef FncDef
73: ":=", &Basgn,
74: "!", &Bbang,
75: "||", &Bcat,
76: "~", &Bcompl,
77: "--", &Bdiff,
78: "/", &Bdiv,
79: "===", &Beqv,
80: "**", &Binter,
81: "|||", &Blconcat,
82: "==", &Blexeq,
83: ">>=", &Blexge,
84: ">>", &Blexgt,
85: "<<=", &Blexle,
86: "<<", &Blexlt,
87: "~==", &Blexne,
88: "-", &Bminus,
89: "%", &Bmod,
90: "*", &Bmult,
91: "-", &Bneg,
92: "~===", &Bneqv,
93: "\\", &Bnonnull,
94: "/", &Bnull,
95: "+", &Bnumber,
96: "=", &Bnumeq,
97: ">=", &Bnumge,
98: ">", &Bnumgt,
99: "<=", &Bnumle,
100: "<", &Bnumlt,
101: "~=", &Bnumne,
102: "+", &Bplus,
103: "^", &Bpower,
104: "?", &Brandom,
105: "<-", &Brasgn,
106: "^", &Brefresh,
107: "<->", &Brswap,
108: ":", &Bsect,
109: "*", &Bsize,
110: "[]", &Bsubsc,
111: ":=:", &Bswap,
112: "=", &Btabmat,
113: "...", &Btoby,
114: "++", &Bunions,
115: ".", &Bvalue,
116: 0, 0
117: };
118:
119: /*
120: * The array is used to establish a "type" for a character. The
121: * codes in use are:
122: * C - control character
123: * H - hexadecimal digit
124: * L - lower case alphabetic
125: * N - decimal digit
126: * P - punctuation
127: * S - whitespace
128: * U - upper case alphabetic
129: *
130: * Note that logical or'ing is used to associate more than one attribute
131: * with a character.
132: */
133:
134: /*
135: * Macros for determining character type.
136: *
137: * The table cytpe classifies each character
138: * in one of the categories defined below.
139: */
140:
141: #define _U 01 /* upper case */
142: #define _L 02 /* lower case */
143: #define _N 04 /* digit */
144: #define _S 010 /* space */
145: #define _P 020 /* punctuation */
146: #define _C 040 /* control */
147: #define _X 0100 /* hex digit (a-f) */
148:
149: #define isalpha(c) (ctype[(c)&0377]&(_U|_L))
150: #define isupper(c) (ctype[(c)&0377]&_U)
151: #define islower(c) (ctype[(c)&0377]&_L)
152: #define isdigit(c) (ctype[(c)&0377]&_N)
153: #define isxdigit(c) (ctype[(c)&0377]&(_N|_X))
154: #define isspace(c) (ctype[(c)&0377]&_S)
155: #define ispunct(c) (ctype[(c)&0377]&_P)
156: #define isalnum(c) (ctype[(c)&0377]&(_U|_L|_N))
157: #define isprint(c) (ctype[(c)&0377]&(_P|_U|_L|_N))
158: #define iscntrl(c) (ctype[(c)&0377]&_C)
159: #define isascii(c) ((unsigned)(c)<=0177)
160: #define toupper(c) (((c)&0377)-'a'+'A')
161: #define tolower(c) (((c)&0377)-'A'+'a')
162: #define toascii(c) (((c)&0177)
163: #define tonum(c) (isdigit(c)?(c)-'0':10+(((c)|(040))-'a'))
164:
165: char ctype[] = {
166: _C, _C, _C, _C, _C, _C, _C, _C,
167: _C, _S, _S, _S, _S, _S, _C, _C,
168: _C, _C, _C, _C, _C, _C, _C, _C,
169: _C, _C, _C, _C, _C, _C, _C, _C,
170: _S, _P, _P, _P, _P, _P, _P, _P,
171: _P, _P, _P, _P, _P, _P, _P, _P,
172: _N, _N, _N, _N, _N, _N, _N, _N,
173: _N, _N, _P, _P, _P, _P, _P, _P,
174: _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U,
175: _U, _U, _U, _U, _U, _U, _U, _U,
176: _U, _U, _U, _U, _U, _U, _U, _U,
177: _U, _U, _U, _P, _P, _P, _P, _P,
178: _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L,
179: _L, _L, _L, _L, _L, _L, _L, _L,
180: _L, _L, _L, _L, _L, _L, _L, _L,
181: _L, _L, _L, _P, _P, _P, _P, _C,
182: 0, 0, 0, 0, 0, 0, 0, 0,
183: 0, 0, 0, 0, 0, 0, 0, 0,
184: 0, 0, 0, 0, 0, 0, 0, 0,
185: 0, 0, 0, 0, 0, 0, 0, 0,
186: 0, 0, 0, 0, 0, 0, 0, 0,
187: 0, 0, 0, 0, 0, 0, 0, 0,
188: 0, 0, 0, 0, 0, 0, 0, 0,
189: 0, 0, 0, 0, 0, 0, 0, 0,
190: 0, 0, 0, 0, 0, 0, 0, 0,
191: 0, 0, 0, 0, 0, 0, 0, 0,
192: 0, 0, 0, 0, 0, 0, 0, 0,
193: 0, 0, 0, 0, 0, 0, 0, 0,
194: 0, 0, 0, 0, 0, 0, 0, 0,
195: 0, 0, 0, 0, 0, 0, 0, 0,
196: 0, 0, 0, 0, 0, 0, 0, 0,
197: 0, 0, 0, 0, 0, 0, 0, 0
198: };
199: /*
200: * cvcset(d, cs, csbuf) - convert d to a cset and
201: * make cs point to it, using csbuf as a buffer if necessary.
202: */
203:
204: cvcset(d, cs, csbuf)
205: register struct descrip *d;
206: int **cs, *csbuf;
207: {
208: register char *s;
209: register word l;
210: char sbuf[MaxCvtLen];
211:
212: Inc(cv_n_cset);
213:
214:
215: if (!Qual(*d) && (d)->dword == D_Cset) {
216: Inc(cv_n_rcset);
217: *cs = BlkLoc(*d)->cset.bits;
218: return T_Cset;
219: }
220:
221: if (cvstr(d, sbuf) == NULL)
222: return NULL;
223:
224: for (l = 0; l < CsetSize; l++)
225: csbuf[l] = 0;
226:
227: s = StrLoc(*d);
228: l = StrLen(*d);
229: while (l--) {
230: Setb(*s, csbuf);
231: s++;
232: }
233: *cs = csbuf;
234: return 1;
235: }
236:
237:
238: /*
239: * cvint - convert the value represented by dp into an integer and write
240: * the value into the location referenced by i. cvint returns Integer or
241: * NULL depending on the outcome of the conversion.
242: */
243:
244: cvint(dp, i)
245: register struct descrip *dp;
246: long *i;
247: {
248: union numeric result;
249: int minsh, maxsh;
250:
251: minsh = MinShort;
252: maxsh = MaxShort;
253:
254: #ifdef RunStats
255: Inc(cv_n_int);
256: if (!Qual(*dp) && (dp)->dword == D_Integer)
257: cv_n_rint++;
258: #endif RunStats
259: /*
260: * Use cvnum to attempt the conversion into "result".
261: */
262: switch (cvnum(dp, &result)) {
263:
264: case T_Integer:
265: *i = result.integer;
266: return T_Integer;
267:
268: case T_Longint:
269: *i = result.integer;
270: return T_Longint;
271:
272: case T_Real:
273: /*
274: * The value converted into a real number. If it's not in the
275: * range of an integer, return a 0, otherwise convert the
276: * real value into an integer. As before, distinguish between
277: * integers and long integers if necessary.
278: */
279: if (result.real > MaxLong || result.real < MinLong)
280: return NULL;
281: *i = (long)result.real;
282: #if IntSize == 16
283: if (*i < (long)minsh || *i > (long)maxsh)
284: return T_Longint;
285: #endif IntSize == 16
286: return T_Integer;
287:
288: default:
289: return NULL;
290: }
291: }
292:
293:
294: /*
295: * cvnum - convert the value represented by d into a numeric quantity and
296: * place the value into *result. Value returned is Integer, D_Real, or
297: * NULL.
298: */
299:
300: /* >cvnum */
301: cvnum(dp,result)
302: register struct descrip *dp;
303: union numeric *result;
304: {
305: static char sbuf[MaxCvtLen];
306:
307: Inc(cv_n_num);
308: if (Qual(*dp)) {
309: qtos(dp, sbuf);
310: return ston(sbuf, result);
311: }
312:
313: switch (Type(*dp)) {
314:
315: case T_Integer:
316: Inc(cv_n_rnum);
317: result->integer = (long)IntVal(*dp);
318: return T_Integer;
319:
320: case T_Longint:
321: Inc(cv_n_rnum);
322: result->integer = BlkLoc(*dp)->longint.intval;
323: return T_Longint;
324:
325: case T_Real:
326: Inc(cv_n_rnum);
327: GetReal(dp,result->real);
328: return T_Real;
329:
330: default:
331: /*
332: * Try to convert the value to a string and
333: * then try to convert the string to an integer.
334: */
335: if (cvstr(dp, sbuf) == NULL)
336: return NULL;
337: return ston(StrLoc(*dp), result);
338: }
339: }
340: /* <cvnum */
341:
342: #define BIG 72057594037927936. /* numbers larger than 2^56 lose precision */
343:
344: /*
345: * ston - convert a string to a numeric quantity if possible.
346: */
347: static ston(s, result)
348: register char *s;
349: union numeric *result;
350: {
351: register int c;
352: int realflag = 0; /* indicates a real number */
353: char msign = '+'; /* sign of mantissa */
354: char esign = '+'; /* sign of exponent */
355: double mantissa = 0; /* scaled mantissa with no fractional part */
356: int scale = 0; /* number of decimal places to shift mantissa */
357: int digits = 0; /* total number of digits seen */
358: int sdigits = 0; /* number of significant digits seen */
359: int exponent = 0; /* exponent part of real number */
360: double fiveto; /* holds 5^scale */
361: double power; /* holds successive squares of 5 to compute fiveto */
362: int minsh, maxsh;
363: #ifndef VMS
364: extern int errno;
365: #else VMS
366: #include <errno.h>
367: #endif
368:
369: minsh = MinShort;
370: maxsh = MaxShort;
371:
372: c = *s++;
373:
374: /*
375: * Skip leading white space.
376: */
377: while (isspace(c))
378: c = *s++;
379:
380: /*
381: * Check for sign.
382: */
383: if (c == '+' || c == '-') {
384: msign = c;
385: c = *s++;
386: }
387:
388: /*
389: * Get integer part of mantissa.
390: */
391: while (isdigit(c)) {
392: digits++;
393: if (mantissa < BIG) {
394: mantissa = mantissa * 10 + (c - '0');
395: if (mantissa > 0.0)
396: sdigits++;
397: }
398: else
399: scale++;
400: c = *s++;
401: }
402:
403: /*
404: * Check for based integer.
405: */
406: if (c == 'r' || c == 'R')
407: return radix(msign, (int)mantissa, s, result);
408:
409: /*
410: * Get fractional part of mantissa.
411: */
412: if (c == '.') {
413: realflag++;
414: c = *s++;
415: while (isdigit(c)) {
416: digits++;
417: if (mantissa < BIG) {
418: mantissa = mantissa * 10 + (c - '0');
419: scale--;
420: if (mantissa > 0.0)
421: sdigits++;
422: }
423: c = *s++;
424: }
425: }
426:
427: /*
428: * Check that at least one digit has been seen so far.
429: */
430: if (digits == 0)
431: return NULL;
432:
433: /*
434: * Get exponent part.
435: */
436: if (c == 'e' || c == 'E') {
437: realflag++;
438: c = *s++;
439: if (c == '+' || c == '-') {
440: esign = c;
441: c = *s++;
442: }
443: if (!isdigit(c))
444: return NULL;
445: while (isdigit(c)) {
446: exponent = exponent * 10 + (c - '0');
447: c = *s++;
448: }
449: scale += (esign == '+')? exponent : -exponent;
450: }
451:
452: /*
453: * Skip trailing white space.
454: */
455: while (isspace(c))
456: c = *s++;
457:
458: /*
459: * Check that entire string has been consumed.
460: */
461: if (c != '\0')
462: return NULL;
463:
464: /*
465: * Test for integer.
466: */
467: if (!realflag && mantissa >= MinLong && mantissa <= MaxLong) {
468: result->integer = (msign == '+')? mantissa : -mantissa;
469: #if IntSize == 16
470: if (result->integer < (long)minsh || result->integer > (long)maxsh)
471: return T_Longint;
472: #endif IntSize == 16
473: return T_Integer;
474: }
475:
476: /*
477: * Rough tests for overflow and underflow.
478: */
479: if (sdigits + scale > LogHuge)
480: return NULL;
481:
482: if (sdigits + scale < -LogHuge) {
483: result->real = 0.0;
484: return T_Real;
485: }
486:
487: /*
488: * Put the number together by multiplying the mantissa by 5^scale and
489: * then using ldexp() to multiply by 2^scale.
490: */
491:
492: #ifdef PDP11
493: /*
494: * Load floating point status register on PDP-11.
495: */
496: ldfps(0200);
497: #endif PDP11
498: exponent = (scale > 0)? scale : -scale;
499: fiveto = 1.0;
500: power = 5.0;
501: for (;;) {
502: if (exponent & 01)
503: fiveto *= power;
504: exponent >>= 1;
505: if (exponent == 0)
506: break;
507: power *= power;
508: }
509: if (scale > 0)
510: mantissa *= fiveto;
511: else
512: mantissa /= fiveto;
513:
514: errno = 0;
515: mantissa = ldexp(mantissa, scale);
516: #ifdef PDP11
517: /*
518: * Load floating point status register on PDP-11
519: */
520: ldfps(03200);
521: #endif PDP11
522: if (errno > 0 && mantissa > 0)
523: /*
524: * ldexp caused overflow.
525: */
526: return NULL;
527:
528: result->real = (msign == '+')? mantissa : -mantissa;
529: return T_Real;
530: }
531:
532: /*
533: * radix - convert string s in radix r into an integer in *result. sign
534: * will be either '+' or '-'.
535: */
536: static radix(sign, r, s, result)
537: char sign;
538: register int r;
539: register char *s;
540: union numeric *result;
541: {
542: register int c;
543: long num;
544: int minsh, maxsh;
545:
546: minsh = MinShort;
547: maxsh = MaxShort;
548:
549: if (r < 2 || r > 36)
550: return NULL;
551:
552: c = *s++;
553: num = 0L;
554: while (isalnum(c)) {
555: c = tonum(c);
556: if (c >= r)
557: return NULL;
558: num = num * r + c;
559: c = *s++;
560: }
561:
562: while (isspace(c))
563: c = *s++;
564:
565: if (c != '\0')
566: return NULL;
567:
568: result->integer = (sign == '+')? num : -num;
569: if (result->integer < (long)minsh || result->integer > (long)maxsh)
570: return T_Longint;
571: else
572: return T_Integer;
573: }
574:
575:
576: /*
577: * cvpos - convert position to strictly positive position
578: * given length.
579: */
580:
581: word cvpos(pos, len)
582: long pos;
583: register word len;
584: {
585: register word p;
586:
587: /*
588: * Return 0 if the position isn't in the range of an int. (?)
589: */
590: if ((long)(p = pos) != pos)
591: return(0);
592: /*
593: * Return 0 if the position is off either end.
594: */
595: if (p < -len || p > len + 1)
596: return(0);
597: /*
598: * If the position is greater than zero, just return it. Otherwise,
599: * convert the zero/negative position.
600: */
601: if (pos > 0)
602: return p;
603: return (len + p + 1);
604: }
605:
606:
607: /*
608: * cvreal - convert to real and put the result into *r.
609: */
610:
611: cvreal(d, r)
612: register struct descrip *d;
613: double *r;
614: {
615: union numeric result;
616:
617: #ifdef RunStats
618: Inc(cv_n_real);
619: if (!Qual(*d) && (d)->dword == D_Real)
620: cv_n_rreal++;
621: #endif RunStats
622: /*
623: * Use cvnum to classify the value. Cast integers into reals and
624: * fail if the value is non-numeric.
625: */
626: switch (cvnum(d, &result)) {
627:
628: case T_Integer:
629: case T_Longint:
630: *r = result.integer;
631: return T_Real;
632:
633: case T_Real:
634: *r = result.real;
635: return T_Real;
636:
637: default:
638: return NULL;
639: }
640: }
641:
642:
643: /*
644: * cvstr(d,s) - convert d (in place) into a string, using s as buffer
645: * if necessary. cvstr returns 0 if the conversion fails, 1 if d
646: * wasn't a string but was converted into one, and 2 if d was already
647: * a string. When a string conversion takes place, sbuf gets the
648: * resulting string.
649: */
650:
651: /* >cvstr */
652: cvstr(dp, sbuf)
653: register struct descrip *dp;
654: char *sbuf;
655: {
656: double rres;
657:
658: Inc(cv_n_str);
659: if (Qual(*dp)) {
660: Inc(cv_n_rstr);
661: return NoCvt; /* It is already a string */
662: }
663:
664: switch (Type(*dp)) {
665: /*
666: * For types that can be converted into strings, call the
667: * appropriate conversion routine and return its result.
668: * Note that the conversion routines change the descriptor
669: * pointed to by dp.
670: */
671: case T_Integer:
672: return itos((long)IntVal(*dp), dp, sbuf);
673:
674: case T_Longint:
675: return itos(BlkLoc(*dp)->longint.intval, dp, sbuf);
676:
677: case T_Real:
678: GetReal(dp,rres);
679: return rtos(rres, dp, sbuf);
680:
681: case T_Cset:
682: return cstos(BlkLoc(*dp)->cset.bits, dp, sbuf);
683:
684: default:
685: /*
686: * The value cannot be converted to a string.
687: */
688: return NULL;
689: }
690: }
691: /* <cvstr */
692:
693: /*
694: * itos - convert the integer num into a string using s as a buffer and
695: * making q a descriptor for the resulting string.
696: */
697: static itos(num, q, s)
698: long num;
699: struct descrip *q;
700: char *s;
701: {
702: register char *p;
703: long ival;
704:
705: p = s + MaxCvtLen - 1;
706: ival = num;
707:
708: *p = '\0';
709: if (num >= 0L)
710: do {
711: *--p = ival % 10L + '0';
712: ival /= 10L;
713: } while (ival != 0L);
714: else {
715: do {
716: *--p = '0' - (ival % 10L);
717: ival /= 10L;
718: } while (ival != 0L);
719: *--p = '-';
720: }
721:
722: StrLen(*q) = s + MaxCvtLen - 1 - p;
723: StrLoc(*q) = p;
724: return Cvt;
725: }
726:
727: /*
728: * rtos - convert the real number n into a string using s as a buffer and
729: * making q a descriptor for the resulting string.
730: */
731: rtos(n, q, s)
732: double n;
733: struct descrip *q;
734: char *s;
735: {
736: char *gcvt();
737: /*
738: * gcvt does all the work.
739: */
740: gcvt(n, 8, s);
741: StrLen(*q) = strlen(s);
742: StrLoc(*q) = s;
743: return Cvt;
744: }
745:
746: /*
747: * cstos - convert the cset bit array pointed at by cs into a string using
748: * s as a buffer and making q a descriptor for the resulting string.
749: */
750:
751: /* >cstos */
752: static cstos(cs, q, s)
753: int *cs;
754: struct descrip *q;
755: char *s;
756: {
757: register char *p;
758: register int i;
759:
760: p = s;
761: for (i = 0; i < CsetSize * CIntSize; i++) {
762: if (Testb(i, cs))
763: *p++ = (char)i;
764: }
765: *p = '\0';
766:
767: StrLen(*q) = p - s;
768: StrLoc(*q) = s;
769: return Cvt;
770: }
771: /* <cstos */
772:
773:
774: /*
775: * gcvt - Convert number to a string in buf. If possible, ndigit significant
776: * digits are produced, otherwise a form with an exponent is used.
777: */
778: char *ecvt();
779: char *
780: gcvt(number, ndigit, buf)
781: double number;
782: char *buf;
783: {
784: int sign, decpt;
785: register char *p1, *p2;
786: register i;
787:
788:
789: p1 = ecvt(number, ndigit, &decpt, &sign);
790: p2 = buf;
791: if (sign)
792: *p2++ = '-';
793: for (i=ndigit-1; i>0 && p1[i]=='0'; i--)
794: ndigit--;
795: if (decpt >= 0 && decpt-ndigit > 4
796: || decpt < 0 && decpt < -3) { /* use E-style */
797: decpt--;
798: *p2++ = *p1++;
799: *p2++ = '.';
800: for (i=1; i<ndigit; i++)
801: *p2++ = *p1++;
802: *p2++ = 'e';
803: if (decpt<0) {
804: decpt = -decpt;
805: *p2++ = '-';
806: }
807: if (decpt/10 > 0)
808: *p2++ = decpt/10 + '0';
809: *p2++ = decpt%10 + '0';
810: } else {
811: if (decpt<=0) {
812: /* if (*p1!='0') */
813: *p2++ = '0';
814: *p2++ = '.';
815: while (decpt<0) {
816: decpt++;
817: *p2++ = '0';
818: }
819: }
820: for (i=1; i<=ndigit; i++) {
821: *p2++ = *p1++;
822: if (i==decpt)
823: *p2++ = '.';
824: }
825: if (ndigit<decpt) {
826: while (ndigit++<decpt)
827: *p2++ = '0';
828: *p2++ = '.';
829: }
830: }
831: if (p2[-1]=='.')
832: *p2++ = '0';
833: *p2 = '\0';
834: return(buf);
835: }
836:
837:
838: /*
839: * mkint - make an integer descriptor for l in *d. A long integer is used
840: * if the value is too large for a regular integer.
841: */
842:
843: mkint(l, d)
844: long l;
845: register struct descrip *d;
846: {
847: extern struct b_int *alclint();
848: int minsh, maxsh;
849:
850: minsh = MinShort;
851: maxsh = MaxShort;
852:
853: if (l < (long)minsh || l > (long)maxsh) {
854: blkreq(sizeof(struct b_int));
855: d->dword = D_Longint;
856: BlkLoc(*d) = (union block *)alclint(l);
857: }
858: else {
859: d->dword = D_Integer;
860: IntVal(*d) = (word)l;
861: }
862: }
863:
864:
865: /*
866: * mkreal(r, d) - make a real number descriptor and associated block
867: * for r and place it in *d.
868: */
869:
870: mkreal(r, d)
871: double r;
872: register struct descrip *d;
873: {
874: extern struct b_real *alcreal();
875:
876: blkreq((uword)sizeof(struct b_real));
877: d->dword = D_Real;
878: BlkLoc(*d) = (union block *) alcreal(r);
879: }
880:
881:
882: /*
883: * mksubs - form a substring. var is a descriptor for the string from
884: * which the substring is to be formed. var may be a variable. val
885: * is a dereferenced version of val. The descriptor for the resulting
886: * substring is placed in *result. The substring starts at position
887: * i and extends for j characters.
888: */
889:
890: mksubs(var, val, i, j, result)
891: register struct descrip *var, *val, *result;
892: word i, j;
893: {
894: extern struct b_tvsubs *alcsubs();
895:
896: if (Qual(*var) || !Var(*var)) {
897: /*
898: * var isn't a variable, just form a descriptor that points into
899: * the string named by val.
900: */
901: StrLen(*result) = j;
902: StrLoc(*result) = StrLoc(*val) + i - 1;
903: return;
904: }
905:
906: if ((var)->dword == D_Tvsubs) {
907: /*
908: * If var is a substring trapped variable,
909: * adjust the position and make var the substrung string.
910: */
911: i += BlkLoc(*var)->tvsubs.sspos - 1;
912: var = &BlkLoc(*var)->tvsubs.ssvar;
913: }
914:
915: /*
916: * Make a substring trapped variable by passing the buck to alcsubs.
917: */
918: result->dword = D_Tvsubs;
919: BlkLoc(*result) = (union block *) alcsubs(j, i, var);
920: return;
921: }
922:
923:
924: /*
925: * strprc - Convert the qualified string named by *d into a procedure
926: * descriptor if possible. n is the number of arguments that the desired
927: * procedure has. n is only used when the name of the procedure is
928: * non-alphabetic (hence, an operator).
929: * A return value of 1 indicates successful conversion.
930: * 0 indicates that the string could not be converted.
931: */
932: strprc(d,n)
933: struct descrip *d;
934: word n;
935: {
936: extern struct descrip *gnames, *globals, *eglobals;
937: struct descrip *np, *gp;
938: struct pstrnm *p;
939: char *s;
940: word ns, l;
941:
942: /*
943: * Look in global name list first.
944: */
945: np = gnames; gp = globals;
946: while (gp < eglobals) {
947: if (!lexcmp(np++,d))
948: if (BlkLoc(*gp)->proc.title == T_Proc) {
949: StrLen(*d) = D_Proc; /* really type field */
950: BlkLoc(*d) = BlkLoc(*gp);
951: return 1;
952: }
953: gp++;
954: }
955: /*
956: * The name is not a global, see if it is a builtin or an operator.
957: */
958: s = StrLoc(*d);
959: l = StrLen(*d);
960: for (p = pntab; p->pstrep; p++)
961: /*
962: * Compare the desired name with each standard procedure/operator
963: * name.
964: */
965: if (!slcmp(s,l,p->pstrep)) {
966: if (isalpha(*s)) {
967: /*
968: * The names are the same and s starts with an alphabetic,
969: * so it's the one being looked for; return it.
970: */
971: StrLen(*d) = D_Proc;
972: BlkLoc(*d) = (union block *) p->pblock;
973: return 1;
974: }
975: if ((ns = p->pblock->nstatic) < 0)
976: ns = -ns;
977: else
978: ns = p->pblock->nparam;
979: if (n == ns) {
980: StrLen(*d) = D_Proc; /* really type field */
981: BlkLoc(*d) = (union block *) p->pblock;
982: return 1;
983: }
984: }
985: return 0;
986: }
987:
988: /*
989: * slcmp - lexically compare l1 bytes of s1 with null-terminated s2.
990: */
991:
992: slcmp(s1, l1, s2)
993: word l1;
994: char *s1,*s2;
995: {
996: register word minlen;
997: word l2;
998:
999: l2 = strlen(s2);
1000:
1001: minlen = (l1 <= l2) ? l1 : l2;
1002:
1003: while (minlen--)
1004: if (*s1++ != *s2++)
1005: return (int)((*--s1 & 0377) - (*--s2 & 0377));
1006:
1007: return (int)(l1 - l2);
1008: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.