Visual calculator "pac", Part 2 of 4
Istvan Mohos
istvan at hhb.UUCP
Sat Jul 15 01:12:49 AEST 1989
# 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
====================================================================
More information about the Alt.sources
mailing list