[alt.sources] Visual calculator "pac", Part 2 of 4

istvan@hhb.UUCP (Istvan Mohos) (07/14/89)

# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# toktab.h amort.c atoi.c bitwise.c conv.c convbase.c

echo x - toktab.h
cat > "toktab.h" << '//E*O*F toktab.h//'
/* toktab.h */
/**********************************************************************
*    File Name     : toktab.h
*    Function      : token definitions, token table
*    Author        : Istvan Mohos, 1987
***********************************************************************/

/* to add token:
   insert in toklist, spacefilled to WORDSIZE, in ascii alpha sequence;
   increment LISTSIZE;
   add token #define, in the SAME ORDER as in toklist;
   renumber defines (0  to  LISTSIZE - 1);
   if token contains weird char, adjust map in pac.c to allow it;
   describe action in interpret.c;
*/

#define WORDSIZE  9        /* maximum token size, not including \0 */
#define LISTSIZE  158      /* number of pac tokens */

#ifdef PACTOK
static char *toklist[] = {
"!        ",
"#        ",
"\'        ",
";        ",
"?        ",
"X        ",
"\\        ",
"amass    ",
"and      ",
"arct     ",
"astro    ",
"at       ",
"atto     ",
"au       ",
"auto     ",
"autoconv ",
"autotime ",
"avogadro ",
"boltzmann",
"break    ",
"bye      ",
"chroma   ",
"clr      ",
"cm       ",
"comma    ",
"cos      ",
"define   ",
"dontsave ",
"dp       ",
"ds       ",
"dup      ",
"earthmass",
"earthrad ",
"echarge  ",
"emass    ",
"euler    ",
"exa      ",
"exit     ",
"exp      ",
"faraday  ",
"femto    ",
"fix      ",
"fo       ",
"for      ",
"format   ",
"g        ",
"gas      ",
"giga     ",
"gravity  ",
"h        ",
"hardform ",
"heat     ",
"help     ",
"hf       ",
"i        ",
"ib       ",
"ibase    ",
"if       ",
"init     ",
"j        ",
"ju       ",
"justify  ",
"k        ",
"kilo     ",
"l        ",
"le       ",
"left     ",
"length   ",
"light    ",
"lightyear",
"log      ",
"m        ",
"mega     ",
"micro    ",
"milli    ",
"mod      ",
"mohos    ",
"moonmass ",
"moonrad  ",
"n        ",
"nano     ",
"natural  ",
"nmass    ",
"not      ",
"o        ",
"ob       ",
"obase    ",
"off      ",
"on       ",
"or       ",
"p        ",
"parallax ",
"parsec   ",
"pd       ",
"pdelta   ",
"pdiff    ",
"pe       ",
"pequal   ",
"peta     ",
"pi       ",
"pico     ",
"planck   ",
"pll      ",
"pm       ",
"pmass    ",
"pminus   ",
"po       ",
"pof      ",
"pop      ",
"pp       ",
"pplus    ",
"pr       ",
"precision",
"psh      ",
"pv       ",
"pversus  ",
"q        ",
"quit     ",
"r        ",
"ri       ",
"right    ",
"rydberg  ",
"s        ",
"sb       ",
"scale    ",
"sin      ",
"sound    ",
"sp       ",
"space    ",
"sqrt     ",
"st       ",
"stack    ",
"staybase ",
"stefan   ",
"sto      ",
"sunmass  ",
"sunrad   ",
"swp      ",
"t        ",
"te       ",
"tera     ",
"terse    ",
"to       ",
"tomoon   ",
"tosun    ",
"tw       ",
"twoscomp ",
"u        ",
"v        ",
"ver      ",
"verbose  ",
"w        ",
"while    ",
"wien     ",
"x        ",
"xor      ",
"xt       ",
"xterse   "
};
#endif

/* pac token table definitions, ordered EXACTLY as toklist,
   numbered sequentially from 0.  When adding or removing tokens, this
   list gets renumbered. */

#define BANG             0
#define SHARP            1
#define TICK             2
#define SEMI             3
#define QUESTION         4
#define X_UPPER          5
#define BACKSLASH        6
#define AMASS            7
#define AND              8
#define ARCT             9
#define ASTRO           10
#define AT              11
#define ATTO            12
#define AU              13
#define AUTO            14
#define AUTOCONV        15
#define AUTOTIME        16
#define AVOGADRO        17
#define BOLTZMANN       18
#define BREAK           19
#define BYE             20
#define CHROMA          21
#define CLR             22
#define CM              23
#define COMMA           24
#define COS             25
#define DEFINE          26
#define DONTSAVE        27
#define DP              28
#define DS              29
#define DUP             30
#define EARTHMASS       31
#define EARTHRAD        32
#define ECHARGE         33
#define EMASS           34
#define EULER           35
#define EXA             36
#define EXIT            37
#define EXP             38
#define FARADAY         39
#define FEMTO           40
#define FIX             41
#define FO              42
#define FOR             43
#define FORMAT          44
#define G_              45
#define GAS             46
#define GIGA            47
#define GRAVITY         48
#define H_              49
#define HARDFORM        50
#define HEAT            51
#define HELP            52
#define HF              53
#define I_              54
#define IB              55
#define IBASE           56
#define IF              57
#define INIT_           58
#define J_              59
#define JU              60
#define JUSTIFY         61
#define K_              62
#define KILO            63
#define L_              64
#define LE              65
#define LEFT            66
#define LENGTH          67
#define LIGHT           68
#define LIGHTYEAR       69
#define LOG             70
#define M_              71
#define MEGA            72
#define MICRO           73
#define MILLI           74
#define MOD             75
#define MOHOS           76
#define MOONMASS        77
#define MOONRAD         78
#define N_              79
#define NANO            80
#define NATURAL         81
#define NMASS           82
#define NOT             83
#define O_              84
#define OB              85
#define OBASE           86
#define OFF             87
#define ON              88
#define OR              89
#define P_              90
#define PARALLAX        91
#define PARSEC          92
#define PD              93
#define PDELTA          94
#define PDIFF           95
#define PE              96
#define PEQUAL          97
#define PETA            98
#define PI              99
#define PICO           100
#define PLANCK         101
#define PLL            102
#define PM             103
#define PMASS          104
#define PMINUS         105
#define PO             106
#define POF            107
#define POP            108
#define PP             109
#define PPLUS          110
#define PR             111
#define PRECISION      112
#define PSH            113
#define PV             114
#define PVERSUS        115
#define Q_             116
#define QUIT           117
#define R_             118
#define RI             119
#define RIGHT          120
#define RYDBERG        121
#define S_             122
#define SB             123
#define SCALE          124
#define SIN            125
#define SOUND          126
#define SP             127
#define SPACE          128
#define SQRT           129
#define ST             130
#define STACK          131
#define STAYBASE       132
#define STEFAN         133
#define STO            134
#define SUNMASS        135
#define SUNRAD         136
#define SWP            137
#define T_             138
#define TE             139
#define TERA           140
#define TERSE          141
#define TO             142
#define TOMOON         143
#define TOSUN          144
#define TW             145
#define TWOSCOMP       146
#define U_             147
#define V_             148
#define VER            149
#define VERBOSE        150
#define W_             151
#define WHILE          152
#define WIEN           153
#define X_LOWER        154
#define XOR            155
#define XT             156
#define XTERSE         157
//E*O*F toktab.h//

