Annotation of researchv10dc/cmd/icon/src/iconx/rconv.c, revision 1.1

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:    }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.