{ex6.source 00/02/10 nm -e ex6p.debugboo} $pagewidth 120, lines 44$ $standard_level 'os_features'$ $type_coercion 'representation'$ $tables on, statement_number on, code_offsets on$ $list_code on$ $optimize off$ {=============================================================== Disclaimer: This program has several sloppy coding practices that can (and have) led to problems. They were put in to help demonstrate program aborts ... I don't *really* code that way! --------------------------------------------------------------- Note: This program uses PRINT in an effort to avoid using the Pascal/XL I/O package (e.g., writeln). This shortens the amount of code emitted by the compiler, which makes it easier to use as a tool for teaching about Debug. --------------------------------------------------------------- Program description: Take two 4-digit numbers from INFO string, add them, print result. --------------------------------------------------------------- Exercise 6.1: When run without an INFO=, the program aborts. Find the cause. (You can fix it, if you want.) Exercise 6.2: When run as: run ex6; info = "1111 2345" the "sum" is correct: 3456 When run as: run ex6; info = "1111 23456" the program aborts. Why? On what line of source code? (You can fix it, if you want.) ===============================================================} program ex6 (info); type byte = 0..255; {occupies 1 byte} good_failed = (failed, good); pac4 = packed array [1..4] of char; pac80 = packed array [1..80] of char; str4 = string [4]; str16 = string [16]; var buf : string [80]; c : char; info : pac80; sum : pac4; x : pac4; y : pac4; zero : pac4; {'0000'} Function ascii : shortint; intrinsic; Function dascii : shortint; intrinsic; Procedure debug; intrinsic; Procedure hpdebug; intrinsic; Procedure print; intrinsic; Procedure terminate; intrinsic; Function z1_to_i (c : char) : integer; forward; {*************************************************} function add (var x : pac4; var y : pac4) : pac4; var carry : integer; {0 or 1} dig : integer; {sum of two digits} inx : integer; sum : pac4; begin carry := 0; for inx := sizeof (x) downto 1 do begin dig := z1_to_i (x [inx]) + z1_to_i (y [inx]) + carry; if dig > 9 then begin carry := 1; dig := dig - 10; end; sum [inx] := chr (dig + ord ('0')); end; add := sum; {return the sum} end {add proc}; {*************************************************} function num32 (n : integer) : str16; {Returns string version of integer n} {e.g.: num32 (123) --> '123' } var len : shortint; s : str16; begin len := dascii (n, 10, s); setstrlen (s, len); num32 := s; end {num32 proc}; {*************************************************} function pac4_to_str (cccc : pac4) : str4; {"converts" a pac4 type into a 4 char string} var s : str4; begin setstrlen (s, 4); s [1] := cccc [1]; s [2] := cccc [2]; s [3] := cccc [3]; s [4] := cccc [4]; pac4_to_str := s; end {pac4_to_str proc}; {*************************************************} function parse_info (var x : pac4; var y : pac4) : good_failed; { Purpose: scans INFO string and grabs the two 4 digits numbers that should be in it. The first number is put into x, the second into y. If all goes well, 'good' is returned, otherwise 'failed'. } label 999; {at end of routine} var err : integer; info_inx : integer; {current index in info} inx : integer; len : integer; {------------------} procedure find_blank; begin while info [info_inx] <> ' ' do info_inx := info_inx + 1; end {find_blank proc}; {------------------} procedure find_non_blank; begin {skip forward as long as the "current" } {character is a blank... } while info [info_inx] = ' ' do info_inx := info_inx + 1; {ok, we found a non-blank ... count length...} len := 1; while info [info_inx + len] <> ' ' do len := len + 1; end {find_non_blank proc}; {------------------} begin parse_info := good; {initial assumption} err := 0; x := zero; y := zero; info_inx := 1; {first byte} find_non_blank; for inx := 1 to len do x [inx] := info [info_inx + inx - 1]; find_blank; find_non_blank; for inx := 1 to len do y [inx] := info [info_inx + inx - 1]; 999: if err <> 0 then begin parse_info := failed; buf := 'parse_info failed, error # ' + num32 (err); print (buf, - strlen (buf), 0); end; end {parse_info proc}; {*************************************************} function z1_to_i (c : char) : integer; {Convert a single char '0', ..., '9' to binary 0, ..., 9} {Note: does not check that c is in '0'...'9'. } begin z1_to_i := ord (c) - ord ('0'); end {z1_to_i proc}; {*************************************************} begin zero := '0000'; {go into INFO string and find two numbers to add...} if parse_info (x, y) = good then begin sum := add (x, y); buf := pac4_to_str (x) + ' + ' + pac4_to_str (y) + ' --> ' + pac4_to_str (sum); print (buf, -strlen (buf), 0); end else begin buf := 'ADD not done.'; end; end.