echo x - amort.c
cat > "amort.c" << '//E*O*F amort.c//'
/* amort.c */
/**********************************************************************
*    File Name     : amort.c
*    Function      : amortization (loan) routines of pac
*    Author        : Istvan Mohos, 1987
***********************************************************************/

#include "defs.h"
#define AMORTMAP
#include "maps.h"
#undef AMORTMAP

show_loan(play)
int play;
{
    int thisline = AMTY;
    int ck, did_input, Too_big;
    char floatbuf[LOANSIZ + 1];
    int pyp, pxp, ryr, rxr;
    static char *fid = "show_loan";

    _TR
    CYX;
    show_float(Amt, AMTY, 2);
    show_float(Rate, PRCY, 3);
    show_float(Years, YRY, 2);
    mvaddstr(DATY, LOANX, "begin mo/year");
    Too_big = show_pymt();

    if (!play)
        year();
    else {
        while(TRUE) {

            switch(thisline) {
            case AMTY:
                if (Amt == 0.)
                    clear_wline(thisline, LOANX, LOANR, 0, 1);
                break;
            case PRCY:
                if (Rate == 0.)
                    clear_wline(thisline, LOANX, LOANR, 0, 1);
                break;
            case YRY:
                if (Years == 0.)
                    clear_wline(thisline, LOANX, LOANR, 0, 1);
                break;
            }

            if ((ck = ledit(floatbuf, loan_map, thisline, LOANX,
                LOANR, 0, 1, 1)) == 1)
                break;
            did_input = strlen(floatbuf);

            if (ck == 2 && Pymt > 0. && !Too_big) {
                ryr=CY, rxr=CX;
                ck = printamort();
                move(CY=ryr, CX=rxr);
                pfresh();
                if (ck == 2)
                    break;
                continue;
            }

            if (did_input) {
                switch(thisline) {
                    case AMTY:
                        Amt = atof(floatbuf);
                        break;
                    case PRCY:
                        Rate = atof(floatbuf);
                        break;
                    case YRY:
                        Years = atof(floatbuf);
                        break;
                }
                Too_big = show_pymt();
            }

            if (++thisline > YRY)
                thisline = AMTY;
        }
        PYX;
        pfresh();
    }
    TR_
}

show_pymt()
{
    double nonzero;
    char reformat[32];
    static char *fid = "show_pymt";

    _TR
    Months = Years * 12.;
    I_mo = (Rate / 100.) / 12.;
    nonzero = 1. - pow(1. + I_mo, - Months);
    if (nonzero == 0. || I_mo == 0.)
        Pymt = Showpymt = 0.;
    else {
        Pymt = Amt * (I_mo / nonzero);
        Showpymt = Pymt + .00999999;
    }

    sprintf(reformat, "%.2f", Showpymt);
    Showpymt = atof(reformat);
    if (show_float(Showpymt, PAYY, 2)) {
        TR_
        return(-1);
    }
    TR_
    return(0);
}

show_float(value, where, decimals)
double value;
int where, decimals;
{
    char loanbuf[32];
    char *lp = loanbuf;
    register char *cp;
    static char *fid = "show_float";

    _TR
    strcpy (lp, Sp13);
    sprintf(lp,  "%.*f",decimals , value);
    (strlen(lp) < 13) ? (*(lp + strlen(lp)) = ' ') : (*(lp + 13) = 0);

    cp = lp + 13;
    if (where > YRY)
        for (; --cp >= lp;)
            if (*cp == '.')
                break;

    if (cp >= lp) {
        mvaddstr(where, LOANX, lp);
        TR_
        return(0);
    }

    mvaddstr(where, LOANX, "overflow     ");
    TR_
    return(-1);
}

