{$nomain}
{$nowalkback}

{

File			: SC:[22,320]CASTRE.PAS
Author			: Peter Stadick
Origin Date		: March 31,1987
Edit History		:

	       Last Edit: 25-NOV-1987 10:24:48 

Description:

	This callable routine will convert an ascii conforment array to
	a real number. This routine assumes base 10 numbers. It will also
	ignore leading spaces, compress out commas and quit conversion
	as soon as it incounters a non-digit after digits. If the number
	is preceeded by an hyphen it will make the result negative. You can
	also specify were in the array you want conversion to begin. The
	maximum size of a number the routine can handle is 30 digits but
	this can be easily changed by recompiling. Also this routine does not
	like commas after the decimal point.
}


PROCEDURE castre(VAR rea:real;
		 asc: PACKED ARRAY [lo..hi:INTEGER] OF CHAR;
		 start: INTEGER); EXTERNAL;

PROCEDURE castre; 

CONST
  max_number_size = 30;

VAR
  in_pos : INTEGER;
  out_pos : INTEGER;
  all_done : BOOLEAN;
  negitive : BOOLEAN;
  started  : BOOLEAN;
  dec_found : BOOLEAN;
  dec_pos : INTEGER;
  asc_num : PACKED ARRAY [1..max_number_size] OF CHAR;
  multiplyer : REAL;
  i : integer;

BEGIN
  all_done := false;
  IF (start > 0) THEN
    in_pos := start + lo - 1
  ELSE
  BEGIN
    in_pos := lo;
    all_done := true;
  END;
  negitive := false;
  started := false;
  dec_found := false;
  out_pos := 0;
  dec_pos := max_number_size + 1;

  WHILE ((asc[in_pos] = ' ') OR (asc[in_pos] = ',') OR (asc[in_pos] = '.') OR
        (asc[in_pos] = '-') OR ((asc[in_pos] >= '0') AND 
	(asc[in_pos] <= '9'))) AND NOT all_done DO
  BEGIN
    CASE asc[in_pos] OF
    ','		: IF dec_found THEN all_done := true;
    '.'		: IF dec_found THEN all_done := true
 		  ELSE BEGIN
		    dec_found := true;
                    started := true; 
                    out_pos := out_pos + 1;
                    dec_pos := out_pos;
                    asc_num[out_pos] := '.'; 
                    IF out_pos = max_number_size THEN all_done := true;
                  END;
    ' ' 	: IF started THEN all_done := true;
    '-'		: IF started THEN all_done := true
		  ELSE negitive := true;
    OTHERWISE   BEGIN
                  started := true;
                  out_pos := out_pos + 1;
                  asc_num[out_pos] := asc[in_pos];
                  IF out_pos = max_number_size THEN all_done := true;
		END;
    END; { case }

    { Advance character count in array }
    IF in_pos = hi THEN 
      all_done := true
    ELSE
      in_pos := in_pos + 1;

  END; { while }

  { Now convert number before decimal point }
  rea := 0.0;
  IF NOT dec_found AND (out_pos < max_number_size) THEN
  BEGIN
    out_pos := out_pos + 1;
    dec_pos := out_pos;
    dec_found := TRUE;
  END;

  IF (dec_pos > 1) OR NOT dec_found AND (start > 0) THEN
  BEGIN
    multiplyer := 1.0;
    FOR i := dec_pos - 1 DOWNTO 1 DO
    BEGIN
      rea := rea + (ORD(asc_num[i]) - ORD('0')) * multiplyer;
      multiplyer := multiplyer * 10.0;
    END;
  END;

  { Now do digits after decimal place }
  IF (dec_pos < max_number_size) AND dec_found AND (out_pos > dec_pos) AND
     (start > 0) THEN
  BEGIN
    multiplyer := 0.1;
    FOR i := dec_pos + 1 TO out_pos DO
    BEGIN
      rea := rea + (ORD(asc_num[i]) - ORD('0')) * multiplyer;
      multiplyer := multiplyer * 0.1;
    END;
  END;

  { Now add on negitive if need be }
  IF negitive THEN rea := rea * (-1.0);

{ castre }
END;
