(* UCSD PASCAL I.5 P-SYSTEM "RADIX" *) PROGRAM CONVERSION; CONST ORDA = 65; {ASCII value of the character 'A'; ORD('A') } ORD0 = 48; {ASCII value of the character '0'; ORD('0') } { The following values are terminal DEPENDENT } EEOLN = 29; {Erase to end of line} EEOS = 11; {Erase to end of screen} ESCAPE = 27; TYPE OREC = PACKED ARRAY[0..4] OF 0..7; {High order bit comes from BREC } HREC = PACKED ARRAY[0..3] OF 0..15; BREC = PACKED ARRAY[0..15] OF 0..1; LETSET = SET OF '0'..'F'; OCTSTR = STRING[6]; { These types are declared so as to allow type } HEXSTR = STRING[4]; { checking of parameters passed to procedures in } BINSTR = STRING[16]; { this program. Octal and Integer have the same } { maximum length. No need to declare twice } XRANGE = 0..2; { This is for the arrays which determine the position of } YRANGE = 0..2; { where to writeout the information } ACROSS = 0..79; { 80 Characters across screen } DOWN = 0..23; { 24 Lines down the screen } VAR R: RECORD CASE INTEGER OF { Takes all the packed arrays above plus an } 1: (INT: INTEGER); { Integer and assigns them all to read out of } 2: (OCTREC: OREC); { the same word. Thus an octal value placed } 3: (HEXREC: HREC); { in the record can be read out as an integer } 4: (BINREC: BREC); { using INT. } END; CH: CHAR; OCTLET, BINLET, DECLET, HEXLET: LETSET; { Test sets for valid input } OCTX, NUMX, BINX, INTX, HEXX: PACKED ARRAY[XRANGE] OF ACROSS; OCTY, NUMY, BINY, INTY, HEXY: PACKED ARRAY[YRANGE] OF DOWN; { Arrays for positioning output correctly } X: XRANGE; { Global indices for the above arrays } Y: YRANGE; PROCEDURE PROMPT(S: STRING); { Displays any string on the top line } BEGIN GOTOXY(0,0); WRITE(S); WRITE(CHR(ESCAPE),CHR(EEOLN)); { Clears the line after the string } END; (* PROMPT *) PROCEDURE CLEARSCREEN; { Clears the entire screen } BEGIN GOTOXY(0,0); WRITE(CHR(ESCAPE),CHR(EEOS)); END; (* CLEARSCREEN *) PROCEDURE INIT; { Initialize } VAR I: INTEGER; BEGIN HEXLET:=['A'..'F']; { Initializes the test sets for input testing } DECLET:=['0'..'9']; OCTLET:=['0'..'7']; BINLET:=['0'..'1']; FOR I:=0 TO 2 DO { Initializes the writeout positioning arrays } BEGIN NUMX[I]:=9 + (I * 27); INTX[I]:=9 + (I * 27); HEXX[I]:=9 + (I * 27); OCTX[I]:=9 + (I * 27); BINX[I]:=9 + (I * 27); END; FOR I:=0 TO 2 DO BEGIN NUMY[I]:=3 + (I * 6); INTY[I]:=4 + (I * 6); HEXY[I]:=5 + (I * 6); OCTY[I]:=6 + (I * 6); BINY[I]:=7 + (I * 6); END; END; (* INIT *) PROCEDURE INITSCREEN; { Initializes the screen and the screen indices, X and Y } VAR I,J,K: INTEGER; NAME: PACKED ARRAY[3..7] OF STRING; BEGIN CLEARSCREEN; X:=0; Y:=0; NAME[3]:='NUMBER :'; NAME[4]:='INTEGER:'; NAME[5]:='HEX :'; NAME[6]:='OCTAL :'; NAME[7]:='BINARY :'; FOR I:=3 TO 7 DO FOR J:=0 TO 2 DO FOR K:=0 TO 2 DO BEGIN GOTOXY(J * 27, I + (K * 6)); WRITE(NAME[I]); END; END; (* INITSCREEN *) PROCEDURE DECTO(NUM: OCTSTR; VAR NUMVALID: BOOLEAN); { Procedure takes a string and converts it into an Integer } VAR I: INTEGER; MINUS: BOOLEAN; BEGIN MINUS:=FALSE; NUMVALID:=TRUE; WITH R DO BEGIN INT:=0; IF NUM[1] = '-' THEN BEGIN MINUS:=TRUE; DELETE(NUM,1,1); END; I:=1; WHILE (I <= LENGTH(NUM)) AND NUMVALID DO BEGIN { Loop reads from left to right and adds value of new c } { character to 10 times the old value. Also checks for } { overflow and valid input. } IF NUM[I] IN DECLET THEN IF (INT < 3277) AND ( ORD(NUM[I]) - ORD0 <= 8 ) THEN INT:=(INT*10) + ORD(NUM[I]) - ORD0 ELSE NUMVALID:=FALSE ELSE NUMVALID:=FALSE; I:=I+1; END; (* WHILE *) IF MINUS THEN { This works on -32768 because -32768 is its } IF INT <= 32767 THEN { own negation in two's complement } INT:= -INT ELSE NUMVALID:=FALSE; END; (* WITH *) IF NOT NUMVALID THEN BEGIN GOTOXY(NUMX[X],NUMY[Y]); WRITE(' ':16); PROMPT('INVALID INTEGER NUMBER. Type to continue'); END; END; (* DECTO *) PROCEDURE HEXTO(NUM: HEXSTR; VAR NUMVALID: BOOLEAN); { Procedure takes a string and converts it into a Hexadecimal number } VAR I,J: INTEGER; BEGIN WITH R DO BEGIN FOR I:=0 TO 3 DO HEXREC[I]:=0; I:=0; NUMVALID:=TRUE; J:=LENGTH(NUM); WHILE (J >= 1) AND NUMVALID DO BEGIN { Loop reads from right to left and puts the value of the } { character into the next array element. Also checks for } { valid input } IF NUM[J] IN HEXLET THEN HEXREC[I]:= ORD(NUM[J])-ORDA + 10 ELSE IF NUM[J] IN DECLET THEN HEXREC[I]:=ORD(NUM[J])-ORD0 ELSE NUMVALID:=FALSE; J:=J-1; I:=I+1; END; (* WHILE *) END; (* WITH *) IF NOT NUMVALID THEN BEGIN GOTOXY(NUMX[X],NUMY[Y]); WRITE(' ':16); PROMPT('INVALID HEXADECIMAL NUMBER. Type to continue'); END; END; (* HEXTO *) PROCEDURE OCTTO(NUM: OCTSTR; VAR NUMVALID: BOOLEAN); { Procedure takes a string and converts it to an Octal number } VAR I,J: INTEGER; BEGIN WITH R DO BEGIN FOR I:=0 TO 4 DO OCTREC[I]:=0; IF LENGTH(NUM) = 6 THEN { If there is a high order byte get its value } BEGIN BINREC[15]:=ORD(NUM[1])-ORD0; DELETE(NUM,1,1); END ELSE { or else set it to zero } BINREC[15]:=0; I:=0; NUMVALID:=TRUE; J:=LENGTH(NUM); WHILE (J >= 1) AND NUMVALID DO BEGIN { Loop reads from right to left and puts the value of the } { character into the next array element. Also checks for } { valid input } IF NUM[J] IN OCTLET THEN OCTREC[I]:=ORD(NUM[J])-ORD0 ELSE NUMVALID:=FALSE; J:=J-1; I:=I+1; END; (* WHILE *) END; (* WITH *) IF NOT NUMVALID THEN BEGIN GOTOXY(NUMX[X],NUMY[Y]); WRITE(' ':16); PROMPT('INVALID OCTAL NUMBER. Type to continue'); END; END; (* OCTTO *) PROCEDURE BINTO(NUM: BINSTR; VAR NUMVALID: BOOLEAN); { Procedure takes a string a converts it into a binary number } VAR I,J: INTEGER; BEGIN WITH R DO BEGIN FOR I:=0 TO 15 DO BINREC[I]:=0; I:=LENGTH(NUM); NUMVALID:=TRUE; J:=0; WHILE (I >= 1) AND NUMVALID DO BEGIN { Loop reads from right to left and puts the value of the } { character into the next array element. Also checks for } { valid input. } IF NUM[I] IN BINLET THEN BINREC[J]:=ORD(NUM[I])-ORD0 ELSE NUMVALID:=FALSE; I:=I-1; J:=J+1; END; (* WHILE *) END; (* WITH *) IF NOT NUMVALID THEN BEGIN GOTOXY(NUMX[X],NUMY[Y]); WRITE(' ':16); PROMPT('INVALID BINARY NUMBER. Type to continue'); END; END; (* BINTO *) PROCEDURE WRITEOUT; { Procedure writes out all the elements of global variable R to the appropiate } { section of the screen and then increments X and Y } VAR I: INTEGER; BEGIN GOTOXY(INTX[X],INTY[Y]); WRITE(R.INT); GOTOXY(HEXX[X],HEXY[Y]); FOR I:=3 DOWNTO 0 DO IF R.HEXREC[I] < 10 THEN WRITE(R.HEXREC[I]) ELSE WRITE(CHR(ORD(R.HEXREC[I])-10+ORDA)); GOTOXY(OCTX[X],OCTY[Y]); WRITE(R.BINREC[15],R.OCTREC[4],R.OCTREC[3],R.OCTREC[2],R.OCTREC[1], R.OCTREC[0]); GOTOXY(BINX[X],BINY[Y]); FOR I:=15 DOWNTO 0 DO WRITE(R.BINREC[I]); IF X = 2 THEN { If end of row } BEGIN IF Y = 2 THEN { If end of screen } BEGIN PROMPT('Type to clear the screen and continue'); READ(CH); INITSCREEN; END ELSE Y:=Y+1; X:=0; END ELSE X:=X+1; END; (* WRITEOUT *) PROCEDURE OUTER; { This procedure is the outer loop and only working loop of the program. } { It reads all user input and calls the appropiate procedure. } VAR CH: CHAR; STR: STRING; NUMVALID,VALID: BOOLEAN; O: OCTSTR; { For passing strings to the procedures. Octal and } H: HEXSTR; { Integer have the same size string. } B: BINSTR; BEGIN INIT; INITSCREEN; REPEAT VALID:=TRUE; PROMPT( 'Type the number followed by the Radix (H,O,I,B), or type C(learscreen, Q(uit'); GOTOXY(NUMX[X],NUMY[Y]); READLN(STR); IF LENGTH(STR) = 0 THEN VALID:=FALSE ELSE IF STR[LENGTH(STR)] IN ['H','O','B','I','C','Q'] THEN CASE STR[LENGTH(STR)] OF 'Q' : EXIT(OUTER); 'C' : INITSCREEN; 'I' : BEGIN DELETE(STR,LENGTH(STR),1); { Delete radix character } IF (LENGTH(STR) > 6) OR (LENGTH(STR) = 0) THEN VALID:=FALSE ELSE BEGIN O:=STR; DECTO(O,NUMVALID); IF NUMVALID THEN WRITEOUT ELSE READ(CH); END; END; 'H' : BEGIN DELETE(STR,LENGTH(STR),1); { Delete radix character } IF (LENGTH(STR) > 4) OR (LENGTH(STR) = 0) THEN VALID:=FALSE ELSE BEGIN H:=STR; HEXTO(H,NUMVALID); IF NUMVALID THEN WRITEOUT ELSE READ(CH); END; END; 'O' : BEGIN DELETE(STR,LENGTH(STR),1); { Delete radix character } IF (LENGTH(STR) > 6) OR ( LENGTH(STR) = 0) THEN VALID:=FALSE ELSE BEGIN O:=STR; OCTTO(O,NUMVALID); IF NUMVALID THEN WRITEOUT ELSE READ(CH); END; END; 'B' : BEGIN DELETE(STR,LENGTH(STR),1); IF (LENGTH(STR) > 16) OR (LENGTH(STR) = 0) THEN VALID:=FALSE ELSE BEGIN B:=STR; BINTO(B,NUMVALID); IF NUMVALID THEN WRITEOUT ELSE READ(CH); END; END; END (* CASE *) ELSE VALID:=FALSE; (* END OF IF RADIX IN SET *) IF NOT VALID THEN BEGIN PROMPT('INVALID INPUT. Type to continue.'); GOTOXY(NUMX[X],NUMY[Y]); WRITE(' ':17); { Blank out bad input } READ(CH); END; UNTIL 1 = 2; {FOREVER} END; (* OUTER *) PROCEDURE HEADER; BEGIN CLEARSCREEN; WRITELN(' This program will convert numbers specified as HEX, OCTAL,'); WRITELN('INTEGER and BINARY numbers to the other radices.'); WRITELN; WRITELN(' Simply type the number followed by the first letter of the'); WRITELN('radix it is in, (i.e. 7BC9H, -12789I, 110010100B, 177760O )'); WRITELN('followed by a carriage return.'); WRITELN; WRITELN(' This program works only with uppercase characters. Lower '); WRITELN('case characters will give "INVALID INPUT" responses. '); WRITELN; WRITELN(' For further information see the document.'); WRITELN; WRITELN; WRITELN(' Type a to continue; Q(uit'); END; BEGIN (* MAIN *) HEADER; READ(CH); OUTER; END. { +------------------------------------------------------------------+ | | | F I N I S | | | +------------------------------------------------------------------+ }