printamort()
{
    double a_amt, ppay, ipay, yppay, yipay;
    FILE *fp;
    char *token, *np;
    int ck, startmonth, startyear, yr;
    int pyp, pxp;
    register int ri;
    int lastmonth;
    char round[32];
    char datebuf[LOANSIZ + 1];
    static char savedate[LOANSIZ + 1];
    char namebuf[TITSIZ + 1];
    char spaceless[TITSIZ + 1];
    int did_input;
    static char *fid = "printamort";

    _TR
    if (strlen(savedate))
        mvaddstr(DATY, LOANX, savedate);

    if ((ck = ledit(&datebuf[0], date_map, DATY,
        LOANX, LOANR, 0, 1, 0)) == 1) {
        TR_
        return(1);
    }
    if (ck == 2) {  /* types ^B, I have no idea what this does */
        TR_
        return(2);
    }
    did_input = datebuf[0];

    if ((token = pactok(&datebuf[0], " .,/:")) == ZERO)
        startmonth = 1, startyear = atoi(Thisyear);
    if ((startmonth = whichmonth(token)) == 0)
        startmonth = 1;
    if ((token = pactok(ZERO, " .,/:")) == ZERO)
        startyear = atoi(Thisyear);
    else if ((startyear = atoi(token)) < 1)
        startyear = atoi(Thisyear);
    else if (startyear < 1900)
        startyear += 1900;

    move(DATY, LOANX);
    printw("%.2d/%.4d      ", startmonth, startyear);
    if (did_input)
        sprintf(savedate, "%.2d/%.4d      ", startmonth, startyear);
    pfresh();

    Basq[EDITREQ] = Bb[LOANREQ];
    CYX;  /* to save the caller'r coordinates */
    update();  /* this returns to the original coordinates,
                  but does'nt pfresh */
retry:

    ledit(namebuf, amort_map, BOT, FBOUND, RBOUND, 1, 1, 0);

    if (strlen(namebuf) == 0) {
        strcpy(spaceless, Amortname);
        for (np = spaceless; *np > 32; np++);
        *np = '\0';
        standout();
        mvaddstr(BOT, FBOUND, Amortname);
        standend();
        pfresh();
    }
    else {
        strcpy(Amortname, namebuf);
        strcpy(spaceless, namebuf);
    }

    if ((fp = fopen(spaceless, "w")) == NULL) {
        standout();
        mvaddstr(BOT, ULEFT, "can't access:");
        pfresh();
        goto retry;
    }
    
    fprintf(fp, "\
AMORTIZATION SCHEDULE\n\n");
    fprintf(fp, "\
        PREPARED FOR    %s\n", Amortname);
    fprintf(fp, "\
        LOAN AMOUNT     %.2f\n", Amt);
    fprintf(fp, "\
        MONTHLY PAYMENT %.2f\n", Showpymt);
    fprintf(fp, "\
        LENDING RATE    %.3f%c\n", Rate, '\045');
    fprintf(fp, "\
        TERM YEARS      %.2f\n\n", Years);

/* format field widths
12345678901 1234567890123 12345678901234567890 12345678901234567890 XX
*/
    fprintf(fp, "\
PAYMENT         DUE               PRINCIPAL          INTEREST           NEW\n");
    fprintf(fp, "\
NUMBER          DATE              PAYMENT            PAYMENT            BALANCE\n\n");

    a_amt = Amt;
    ck = startmonth;
    Intrst = yppay = yipay = 0.;
    yr = 1;
    for (ri = 1, lastmonth = (int)Months; ri < lastmonth; ri++) {
        ipay = I_mo * a_amt;
        sprintf(round, "%.2f", ipay);
        ipay = atof(round);
        yipay += ipay;
        ppay = Pymt - ipay + .009999999;
        sprintf(round, "%.2f", ppay);
        ppay = atof(round);
        yppay += ppay;
        a_amt -= ppay;
        fprintf(fp, "\
  %4d      %.2d/01/%.4d    %17.2f %17.2f %17.2f\n",
            ri, ck, startyear, ppay, ipay, a_amt);
        if (++ck > 12)
            ck = 1;
        if (((ri - 1) % 12) == (12 - startmonth)) {
            fprintf(fp, "\
YEAR %.2d TOTAL:            %17.2f %17.2f\n\n", yr++, yppay, yipay);
            Intrst += yipay;
            ++startyear;
            yppay = yipay = 0.;
        }
    }
    ipay = I_mo * a_amt;
    sprintf(round, "%.2f", ipay);
    ipay = atof(round);
    yipay += ipay;
    ppay = Pymt - ipay + .009999999;
    sprintf(round, "%.2f", ppay);
    ppay = atof(round);
    a_amt -= ppay;
    ppay += a_amt;
    yppay += ppay;
    a_amt = 0.;
    Intrst += yipay;
    fprintf(fp, "\
  %4d      %.2d/01/%.4d    %17.2f %17.2f %17.2f\n",
        ri, ck, startyear, ppay, ipay, a_amt);
    fprintf(fp, "\
YEAR %.2d TOTAL:            %17.2f %17.2f\n\n", yr, yppay, yipay);
    fprintf(fp, "\
GRAND TOTAL:              %17.2f %17.2f\n", Amt, Intrst);
    fclose(fp);

    strcpy(Bb[LOANREQ] + BUFSTOP, Amortname);
    rev_clear(Bb[LOANREQ] + TITSIZ);
    Basq[EDITREQ] = ZERO;

    PYX;
    update();
    TR_
    return(0);
}

//E*O*F amort.c//

echo x - atoi.c
cat > "atoi.c" << '//E*O*F atoi.c//'
/* atoi.c */
/**********************************************************************
*    File Name     : atoi.c
*    Function      : ascii/decimal/octal/hex converter of pac
*    Author        : Istvan Mohos, 1987
***********************************************************************/

#include "defs.h"
#define ATOIMAP
#include "maps.h"
#undef ATOIMAP

byte_conv(from)
int from;
{
    char c, bbuf[10], *bb;
    int pyp, pxp;
    int ri, ffd, value;
    static char *fid = "byte_conv";

    _TR
    CYX;
    switch(from) {
        case 4:
            mvaddstr(UTOP + 1, ATOIX, "ENTER 3");
            mvaddstr(UTOP + 2, ATOIX, "DECIMAL");
            mvaddstr(UTOP + 3, ATOIX, "DIGITS ");
            value = -1;
            while(value == -1) {
                mvaddstr(UTOP, ATOIX, "dec    ");

                ledit(bbuf, a_ed_map, UTOP, ATOIX+4, ATOIX+6, 0, 1, 1);
                if (!*bbuf)
                    continue;
                value = 0;
                upcase(bbuf);
                bb = bbuf;
                for (ri = strlen(bbuf); --ri >= 0; bb++) {
                    value *= 10;
                    value += (*bb > 57) ? (*bb - 55) : (*bb - 48);
                }
                if (value < 0 || value > 127) {
                    value = -1;
                    continue;
                }
            }
            move(UTOP, ATOIX);
            printw("dec %3d", value);

            move(UTOP + 1, ATOIX);
            if (value == 127)
                printw("asc DEL");
            else if (value < 33)
                printw("%s",lotab[value]);
            else
                printw("asc   %c",value);

            move(UTOP + 2, ATOIX);
            printw("oct %.3o", value);

            move(UTOP + 3, ATOIX);
            printw("hex  %.2x", value);
            break;
        case 1:
        default:
            ri = 0;
            Save_sig[ri++] = signal(SIGHUP,  SIG_IGN);
            Save_sig[ri++] = signal(SIGINT,  SIG_IGN);
            Save_sig[ri++] = signal(SIGQUIT, SIG_IGN);
            Save_sig[ri++] = signal(SIGTERM, SIG_IGN);

#ifndef REALUNIX
            Save_sig[ri++] = signal(SIGTSTP, SIG_IGN);
            Save_sig[ri++] = signal(SIGCONT, SIG_IGN);
#endif
            mvaddstr(UTOP + 1, ATOIX, "    HIT");
            mvaddstr(UTOP + 2, ATOIX, "    ANY");
            mvaddstr(UTOP + 3, ATOIX, "    KEY");
            mvaddstr(UTOP, ATOIX, "asc    ");
            move(UTOP, ATOIX + 6);
            pfresh();
            ffd = dup(0);
            close(0);
            read(ffd, &c, 1);
            dup(ffd);
            close(ffd);
            value = c & 127;

            move(UTOP, ATOIX);
            if (value == 127)
                printw("asc DEL");
            else if (value < 33)
                printw("%s",lotab[value]);
            else
                printw("asc   %c",value);
            move(UTOP + 1, ATOIX);
            printw("dec %3d", value);
            move(UTOP + 2, ATOIX);
            printw("oct %.3o", value);
            move(UTOP + 3, ATOIX);
            printw("hex  %.2x", value);

            ri = 0;
            signal(SIGHUP,  Save_sig[ri++]);
            signal(SIGINT,  Save_sig[ri++]);
            signal(SIGQUIT, Save_sig[ri++]);
            signal(SIGTERM, Save_sig[ri++]);

#ifndef REALUNIX
            signal(SIGTSTP, Save_sig[ri++]);
            signal(SIGCONT, Save_sig[ri++]);
#endif
            break;
        case 15:
            mvaddstr(UTOP + 1, ATOIX, "ENTER 3");
            mvaddstr(UTOP + 2, ATOIX, "OCTAL  ");
            mvaddstr(UTOP + 3, ATOIX, "DIGITS ");
            value = -1;
            while(value == -1) {
                mvaddstr(UTOP, ATOIX, "oct    ");

                ledit(bbuf, a_ed_map, UTOP, ATOIX+4, ATOIX+6, 0, 1, 1);
                if (!*bbuf)
                    continue;
                value = 0;
                upcase(bbuf);
                bb = bbuf;
                for (ri = strlen(bbuf); --ri >= 0; bb++) {
                    value <<= 3;
                    value += (*bb > 57) ? (*bb - 55) : (*bb - 48);
                }
                if (value < 0 || value > 127) {
                    value = -1;
                    continue;
                }
            }
            move(UTOP, ATOIX);
            printw("oct %.3o", value);

            move(UTOP + 1, ATOIX);
            if (value == 127)
                printw("asc DEL");
            else if (value < 33)
                printw("%s",lotab[value]);
            else
                printw("asc   %c",value);
            move(UTOP + 2, ATOIX);
            printw("dec %3d", value);
            move(UTOP + 3, ATOIX);
            printw("hex  %.2x", value);
            break;
        case 24:
            mvaddstr(UTOP + 1, ATOIX, "ENTER 2");
            mvaddstr(UTOP + 2, ATOIX, "HEX    ");
            mvaddstr(UTOP + 3, ATOIX, "DIGITS ");
            value = -1;
            while(value == -1) {
                mvaddstr(UTOP, ATOIX, "hex    ");

                ledit(bbuf, a_ed_map, UTOP, ATOIX+4, ATOIX+6, 0, 1, 1);
                if (!*bbuf)
                    continue;
                value = 0;
                upcase(bbuf);
                bb = bbuf;
                for (ri = strlen(bbuf); --ri >= 0; bb++) {
                    value <<= 4;
                    value += (*bb > 57) ? (*bb - 55) : (*bb - 48);
                }
                if (value < 0 || value > 127) {
                    value = -1;
                    continue;
                }
            }
            move(UTOP, ATOIX);
            printw("hex  %.2x", value);

            move(UTOP + 1, ATOIX);
            if (value == 127)
                printw("asc DEL");
            else if (value < 33)
                printw("%s",lotab[value]);
            else
                printw("asc   %c",value);

            move(UTOP + 2, ATOIX);
            printw("dec %3d", value);
            move(UTOP + 3, ATOIX);
            printw("oct %.3o", value);
            break;
    }
    PYX;
    pfresh();
TR_
}

