jdg@hpqtdla.HP.COM (James Gentles) (03/16/90)
Is anyone out there still using Mark Adler's HPREAD1.3 to get data into your
PC from your HP28? Here are two C programs that enhance Mark's excellent
efforts.
The HPREAD1.3 output on the PC is a little strange with the 28's special
characters mapping to some strange characters in the PC's extended character
set. I have written some code to decypher the characters and then format
the output a little better. These are my first two programs written in C
so please forgive the style. Also they are not bomb proof.
My main use of HPREAD is for printing, archiving and posting programs on
notes / email. My notes / email system is a HP mainframe, and its best to
use 7bit ASCII with it, so my need for HPTRANS. HPTRANS replaces all the
HP28 special characters (128 to 255) with strings of standard characters.
The common characters like not equals are replaced with <> but the more
obscure characters are replaced with strings with $ at the end as a clue
to the reader that a character has been replaced. e.g. e acute is "e/$".
All 128 characters from 128 to 255 are replaced with the corresponding string
in a data file HPTABLE.ASC. The program also constructs a table of strings
used at the end of the output. Stdin and Stdout are used. By modifying the
HPTABLE.ASC file it should be possible to map HP28 ASCII to MS-DOS ASCII
if you wanted to keep your files on the MS_DOS machine.
HPFORMAT takes the output of HPTRANS and tidies it up. This is not perfect,
but it does cut down the work required to produce a 'pretty' output. It
maintains the hp28's indenting structure with the following rules.
1. Line length is between 40 and 50 ( NOT 23). The line will end on a
space, ', ), *, +, or when the line is 50 characters long.
2. The output maintains the indent when it scrolls onto the next line, unlike
the HP28 which starts at the beginning of the next line
Possible Bugs: The indenting should be clamped to be less than the line
length, this is easy to fix, I havent got round to it yet.
It is sometimes unclear whether the input c/r is because of
wrap-around or because it wants a c/r. Currently this criterion
is used - IF more than 18 chars into the line then its a wrap-
around, else its a c/r. This is open to errors, a better
solution is conceivable but the code begins to get more complex
The un-indenting is wrong, this is not a problem as very few
HP28 programs have commands during this period >> >> >>.
Again HPFORMAT uses stdin and stdout
Sample input and output:
The following HP28 program "FMTTIME" was uploaded using HPREAD
FMTTIME
S RCLF 58 CHR Y t f
c
S t 10000 * IP
10000 / 't' STO
IF t 12 I
THEN t 12 - 't'
STO " pm"
ELSE " am"
END
IF t 1 <
THEN t 12 + 't'
STO
END t IP STD
YSTR c + t FP 4 FIX
YSTR DUP 3 4 SUB c +
SWAP 5 6 SUB + +
SWAP + f STOF
B
B
Notice the short line length, poor indentation and illegible characters. Put
this through HPTRANS to get:
FMTTIME
<< RCLF 58 CHR -> t f
c
<< t 10000 * IP
10000 / 't' STO
IF t 12 >=
THEN t 12 - 't'
STO " pm"
ELSE " am"
END
IF t 1 <
THEN t 12 + 't'
STO
END t IP STD
->STR c + t FP 4 FIX
->STR DUP 3 4 SUB c +
SWAP 5 6 SUB + +
SWAP + f STOF
>>
>>
SYMBOL KEY:
>= 138:-Greater_than_&_equal_to
-> 141:-Right_hand_arrow
<< 146:-Start_program_construct
>> 147:-End_program_construct
Note that all the special characters have been replaced and a SYMBOL TABLE
added. Finally put this through HPFORMAT
FMTTIME
<< RCLF 58 CHR -> t f c
<< t 10000 * IP 10000 / 't' STO
IF t 12 >=
THEN t 12 - 't' STO " pm"
ELSE " am"
END
IF t 1 <
THEN t 12 + 't' STO
END t IP STD ->STR c + t FP 4 FIX ->STR
DUP 3 4 SUB c + SWAP 5 6 SUB + + SWAP
+ f STOF
>>
>>
SYMBOL KEY:
>= 138:-Greater_than_&_equal_to
-> 141:-Right_hand_arrow
<< 146:-Start_program_construct
>> 147:-End_program_construct *
Thats the final output.
There now follows 2 C source files and an ascii file which you can compile
to do the above. I hope this has been of interest, comments by email/notes
appreciated.
Many Thanks
James Gentles
---------------------------------------------------------------------
I have no professional connection with Hewlett-Packard's
calculator operations other than as a user of their products.
---------------------------------------------------------------------
Opinions expressed are my own, and are not intended to be an official
statement by Hewlett-Packard Company
---------------------------------------------------------------------
Name: James Gentles GM4WZP
Organization: Hewlett-Packard Queensferry Telecomunications Division
Email: jdg@hpqtdla.hp.com hp-sdd
Address: Station Road, South Queensferry, West Lothian, Scotland
---------------------------------------------------------------------
------------HPTRANS.C-----------cut_here_and_disgard_this_line--------------
/*
HPTRANS Revision 1.0 James Gentles 27th Feb 1990 jdg@hpqtdla.hp.com
This program accepts from stdinput a file created by the HPREAD program from
the HP28's IR link. This file is coded in the HP28 version of ASCII which
has special characters in locations 128-255. This program takes a file of
replacement characters (HPTABLE.ASC) and replaces the special HP28 characters.
The output to stdoutput is a file with all the special characters replaced
with a string of 1 or more characters from the look up table.
*/
#include <stdio.h>
main()
{
int c;
int i;
int j;
char string[128][10];
int keyflag[128];
char keychar[128][60];
FILE *fopen(), *tableF;
tableF = fopen("HPTABLE.ASC" , "r");
i=1;
while (i <= 128)
{
fscanf(tableF, "%s", string[i] ); /* Suck in 128 sets of 2 strings */
fscanf(tableF, "%s", keychar[i]); /* from HPTABLE.ASC */
Skeyflag[i]=0;
i+=1;
}
while ((c = getchar()) != EOF)
if (c <= 127) /* CHR 0 to 127 pass straight through */
putchar(c);
else
{
printf("%s" , string[(c-127)]);/* ELSE replace with string from */
keyflag[(c-127)] = 1; /* HPTABLE.ASC and set keyflag */
}
printf("\n \nSYMBOL KEY:\n"); /* Print Heading for Table */
i=1; /* then print strings that have */
while (i <=128) /* been used in listing. */
{
if(keyflag[i] ==1) printf("\n%s %s\n" , string[i], keychar[i] );
i+=1;
}
}
------------HPTABLE.ASC---------cut_here_and_disgard_this_line--------------
space$ 128:-Blank
div$ 129:-Division_line&dots
mul$ 130:-Multiply_cross
SQRT 131:-Square_root_symbol
int$ 132:-Integral
sig$ 133:-Sigma
|>$ 134:-Triangular_right_arrow
pi 135:-Symbolic_constant
delta$ 136:-Greek_delta
<= 137:-Less_than_&_equal_to
>= 138:-Greater_than_&_equal_to
<> 139:-Not_equal_to
alpha$ 140:-Greek_alpha
-> 141:-Right_hand_arrow
<- 142:-Left_hand_arrow
micro$ 143:-10E-6
lf$ 144:-L/F_symbol
deg$ 145:-Degree_symbol
<< 146:-Start_program_construct
>> 147:-End_program_construct
|-$ 148:-T_on_side
1 149:-Subscript_1
2 150:-Subscript_2
2 151:-Superscript_2
3 152:-Superscript_3
; 153:-Subscript/inverse_;
j 154:-Subscript_j
.. 155:-Double_dot
; 156:-Superscript/inverse_;
; 157:-Superscript_j
k 158:-Superscript_k
n 159:-Superscript_n
ang$ 160:-Angle_from_horizontal
A\$ 161:-A_grave
A^$ 162:-A_circumflex
E\$ 163:-E_grave
E^$ 164:-E_circumflex
E..$ 165:-E_umlaut
I^$ 166:-I_circumflex
I..$ 167:-I_umlaut
/$ 168:-acute
\$ 169:-grave
^ 170:-circumflex
..$ 171:_umlaut
~ 172:-tilde
u\$ 173:-u_grave
u^$ 174:-u_circumflex
pnd$ 175:-UK_pounds
- 176:-High_underscore
v/$ 177:-v_acute
y/$ 178:-y_acute
deg$ 179:-Degree_symbol
C,$ 180
c,$ 181
Nv$ 182
n~$ 183:-n_tilde
i 184:-Italic_i
?$ 185:-Inverted_?
XO$ 186
pnd2$ 187:-pound,only_1_bar
YT$ 188
sect$ 189:-Section_mark
f 190:-Italic_f
c|$ 191:-
a^$ 192:-a_circumflex
e^$ 193:-e_circumflex
o^$ 194:-o_circumflex
u^$ 195:-u_circumflex
a/$ 196:-a_acute
e/$ 197:-e_acute
o/$ 198:-o_acute
u/$ 199:-u_acute
a\$ 200:-a_grave
e\$ 201:-e_grave
o\$ 202:-o_grave
u\$ 203:-u_grave
a..$ 204:-a_umlaut
e..$ 205:-e_umlaut
o..$ 206:-o_umlaut
u..$ 207:-u_umlaut
Ao$ 208:-
i^$ 209:-i_circumflex
/O$ 210:-Greek_PHI
AE$ 211:-
ao$ 212:-
i/$ 213:-i_acute
/o$ 214:-Greek_phi
/x$ 215:-
A 216:-A_umlaut
i\$ 217:-i_grave
U..$ 218:-U_umlaut
u..$ 219:-u_umlaut
E/$ 220:-E_acute
i..$ 221:-i_umlaut
beta$ 222:-Greek_beta
o^ 223:-o_circumflex
A/$ 224:-A_acute
A~$ 225:-A_tilde
a~$ 226:-a_tilde
-D$ 227:-
delta+$ 228:-
I/$ 229:-I_acute
I\$ 230:-I_grave
o/$ 231:-o_acute
o\$ 232:-o_grave
O~$ 233:-O_tilde
o~$ 234:-o_tilde
Sv$ 235:-
sv$ 236:-
U/$ 237:-U_acute
Y/$ 238:-Y_acute
y..$ 239:-y_umlaut
P 240:-
|o$ 241:-
. 242:-Dot
micro$ 243:-1E-6
||$ 244:-
3/4$ 245:-Fraction_3/4
- 246:-Long_minus
1/4$ 247:-Fraction_1/4
1/2$ 248:-Fraction_1/2
a_$ 249:-
o_$ 250:-
<< 251:-Start_program_construct
[] 252:-Solid_block
>> 253:-End_program_construct
+-$ 254:-Plus/minus
space$ 255:-Blank
-----------------------------------------------
HPTABLE.ASC Look-up Table for HPTRANS Programme
Revision 1.0 27th Feb 1990 jdg@hpqtdla.hp.com
The first 128 lines of this file contain two
strings per line, representing a look-up table
to translate 8bit HP28 characters to 7bit ASCII.
The 128 lines represent character codes 128-255,
string one is the ASCII replacement string, and
string two is a description used in a key table.
------------HPFORMAT.ASC--------cut_here_and_disgard_this_line--------------
/*
HPFORMAT Revision 1.0 James Gentles 27th Feb 1990 jdg@hpqtdla.hp.com
This program is used to format the output from a HP28 calculator via
its IR link via HPREAD. It is suggested that the text be put through
HPTRANS first to remove any special characters.
The program takes the input on stdinput and sends the formatted output
to stdoutput. The 23 column input is changed to approximately 45 column,
and the HP28's indenting is maintained.i
This program will only work with computers using the ASCII code
This source is written in C
*/
#include <stdio.h>
main()
{
int c;
int i;
int tindent;
int indent;
int linelength;
int linepos;
int iplinepos;
int tiplpos;
iplinepos = 0;
tiplpos = 0;
linepos = 1;
indent = 0;
tindent= 0;
linelength=40;
while ((c = getchar()) != EOF)
{
iplinepos+=1; /* Keep track of stdinput column */
if (c == '\n')
{
tiplpos = iplinepos;
iplinepos=0;
tindent = 0;
do
{
c = getchar(); /* if c/r count number of spaces (indent) */
iplinepos+=1; /* at beginning of the next line */
if (c == 32)
tindent+=1;
}
while (c == 32);
if (tindent != 0) /* set up new indent and send it to stdop */
{
indent = tindent;
putchar('\n');
for (i =1; i <= indent; i+=1)
putchar(32);
linepos = indent + 1;
}
else
if (tiplpos < 15)
putchar('\n'); /* if no indnet and near beginning of */
/* line then start new line */
else
putchar(32); /* ignore c/r and replace with space */
putchar(c);
if (c!='\n')
linepos+=1; /* Increment output column unless c/r */
else
linepos =1;
}
else
{
putchar(c);
linepos+=1;
}
if ((linepos >= linelength) && ((c==32) || (c==39) || (c==41) ||
(c==42) || (c==43) || (linepos>= (linelength + 10)) ))
{ /* at convenient point at end of output line do a c/r */
putchar('\n');
for (i = 1; i <= indent; i+=1)
putchar(32);
linepos = indent + 1;
}
}
}