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