//E*O*F atoi.c//

echo x - bitwise.c
cat > "bitwise.c" << '//E*O*F bitwise.c//'
/* bitwise.c */
/**********************************************************************
*    File Name     : bitwise.c
*    Function      : and/or/xor/not/two's complement functions of pac
*    Author        : Istvan Mohos, 1987
***********************************************************************/


#include "defs.h"
#include "toktab.h"

/* bitwise operators:
   Ignore negative signs, if any.
   Add preceding zeros to match digit count of integral part of numbers.
   Add trailing zeros to match digit count of fractional part of nums.
   Flip bits as appropriate.
*/
   
char *
bitwise(oper, operand1, operand2, negflag)
char *operand1, *operand2;
int oper, *negflag;
{

#ifdef BITTEST
    static char debug1[LINEMAX], debug2[LINEMAX];
    static
#endif
    char buf1[LINEMAX], buf2[LINEMAX];

    static char bitbuf[LINEMAX];
    char *bp = bitbuf;
    char *pt1 = operand1;
    char *pt2 = operand2;
    register char *r1, *r2;
    register int ri;
    int leflen1, leflen2;
    int ritlen1 = 0;
    int ritlen2 = 0;
    int dot1 = 0;
    int dot2 = 0;
    int len_of1, len_of2;
    int maxlef, maxrit;
    static char *fid = "bitwise";

    _TR
    *bp++ = Base_str[2];
    *bp++ = ' ';

    /* ignore signs */
    *negflag = 0;
    if (*pt1 == '-')
        ++pt1;
    len_of1 = strlen(pt1);
    for (r1 = pt1 + len_of1; --r1 >= pt1;)
        if (*r1 == '.') {
            dot1 = 1;
            break;
        }
    if (!dot1)
       leflen1 = len_of1;
    else {
       leflen1 = r1 - pt1;
       ritlen1 = len_of1 - leflen1 - 1;
    }
    
    switch (oper) {
        default:
        case AND:
        case OR:
        case XOR:
            if (*pt2 == '-')
                ++pt2;
            len_of2 = strlen(pt2);
            for (r2 = pt2 + len_of2; --r2 >= pt2;)
                if (*r2 == '.') {
                    dot2 = 2;
                    break;
                }
            if (!dot2)
               leflen2 = len_of2;
            else {
               leflen2 = r2 - pt2;
               ritlen2 = len_of2 - leflen2 - 2;
            }
        
            maxlef = (leflen1 > leflen2) ? leflen1 : leflen2;
            maxrit = (ritlen1 > ritlen2) ? ritlen1 : ritlen2;

            r1 = buf1;
            for (ri = maxlef - leflen1; --ri >= 0; *r1++ = '0');
            strcpy(r1, pt1);
            r1 += len_of1;
            if (dot1 || dot2)
                *r1++ = '.';
            for (ri = maxrit - ritlen1; --ri >= 0; *r1++ = '0');
            *r1 = '\0';
            r1 = buf1;

            r2 = buf2;
            for (ri = maxlef - leflen2; --ri >= 0; *r2++ = '0');
            strcpy(r2, pt2);
            r2 += len_of2;
            if (dot1 || dot2)
                *r2++ = '.';
            for (ri = maxrit - ritlen2; --ri >= 0; *r2++ = '0');
            *r2 = '\0';
            ri = r2 - buf2; /* not including the null */
            r2 = buf2;

            switch (oper) {
                case AND:
                    for (; --ri >= 0; r1++, r2++, bp++)
                        if (*r1 == '1' && *r2 == '1')
                            *bp = '1';
                        else
                            *bp = '0';
                    break;
                case OR:
                    for (; --ri >= 0; r1++, r2++, bp++)
                        if (*r1 == '1' || *r2 == '1')
                            *bp = '1';
                        else
                            *bp = '0';
                    break;
                case XOR:
                    for (; --ri >= 0; r1++, r2++, bp++)
                        if ((*r1 == '1' && *r2 == '0') ||
                            (*r1 == '0' && *r2 == '1'))
                            *bp = '1';
                        else
                            *bp = '0';
                    break;
            }
            *bp = '\0';
            if (dot1 || dot2)
                *(bitbuf + 2 + maxlef) = '.';

#ifdef BITTEST
    strcpy(debug1, pt1);
    strcpy(debug2, pt2);
    if (Trace && Tf != NULL)
        fprintf(Tf,
        "\n<<<%s>>>\n<<<%s>>>\n<<<<%s>>>\n<<<%s>>>\n<<<%s>>>\n",
        debug1, debug2, buf1, buf2, bitbuf);
#endif

            TR_
            return(bitbuf);

        case TW:
            if (dot1) {
                TR_
                return(ZERO);
            }
            if (atoi(pt1) == 0) {
                strcpy(bp, "-1");
                TR_
                return(bitbuf);
            }
            /* case continues */
        case NOT:

            /* convert second number (in base 10), to size of
               field in which to evaluate the operand */
            if (*pt2 == '-')
                ++pt2;
            if ((len_of2 = atoi(pt2)) > LINEMAX - 4 - ritlen1) {
                TR_
                return(ZERO);
            }

            if (*pt1 == '1' && len_of2 == leflen1)
                *negflag = 1;
            if (leflen1 > len_of2) {
                len_of2 = leflen1; 
                pac_err("field too small");
            }
            r2 = bp;
            for (ri = len_of2; --ri >= 0; *r2++ = '1');
            *r2++ = '.';
            for (ri = ritlen1; --ri >= 0; *r2++ = '1');
            *r2-- = '\0';  /* end of result in bitbuf */

            /* on last digit */
            r1 = pt1 + leflen1 + ritlen1 + dot1 -1;
            for (ri = ritlen1; --ri >= 0; r1--, r2--)
                if (*r1 == '1')
                    *r2 = '0';
            if (dot1)
                *r2-- = *r1--;
            else
                *r2-- = '\0';

            for (ri = leflen1; --ri >= 0; r1--, r2--)
                if (*r1 == '1')
                    *r2 = '0';
            TR_
            return(bitbuf);
    }
}
//E*O*F bitwise.c//

