PROGRAM castin; {$nomain} { File:[22,310]CASTIN.PAS Author: Phil Hannay 14-Jan-87 (patterned after CASTWO.PAS) Last Edit: 23-JUN-1988 22:05:43 History: 23-JUN-1988 21:55:32 - JMB PA3UTL upgrade. } {$NOLIST} {[a+,b+,l-,k+,r+] Pasmat } %INCLUDE 'PAS$EXT:General.typ'; %INCLUDE 'PAS$EXT:Error.ext'; %INCLUDE 'PAS$EXT:CASTWO.EXT'; {$LIST} PROCEDURE Castin(VAR asc: PACKED ARRAY [lo..hi: integer] OF char; VAR Int: integer; VAR pos: integer); EXTERNAL; {*USER* Pascal-3 procedure which converts an input string of ASCII characters in ASC to an integer INT (signed binary word) using a decimal (base 10) radix. POS specifies starting point in the string (array). Upon exit from this procedure, POS will be left pointing to the position of the terminating character or the end of the string, whichever comes first. Leading space or tab character(s) are ignored. The number will be considered negative if a leading "-" minus sign is encountered, and the number will be considered positive is a leading "+" plus sign or no sign at all is encountered. The plus or minus sign needs to preceed the first ascii digit, but can be separated from that first digit by any number of (ignored) space or tab characters. Any non-digit following the first valid digit will terminate the conversion. This includes a period (decimal point), a comma, a blank, or any other non digit. In any case, POS will be left pointing at this terminating character, so you may use it to go on to the next number. Thus you can parse strings like "34,+55,+ 45, -834,,3". Where no valid digit is encountered before the next terminator (such as the ",," in the example), a value of zero will be returned. Likewise a number like "345.344" could be parsed into two integers, the first representing the number before the decimal point, the second the number after the decimal. Remember that this routine handles arrays using the string conventions. The length of a type 0 string is determined by the 0 element of the array, and the length of a type 1 string is determined by the first null character in the string. Be careful if you use strings made up of left justified numbers with extra blank padding to the right of the number. The first blank encountered will act as the terminator. If you keep POS where it is and call CASTIN again, the remaining blanks will be read as another number and give you a zero. This is nice in that an all blank string like " " will return a value of zero. It does also mean that a string like "34 " will return a value of 34, the first time you call CASTIN, and if you do not alter POS, will return a 0, the second time you call CASTIN. Integer overflow (greater than +32767 or less than -32768) is indicated by a negative POS value. No error messages are issued on integer overflow, so caller must check POS if overflow possiblity exists. On the other hand, this also permits the caller to use this routine to validate input to insure that the ascii string represents a valid integer. } {*WIZARD* The input string is converted to a signed word in INT. The radix is assumed to be decimal. Thus the range that the ascii string can represent is +32767 down thru -32768. If overflow occurs, and error message is output, and INT retains the last valid value, and POS is set negative. A leading plus (+) or minus (-) sign will be recognized, with a minus sign overriding a positive sign in the unlikely event that the two are used together. After the occurance of a valid digit, the plus and minus signs are considered valid terminating characters. Periods (decimal points) and commas are considered valid terminating characters. Note: This routine will handle type 1 strings, type 0 strings, and ordinary packed arrays. There is some differences in behavior that need to be understood. The upper limit of the variable ASC will be determined by the byte integer value in ASC[0] in type 0 strings. However, in type 1 strings and ordinary packed arrays, there is not clear definition of the upper limit. A type 1 string upper limit is defined by the the occurance of a character in the string. But an ordinary packed array could also have a null, without any intention of being a type 1 string. For this reason, we use the upper limit of the array for ASC variables that are not type 0 strings, and treat type 1 strings as if they were ordinary packed arrays. The action of this conversion routine is the same for all types of ASC, but they are not handled the same internally in this procedure. } PROCEDURE Castin; LABEL 999; { used for premature exit on error } CONST Debug = false; VAR Bpos, Limit : integer; Bin, Max : Word; Positive: boolean; {set true if number is positive} BEGIN {Initialize some stuff.} Positive := true; {assume positve number} Int := 0; {assume zero - if no ascii digits found, will return zero} IF ((lo = 0) AND (pos < 1)) OR (pos > hi) THEN BEGIN error(4, warning_err, 'CASTIN -- Illegal postition:', pos); GOTO 999 END; if lo = 0 then limit:= ord(asc[0]) else limit:= hi; { skip leading spaces,tabs,zeros,plus sign or minus signs } Bpos := pos; WHILE (Bpos < Limit) AND (ord(asc[Bpos]) IN [40B, 11B, 60B, 53B, 55B]) DO BEGIN { If minus sign encountered, set postive false to indicate negative number } IF ord(asc[Bpos]) IN [55B] THEN Positive := false; Bpos := Bpos + 1; END; IF (Bpos = Limit) AND (ord(asc[Bpos]) IN [40B, 11B, 60B, 53B, 55B]) THEN BEGIN { zero or nothing to convert } IF Debug THEN writeln('no bpos found'); pos := Limit; GOTO 999 END; { Now convert the number using CASTWO radix 10 } Pos:= Bpos; CASTWO(Asc, Bin, Pos, 10); if positive then max:= 77777B else max:= 100000B; if debug then writeln ('max=',max:-6,' bin=',bin:-6); if Bin > max then begin { overflow } Pos:= pos * (-1); GOTO 999; end else begin { okay, assign pos or neg} Int:= Loophole (integer, Bin); if not(positive) then Int:= Int * (-1); end; 999: END;