echo x - conv.c
cat > "conv.c" << '//E*O*F conv.c//'
/* conv.c */
/**********************************************************************
*    File Name     : conv.c
*    Function      : user conversion routines of pac
*                  : Recursion is too big a task to fit the framework
*                  :  (i.e. defining 'to foo' as 'to {to foo}' brings
*                  :  up all sorts of control problems).  To simplify,
*                  :  only numerical expressions and binary operands
*                  :  are permitted, in a single statement (no ';').
*                  : 
*    Author        : Istvan Mohos, 1987
***********************************************************************/


#include "defs.h"
#define CONVMAP
#include "maps.h"
#undef CONVMAP

show_uconv()
{
    register ri;
    static char *fid = "show_uconv";

    _TR
    if (Convsel < CENTER)
        Topconv = 0;
    else if (Convsel >= Convcount - CENTER)
        Topconv = Convcount - (2 * CENTER);
    else
        Topconv = Convsel - CENTER + 1;

    for (ri = 0; ri < FITCONV; ri++) {
        mvaddstr(ri + TOP+1, CONVLEFT, Convlist[ri + Topconv][0]);
        addch(' ');
        mvaddstr(ri + TOP+1, KEYLEFT, Convlist[ri + Topconv][1]);
    }

    standout();
    for (ri = 0; ri < FITCONV; ri++)
        mvaddch(UTOP + ri, RBOUND, ' ');

    mvaddstr(TOP+1 + Convsel - Topconv, CONVLEFT, Convlist[Convsel][0]);
    standend();
    TR_
}

setup_uconv()
{
    register char *rc;
    register int ri;
    static char *fid = "setup_uconv";

    _TR
    Convhsiz = Convcount * (FROMTOSIZ + KEYSIZ);
    for (ri = 0; ri < Convcount; ri++)
        Convhsiz += strlen(Convlist[ri][2]) + 1; /* conv string + \n */
    if ((Convhom = calloc(Convhsiz, 1)) == ZERO)
        fatal("calloc error in setup_uconv");

    /* move static defs to dynamically alterable Convhom buffer */
    for (rc = Convhom, ri = 0; ri < Convcount; ri++) {
        strcpy(rc, Convlist[ri][0]);
        rc += FROMTOSIZ;
        strcpy(rc, Convlist[ri][1]);
        rc += KEYSIZ;
        strcpy(rc, Convlist[ri][2]);
        while (*rc++ != '\0');
    }
    realign_conv();
    TR_
}

conv_id(c_ptr)
char *c_ptr;
{
    int inlist_val, under;
    static char *fid = "conv_id";

    _TR
    if ((inlist_val = spacefill(c_ptr, 3)) != -1)
        inlist_val = keysearch(Tokbuf, Convcount, &under);
    TR_
    return(inlist_val);
}

keysearch (key, max, under)
register char *key;
int max, *under;
{
    register int guess, mid, lo = 0, hi;
    static char *fid = "keysearch";

    _TR
    hi = max - 1;
    while (lo <= hi) {
        mid = (lo + hi) >> 1;
        if ((guess = strcmp(key, Convlist[mid][1])) < 0)
            hi = mid - 1;
        else if (guess > 0)
            lo = mid + 1;
        else {
            TR_
            return(mid);
        }
    }
    *under = lo;
    TR_
    return (-1);
}

newconv()
{
    int c;
    int lbound;
    char calbuf[LINEMAX];
    int pyp, pxp;
    int ri;
    register int rj;
    register char *rc;
    static char *fid = "newconv";

    _TR
    CYX;
    rc = calbuf;
    for (ri = UTOP; ri <= UBOT; ri++)
        for (rj = ULEFT; rj <= URIGHT; rj++)
            *rc++ = stdscr->_y[ri][rj];

    mvaddstr(UTOP, ULEFT, Sp44);
    mvaddstr(UTOP + 1, ULEFT, Sp44);
    mvaddstr(UTOP + 2, ULEFT, Sp44);

    if (Convcount == 255) {
        mvaddstr(UTOP, ULEFT,
            "SELECT:   ...full...    Remove     Change  _");
        lbound = ULEFT + strlen(
            "SELECT:   ...full...    Remove     Change  ");

        while((c = ledit(ZERO,c_sel_map,UTOP,lbound,lbound,0,0,0)
            | 32) != 'r' && c != 'c');
    }
    else if (Convcount == 22) {
        mvaddstr(UTOP, ULEFT,
            "SELECT:     Install   ...low...    Change  _");
        lbound = ULEFT + strlen(
            "SELECT:     Install   ...low...    Change  ");

        while((c = ledit(ZERO,c_sel_map,UTOP,lbound,lbound,0,0,0)
            | 32) != 'i' && c != 'c');
    }
    else {
        mvaddstr(UTOP, ULEFT,
            "SELECT:     Install     Remove     Change  _");
        lbound = ULEFT + strlen(
            "SELECT:     Install     Remove     Change  ");

        while((c = ledit(ZERO,c_sel_map,UTOP,lbound,lbound,0,0,0)
            | 32) != 'i' && c != 'r' && c != 'c');
    }

    mvaddstr(UTOP, ULEFT, Sp44);
    mvaddstr(UTOP + 1, ULEFT, Sp44);
    mvaddstr(UTOP + 2, ULEFT, Sp44);

    switch(c) {
        case 'i':
            addnew(specify(pyp, pxp));
            break;

        case 'r':
            remove(celect());
            break;

        case 'c':
            remove(celect());
            addnew(specify(pyp, pxp));
            break;
    }

    rc = calbuf;
    for (ri = UTOP; ri <= UBOT; ri++)
        for (rj = ULEFT; rj <= URIGHT; rj++)
            mvaddch(ri, rj, *rc++);

    PYX;
    pfresh();
    TR_
}

celect()
{
    int lbound, rbound;
    char *c_key;
    int keylen, old_id, dummy;
    static char *fid = "celect";

    _TR
    clear_wline(UTOP, ULEFT, URIGHT, 0, 3);
    c_key = "   ";
    mvaddstr(UTOP, ULEFT,
        "ENTER OLD 'TO' SEARCH KEY:   [");
    lbound = ULEFT + strlen(
        "ENTER OLD 'TO' SEARCH KEY:   [");
    rbound = lbound + 2;
    mvaddstr(UTOP, rbound + 1, "]");

    old_id = -1;
    while (old_id == -1) {
        mvaddstr(UTOP, lbound, c_key);
    

        ledit(&K_buf[0], c_ed_map, UTOP, lbound, rbound, 0, 1, 1);
        /* stripping surrounding spaces */

        if(!*K_buf)
            continue;
        keylen = strlen(K_buf);
        if (keylen < 3)
            K_buf[2] = ' ';
        else if (*(K_buf+1) == ' ')
            *(K_buf+1) = '_'; /* turn embedded space into _ */
        if (keylen < 2)
            K_buf[1] = ' ';
        old_id = keysearch(K_buf, Convcount, &dummy);
    }
    TR_
    return(old_id);
}

specify(pyp, pxp)
int pyp, pxp;
{
    int lbound, rbound;
    char *c_label, *c_key;
    int neednewkey = 1, keylen, insert;
    static char *fid = "specify";

    _TR
    clear_wline(UTOP, ULEFT, URIGHT, 0, 3);
    while (neednewkey) {
        c_key = "   ";
        mvaddstr(UTOP + 1, ULEFT,
            "ENTER NEW 'TO' SEARCH KEY:   [");
        lbound = ULEFT + strlen(
            "ENTER NEW 'TO' SEARCH KEY:   [");
        mvaddstr(UTOP + 1, lbound, c_key);
        rbound = lbound + 2;
        mvaddstr(UTOP + 1, rbound + 1, "]");
    

        ledit(&K_buf[0], c_ed_map, UTOP+1, lbound, rbound, 0, 1, 1);
        /* stripping surrounding spaces */

        if (keylen = strlen(K_buf)) {
            if (keylen < 3)
                K_buf[2] = ' ';
            else if (*(K_buf+1) == ' ')
                *(K_buf+1) = '_'; /* turn emmbedded space into _ */
            if (keylen < 2)
                K_buf[1] = ' ';
        }
        else
            continue;
        if (keysearch(K_buf, Convcount, &insert) == -1)
            neednewkey = FALSE;
        /* if it did find it, the proposed new key is a duplicate,
           and is disallowed */
    }

    c_label = "             ";
    mvaddstr(UTOP + 2, ULEFT, "ENTER 'CONVERSIONS' LABEL:   [");
    lbound = ULEFT + strlen( "ENTER 'CONVERSIONS' LABEL:   [");
    mvaddstr(UTOP + 2, lbound, c_label);
    rbound = lbound + 12;
    mvaddstr(UTOP + 2, rbound + 1, "]");


    ledit(&L_buf[0], c_ed_map, UTOP+2, lbound, rbound, 0, 0, 1);

    mvaddstr(UTOP, ULEFT, Sp44);
    mvaddstr(UTOP + 1, ULEFT, Sp44);
    mvaddstr(UTOP + 2, ULEFT, Sp44);

    mvaddstr(UTOP, ULEFT,
        "COMPLETE THE EQUATION USING THE BACKSLASH \\");
    mvaddstr(UTOP + 1, ULEFT,
        "CHARACTER TO REPRESENT THE 'FROM' QUANTITY.");
    mvaddstr(UTOP + 2, ULEFT,
        "CONSTANTS ARE INTERPRETED IN DECIMAL RADIX.");

    Basq[EDITREQ] = Bb[EDITREQ];
    update();  /* this returns to the original coordinates,
                  but does'nt pfresh */

enter_conv:

    ledit(&Eq_buf[0], eq_ed_map, BOT, FBOUND, RBOUND, 1, 1, 1);

    if (verify_uconv())
        goto enter_conv;

    Basq[EDITREQ] = ZERO;
    PYX;
    update();
    pfresh();
    TR_
    return(insert);
}

realign_conv()
{
    register int ri;
    register char *rc;
    static char *fid = "realign_conv";

    _TR
    for (rc = Convhom, ri = 0; ri < Convcount; ri++) {
        Convlist[ri][0] = rc; /* ptr to first word of conversion */
        rc += FROMTOSIZ;         /* buffer pointer to second word */
        Convlist[ri][1] = rc; /* ptr to 2nd word of conversion */
        rc += KEYSIZ;            /* buffer pointer to conv string */
        Convlist[ri][2] = rc; /* ptr to conversion string */
        while (*rc++ != '\0');   /* find next conversion in buffer */
    }
    TR_
}

remove(old_id)
int old_id;
{
/*
   malloc Convhsiz size temp buffer;
   copy Convhom into temp until old_id conversion;
   skip (do not copy) old_id conversion;
   copy rest of Convhom into temp;
   free Convhom;
   assign Convhom pointer to temp;
   decrement Convcount;
   adjust Convhsiz;
   realign Convlist pointers along new buffer;
*/

    char *Tmp;
    register char *tp;
    unsigned rmsiz;
    register int ri;
    static char *fid = "remove";

    _TR
    if ((Tmp = malloc(Convhsiz)) == ZERO)
        fatal("malloc error in remove");
    tp = Tmp;

    for (ri = 0; ri < old_id; ri++) {
        strcpy(tp, Convlist[ri][0]);
        tp += FROMTOSIZ;
        strcpy(tp, Convlist[ri][1]);
        tp += KEYSIZ;
        strcpy(tp, Convlist[ri][2]);
        while (*tp++ != '\0');
    }
    rmsiz = FROMTOSIZ + KEYSIZ + strlen(Convlist[ri][2]) + 1; 
    for (ri = old_id + 1; ri < Convcount; ri++) {
        strcpy(tp, Convlist[ri][0]);
        tp += FROMTOSIZ;
        strcpy(tp, Convlist[ri][1]);
        tp += KEYSIZ;
        strcpy(tp, Convlist[ri][2]);
        while (*tp++ != '\0');
    }
    free(Convhom);
    Convhom = Tmp;
    --Convcount;
    Convhsiz -= rmsiz;
    realign_conv();
    if (Convsel > old_id)
        --Convsel;
    else if (Convsel == old_id)
        Convsel = CONVSEL;
    show_uconv();
    TR_
}

addnew(insert)
int insert;
{
/*
   Malloc new buffer, to hold Convhom + size of new conversion.
   Copy Convhom into new buffer, until the alphabetic ordering
       of KEYs reaches the new KEY.
   Insert new conversion in new buffer.
   Finish copying old conversions from Convhom to new buffer.
   Free Convhom.
   Assign Convhom (pointer) to new buffer.
   Increment Convcount.
   adjust Convhsiz;
   Realign Convlist pointers along new buffer.
*/

    char *Tmp;
    register char *tp;
    unsigned addsiz;
    register int ri;
    static char *fid = "addnew";

    _TR
    addsiz = FROMTOSIZ + KEYSIZ + strlen(Eq_buf) + 1; 
    if ((Tmp = malloc(Convhsiz + addsiz)) == ZERO)
        fatal("malloc error in addnew");
    tp = Tmp;

    for (ri = 0; ri < insert; ri++) {
        strcpy(tp, Convlist[ri][0]);
        tp += FROMTOSIZ;
        strcpy(tp, Convlist[ri][1]);
        tp += KEYSIZ;
        strcpy(tp, Convlist[ri][2]);
        while (*tp++ != '\0');
    }
    strcpy(tp, L_buf);
    tp += FROMTOSIZ;
    strcpy(tp, K_buf);
    tp += KEYSIZ;
    strcpy(tp, Eq_buf);
    while (*tp++ != '\0');
    for (ri = insert; ri < Convcount; ri++) {
        strcpy(tp, Convlist[ri][0]);
        tp += FROMTOSIZ;
        strcpy(tp, Convlist[ri][1]);
        tp += KEYSIZ;
        strcpy(tp, Convlist[ri][2]);
        while (*tp++ != '\0');
    }
    free(Convhom);
    Convhom = Tmp;
    ++Convcount;
    Convhsiz += addsiz;
    realign_conv();
    Convsel = insert;
    show_uconv();
    TR_
}

verify_uconv()
{
    static char *fid = "verify_uconv";

    _TR
    if (strlen(Eq_buf) == 0) {
        strcpy(Eq_buf, "\\");
        TR_
        return(0);
    }

    TR_
    return(0);
}

/* the routine that interprets the user keyword TO */
conv_usr()
{
    char *ctab, *cb, cbuf[LINEMAX];
    char hardbuf[LINEMAX];
    int ri;
    int sav_ibase;
    static char *fid = "conv_usr";

    _TR
    e_syntax();
    e_divby0();
    e_exponent();
    e_bcexec();

    if (!Bc_error) {
        sav_ibase = Ibase;
        Ibase = 10;
        conv_bc(Mainbuf, ZERO, 0, 0);
        *(Convbuf + DIGMAX + 2) = '\0';
        ri = strlen(Convbuf);
        Ibase = sav_ibase;
    
        cb = cbuf;
        strcpy(cb, "ibase=A;");
        cb += strlen(cb);
    
        ctab = Convlist[Convsel][2];
        sprintf(Bb[CONVREQ] + BUFSTOP, ctab);
        rev_clear(Bb[CONVREQ] + TITSIZ);
        Basq[CONVREQ] = Bb[CONVREQ];
        update();
    
        if ( Hc != -1 && Hf != FXTER) {
            if (Hf == FVER)
                sprintf(hardbuf, "TO %s: %s\n", Convlist[Convsel][1], ctab);
            else
                sprintf(hardbuf, "TO %s\n", Convlist[Convsel][1]);
            if ((write(Hc, hardbuf, strlen(hardbuf))) !=
                strlen(hardbuf))
                fatal("hardcopy write");
        }
    
        while (*ctab != '\0') {
            if (*ctab == '\\') {
                strcpy(cb, Convbuf);
                cb += ri;
                ctab++;
            }
            else
                *cb++ = *ctab++;
        }
        sprintf(cb, ";ibase=%d\n", Ibase);
        if (write(A_write[1], cbuf, strlen(cbuf)) == -1)
            fatal("main pipe write");
        clear_accwin();
        wait_main_pipe();
    }
    if (Autoconv == DISA)
        Do_conv = FALSE;
    TR_
}

//E*O*F conv.c//

echo x - convbase.c
cat > "convbase.c" << '//E*O*F convbase.c//'
/* convbase.c */
/**********************************************************************
*    File Name     : convbase.c
*    Function      : use second bc pipe for conversion between radices
*    Author        : Istvan Mohos, 1987
***********************************************************************/

#include "defs.h"
#include "toktab.h"
#define INTERMAP
#include "maps.h"
#undef INTERMAP

char *
substivar(found, token, ib)
char *token;
int found, ib;
{ 
    static char res[PIPEMAX];
    static struct stk_cell *sr = &Stk[0];
    static char *fid = "substivar";
    char *ret = res;
    int tokval;

    _TR
    if (found == -1) {
        if (token == ZERO) {
            TR_
            return(ZERO);
        }
        tokval = lookup(token);
    }
    else
        tokval = found;

    switch(tokval) {
        case H_:
        case I_:
        case J_:
        case K_:
        case L_:
        case M_:
        case N_:
        case O_:
        case P_:
        case Q_:
        case R_:
        case S_:
        case T_:
        case U_:
        case V_:
        case W_:
            onereg(*token - 'g');
            conv_bc(Onebuf, res, 1, ib);
            break;

case PI: conv_bc("3.1415926535897932384626433832795028841971693993751",
                    res, 10, ib); break;
case ASTRO:     conv_bc("149504200", res, 10, ib); break;
                    /* km */
case AMASS:     conv_bc(".00000000000000000000000165975",
                    res, 10, ib); break; /* grams */
case AVOGADRO:  conv_bc("602502000000000000000000",
                    res, 10, ib); break; /* per g mole */
case BOLTZMANN: conv_bc(".000000000000000138040", res, 10, ib); break;
                    /* erg/Kelvin */
case ECHARGE:   conv_bc(".000000000160202", res, 10, ib); break;
                    /* esu */
case CHROMA:    conv_bc("1.0594631", res, 10, ib); break;
case EMASS:     conv_bc(".000000000000000000000000000910820",
                    res, 10, ib); break; /* grams */
case EULER:     conv_bc(".577216", res, 10, ib); break;
case FARADAY:   conv_bc("96521900", res, 10, ib); break;
                    /* C/kmole */
case G_:        conv_bc("9.80665", res, 10, ib); break;
                    /* m/s2 */
case GAS:       conv_bc("83169600", res, 10, ib); break;
                    /* erg/g mole Kelvin */
case GRAVITY:   conv_bc(".00000000006673", res, 10, ib); break;
                    /* N m2/kg2 */
case HEAT:      conv_bc("4.1855", res, 10, ib); break;
                    /* J/cal */
case LIGHT:     conv_bc("299792.50", res, 10, ib); break;
                    /* km/sec */
case LIGHTYEAR: conv_bc("9460530000000", res, 10, ib); break;
                    /* km */
case MOONMASS:  conv_bc("73430000000000000000000", res, 10, ib); break;
                    /* kg */
case SUNMASS:   conv_bc("1987000000000000000000000000000",
                    res, 10, ib); break; /* kg */
case EARTHMASS: conv_bc("5976500000000000000000000",
                    res, 10, ib); break; /* kg */
case NATURAL:   conv_bc("2.7182818284590452353602874713526",
                    res, 10, ib); break;
case NMASS:     conv_bc(".00000000000000000000000167465",
                    res, 10, ib); break; /* grams */
case PARSEC:    conv_bc("30837450000000", res, 10, ib); break;
                    /* km */
case PARALLAX:  conv_bc("8.794", res, 10, ib); break;
                    /* " */
case PLANCK:    conv_bc(".00000000000000000000000000662491",
                    res, 10, ib); break; /* erg sec */
case PMASS:     conv_bc(".00000000000000000000000167235",
                    res, 10, ib); break; /* grams */
case MOONRAD:   conv_bc("1738000", res, 10, ib); break;
                    /* meters */
case SUNRAD:    conv_bc("696500000", res, 10, ib); break;
                    /* meters */
case EARTHRAD:  conv_bc("6378388", res, 10, ib); break;
                    /* meters */
case RYDBERG:   conv_bc("10973732.8", res, 10, ib); break;
                    /* per meter */
case SOUND:     conv_bc("340.505", res, 10, ib); break;
                    /* meters/sec: 331.4 + (.607 * Celsius) */
case STEFAN:    conv_bc(".000000056693", res, 10, ib); break;
                    /* J/m2 Kelvin4 sec */
case TOMOON:    conv_bc("384400", res, 10, ib); break;
                    /* km */
case TOSUN:     conv_bc("149500000", res, 10, ib); break;
                    /* km */
case WIEN:      conv_bc(".289778", res, 10, ib); break;
                    /* cm Kelvin */

case MILLI:     conv_bc(".001", res, 10, ib); break;
case MICRO:     conv_bc(".000001", res, 10, ib); break;
case NANO:      conv_bc(".000000001", res, 10, ib); break;
case PICO:      conv_bc(".000000000001", res, 10, ib); break;
case FEMTO:     conv_bc(".000000000000001", res, 10, ib); break;
case ATTO:      conv_bc(".000000000000000001", res, 10, ib); break;
case KILO:      conv_bc("1000", res, 10, ib); break;
case MEGA:      conv_bc("1000000", res, 10, ib); break;
case GIGA:      conv_bc("1000000000", res, 10, ib); break;
case TERA:      conv_bc("1000000000000", res, 10, ib); break;
case PETA:      conv_bc("1000000000000000", res, 10, ib); break;
case EXA:       conv_bc("1000000000000000000", res, 10, ib); break;

        case X_LOWER:
        case X_UPPER:
            sprintf(res, "%s", sixteen[Ibase]);
            break;

        case BACKSLASH:
            conv_bc(sr->cell, res, 1, ib);
            break;

        case NOTINLIST:    /* presumably a digit string */
            upcase(token);
            ret = token;
            break;

        default: /* token in list, but is not variable or constant */
            ret = Convbuf;   /* just to warn the caller */
            break;
    }
    TR_
    return(ret);
}

/* translate frombuf number string in frombase radix,
   to string in tobuf in tobase radix.

   If frombase and tobase are identical no conversion is done;
   buffer is simply copied.
   Otherwise, conv_pipe's ibase is set to the frombase radix,
   conv_pipe's obase is set to tobase, and the frombuf
   string is executed through conv_pipe.

   If frombase is 0, Lastob is taken as frombase.
   If frombase is -1, Ibase is taken as frombase.
   If frombase is 1, frombase is deduced from the first character
       of frombuf in stack string format.

   If tobuf is ZERO, result goes to Convbuf.  Else tobuf must
   be at least PIPEMAX long.
*/

conv_bc(frombuf, tobuf, frombase, tobase)
char *frombuf, *tobuf;
int frombase, tobase;
{
    int value, maxchars;
    int charcount = 0;
    register char *bptr, *toasc_p;
    static char *fid = "conv_bc";

    _TR
    bptr = frombuf;
    if (tobase == 0)
        tobase = Ibase;
    maxchars = strlen(frombuf);
    if (tobuf == ZERO)
        tobuf = Convbuf;

    switch (frombase) {
        case 1:
            charcount = 1;
            value = *bptr & 127; /* ascii value of passed radix label */
            for (toasc_p = Base_str + 16;; toasc_p--) {
                if (*toasc_p == value) {
                    frombase = toasc_p - Base_str;
                    break;
                }
            }
            while ((*++bptr & 127) == ' ') /* get to digit string */
                ++charcount;
            break;

        case -1:
            frombase = Ibase;
            break;

        case 0:
            frombase = Lastob;
            break;

        default:
            break;

    }

    if (frombase == tobase) {
        toasc_p = tobuf;
        while(charcount++ < maxchars)
            if ((*bptr & 127) != ' ')
                *toasc_p++ = *bptr++ & 127;
            else
                ++bptr;
        *toasc_p = '\0';
    }
    else {
        sprintf(Mop, "ibase=A;obase=%d;ibase=%d\n", tobase, frombase);
        toasc_p = &Mop[strlen(Mop)];
        while(charcount++ < maxchars)
            *toasc_p++ = *bptr++ & 127;
        *toasc_p++ = '\n';
        *toasc_p = '\0';
        if (write (B_write[1], Mop, strlen(Mop)) == -1)
            fatal("wait_conv_pipe write");
        wait_conv_pipe(tobuf);
    }
    TR_
}

//E*O*F convbase.c//

echo Possible errors detected by \'wc\' [hopefully none]:
temp=/tmp/shar$$
trap "rm -f $temp; exit" 0 1 2 3 15
cat > $temp <<\!!!
     344     911    7256 toktab.h
     303     873    7762 amort.c
     196     577    6011 atoi.c
     201     685    5666 bitwise.c
     522    1623   13160 conv.c
     243     903    7993 convbase.c
    1809    5572   47848 total
!!!
wc  toktab.h amort.c atoi.c bitwise.c conv.c convbase.c | sed 's=[^ ]*/==' | diff -b $temp -
exit 0
-- 
        Istvan Mohos
        {ihnp4,decvax,allegra}!philabs!hhb!istvan
        HHB Systems 1000 Wyckoff Ave. Mahwah NJ 07430 201-848-8000
====================================================================