subroutine apthexd (asrce, isrce, nchar, iamax, idmax, iemax, & aword, iword, fword, mtype, nerr) ccbeg. cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c SUBROUTINE APTHEXD c c call apthexd (asrce, isrce, nchar, iamax, idmax, iemax, c & aword, iword, fword, mtype, nerr) c c Version: apthexd Updated 1997 August 4 11:20. c apthexd Originated 1993 February 16 11:50. c c Author: Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123. c c c Purpose: To translate a hexadecimal character string to a decimal c integer or floating point number, if possible. c The string is in array asrce, starting at character position c isrce, and has a length of nchar characters. c The word length in character array aword is iamax characters. c Integers may have up to idmax hexadecimal digits. c Floating point numbers may have exponents up to iemax c hexadecimal digits. c The results are stored in the character array aword, the c decimal integer word iword, and/or the floating point word c fword, depending on the data type of the string, mtype. c Flag nerr indicates any input or result error. c c Note: Do not convert this source file to all upper or lower case. c It contains both upper and lower case character variables. c c Input: asrce, isrce, nchar, idmax, iemax. c c Output: aword, iword, fword, mtype, nerr. c Note: do not equivalence fword and iword. c c Glossary: c c asrce Input A character array, containing the character string to c be translated, starting in character position isrce, c with a length of nchar characters. c c aword Output A character array containing iamax characters per word, c compatible with a calling routine argument of type c character*iamax, or iamax words of type character*1, c etc. Always filled with up to iamax characters of c the character string, and right-filled with blanks c as necessary. c c fword Output A decimal floating point number, initialized to zero. c The maximum allowable exponent is iemax. c If the string is translated into an integer c (mtype = 2) or into a decimal floating point number c (mtype = 3), its floating point value will be c returned in fword. If the string is formatted as an c integer, but contains more than idmax digits after c any leading zeros, it will be translated into a c floating point number, and returned in fword. c The character string may have leading or trailing c blanks. The first non-blank character may be a "+" c or "-". The mantissa may contain any positive number c of digits, but no more than one decimal point, and c may have trailing blanks. If an exponent is given, c it must begin with "h", "H", "+" or "-". c An initial "h" or "H", may be followed by c a "+" or "-". The digits of the exponent may have c leading and trailing blanks, but no additional c characters following any trailing blanks. c Note: do not equivalence iword to fword. c c iamax Input Number of characters in each word of type character c array aword. c c idmax Input Maximum number of digits in an integer. Depends on c the machine. c Must be positive. c c iemax Input Maximum size (positive or negative) of the exponent c of a floating point number. Depends on the machine. c Approximately 308 on a 64-bit floating point machine. c Must be positive. c c isrce Input The character position in array asrec of the first c character of the string. E. g., isrce = 1 means c the leftmost character of asrce(1). c Must be positive. c c iword Output An integer. Initialized to zero. The maximum number c of digits is idmax. If the character string is c translated into an integer (mtype = 2), iword will c contain its decimal integer value, and fword will c contain its decimal floating point value. c Note: do not equivalence fword and iword. c The character string may have leading or trailing c blanks. For a hexadecimal number, the first c non-blank character may be a "+" or "-". c All other characters must be hexadecimal digits, c with no more than idmax digits following any leading c zeros. c c mtype Output An integer. Indicates the data type of the character c string, and which results are returned: c 0: Not recognizable as a hexadecimal integer or c floating point number, and longer than iamax c characters (nerr = 0), or a hexadecimal c floating point number whose exponent exceeds the c limit iemax (nerr = 5). c Returned in aword. c 1: Not recognizable as a hexadecimal integer or c floating point number. String has 1 to iamax c characters. c Returned in aword, left-adjusted, right-filled c with blanks, as necessary. c 2: Character string translated into decimal integer c mode. The integer value is returned in iword, c and the decimal floating point value is returned c in fword. c Also returned in aword, as for mtype = 1. c 3: Character string translated into decimal c floating point mode, and returned in fword. c The integer value can not be stored in iword, c because of the possibility of overflow of numbers c with large exponents. If nerr = 4, the character c string was an integer with more than idmax c digits. c Also returned in aword, as for mtype = 1. c c nerr Output Indicates an input or result error, if not zero. c 1 if nchar is not positive. c 2 if isrce is not positive. c 3 if iamax, idmax or iemax is not positive. c 4 if an integer exceeds idmax characters. If so, c a floating point result is returned in fword, c with mtype = 3. c 5 if a floating point exponent exceeds iemax. c If so, a character string is returned in aword, c with mtype = 0. c c nchar Input The number of characters in the character string. c cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccend. c.... Declarations for arguments. dimension asrce (1) ! Array of characters. character*1 asrce ! Array of characters. dimension aword (1) ! Character interpretation of string. character*1 aword ! Character interpretation of string. c.... Local variables. common /lapthexd/ fintadd ! Floating point idig - 1. common /lapthexd/ fintval ! Floating point mantissa value. common /lapthexd/ fsign ! Indicates sign of mantissa. common /lapthexd/ icharm ! Index in aword. common /lapthexd/ idig ! Index in array adigit or bdigit. common /lapthexd/ intval ! Integer mantissa value. common /lapthexd/ ipt ! Indicates position of decimal point. common /lapthexd/ isign ! Indicates sign of mantissa. common /lapthexd/ kdigit ! Number of exponent digits. common /lapthexd/ kexp ! Integer exponent value. common /lapthexd/ ksign ! Indicates sign of exponent. common /lapthexd/ nbeg ! Index in the string. common /lapthexd/ nc ! Index in the string. common /lapthexd/ ndigall ! Number of mantissa digits. common /lapthexd/ ndigit ! Number of significant digits. common /lapthexd/ nzeros ! Number of zeroes to insert. common /capthexd/ achar ! A single character in string. character*1 achar dimension adigit(16) ! Integer digits from 0 to F. character*1 adigit data adigit / '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', & 'A', 'B', 'C', 'D', 'E', 'F' / dimension bdigit(16) ! Integer digits from 0 to f. character*1 bdigit data bdigit / '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', & 'a', 'b', 'c', 'd', 'e', 'f' / cbugc***DEBUG begins. cbug common /lapthexd/ nmaxa ! # of characters of asrce to write. cbug 9901 format (/ 'apthexd translating an ASCII word.' / cbug & ' isrce=',i6,' nchar=',i6, cbug & ' iamax=',i3,' idmax=',i3,' iemax=',i6) cbug 9902 format (' asrce=',64a1) cbug write ( 3, 9901) isrce, nchar, iamax, idmax, iemax cbug nmaxa = 8 * (1 + (isrce + nchar - 2) / 8) cbug write ( 3, 9902) (asrce(nc), nc = 1, nmaxa) cbugc***DEBUG ends. c.... Initialize the output. nerr = 0 mtype = 1 iword = 0 fword = 0.0 do 105 nc = 1, iamax ! Loop over output characters. aword(nc) = ' ' 105 continue ! End of loop over output characters. c.... Test for input errors. if (nchar .le. 0) then nerr = 1 go to 210 endif if (isrce .le. 0) then nerr = 2 go to 210 endif if ((iamax .le. 0) .or. (idmax .le. 0) .or. (iemax .le. 0)) then nerr = 3 go to 210 endif c.... Put up to iamax characters of string into aword. icharm = nchar if (icharm .gt. iamax) then mtype = 0 ! Type character (>iamax) or bad f-p. icharm = iamax endif do 110 nc = 1, icharm ! Loop over output characters. aword(nc) = asrce(isrce+nc-1) 110 continue ! End of loop over output characters. cbugcbugc***DEBUG begins. cbugcbug 9701 format ('aword= ',24a1) cbugcbug write ( 3, 9701) (aword(nc), nc = 1, 24) cbugcbugc***DEBUG ends. c=======================================================================-------- c.... Look for the beginning of the mantissa field for integers and c.... floating point numbers. Find the first non-blank character. do 115 nc = 1, nchar ! Loop over character string. achar = asrce(isrce+nc-1) if (achar .ne. ' ') go to 120 115 continue ! End of loop over character string. cbugcbugc***DEBUG begins. cbugcbug 9702 format ('asrce all blank.') cbugcbug write ( 3, 9702) cbugcbugc***DEBUG ends. go to 210 ! All characters are blank. c.... See if the first non-blank character is "+" or "-". 120 if (achar .eq. '-') then nc = nc + 1 isign = -1 fsign = -1.0 elseif (achar .eq. '+') then nc = nc + 1 isign = 1 fsign = 1.0 else isign = 1 fsign = 1.0 endif cbugcbugc***DEBUG begins. cbugcbug 9703 format ('nc=',i3,' isign=',i3,' fsign=',1pe22.14) cbugcbug write ( 3, 9703) nc, isign, fsign cbugcbugc***DEBUG ends. c.... See if the only non-blank character in string is "+" or "-". if (nc .gt. nchar) go to 210 ! All characters are blank, "+" or "-". c.... See if the first character after any sign and/or decimal point is not an c.... integer. If so, word can not be an integer or a floating point number. achar = asrce(isrce+nc-1) if (achar .eq. '.') achar = asrce(isrce+nc) do 121 idig = 1, 16 if (achar .eq. adigit(idig)) go to 122 if (achar .eq. bdigit(idig)) go to 122 121 continue cbugcbugc***DEBUG begins. cbugcbug 9704 format ('Unacceptable character after +-. =',a1) cbugcbug write ( 3, 9704) achar cbugcbugc***DEBUG ends. go to 210 122 continue c=======================================================================-------- c.... Found the beginning of the mantissa. Initialize counters. intval = 0 ipt = -1000000 ndigall = 0 ndigit = 0 nzeros = 0 c.... Scan the remainder of the the mantissa and translate. nbeg = nc do 140 nc = nbeg, nchar ! Loop over rest of string. achar = asrce(isrce+nc-1) cbugcbugc***DEBUG begins. cbugcbug 9705 format ('nc=',i3,' achar= ',a1) cbugcbug write ( 3, 9705) nc, achar cbugcbugc***DEBUG ends. c.... Test for any trailing blanks after the mantissa. if (achar .eq. ' ') go to 145 ! Blank ends mantissa. c.... Scan for a digit or decimal point (which are part of mantissa). do 125 idig = 1, 16 ! Loop over digits. if (achar .eq. adigit(idig)) go to 130 if (achar .eq. bdigit(idig)) go to 130 125 continue ! End of loop over digits. cbugcbugc***DEBUG begins. cbugcbug 9706 format ('Not a digit. achar= ',a1) cbugcbug write ( 3, 9706) achar cbugcbugc***DEBUG ends. c.... Not a digit. Test for first decimal point (only allow 1). if ((ipt .ge. 0) .or. (achar .ne. '.')) go to 160 ! End of mantissa. ipt = 0 ! Found first decimal point. cbugcbugc***DEBUG begins. cbugcbug 9707 format ('A decimal point. achar= ',a1) cbugcbug write ( 3, 9707) achar cbugcbugc***DEBUG ends. go to 140 c.... Found a digit. See if zero or non-zero, if after a decimal point. 130 if (ipt .ge. 0) then ! String has a decimal point. cbugcbugc***DEBUG begins. cbugcbug 9708 format ('String has a decimal point.') cbugcbug write ( 3, 9708) cbugcbugc***DEBUG ends. c.... Save number of zeros following the decimal point. if (idig .eq. 1) then ! Save zeros. nzeros = nzeros + 1 cbugcbugc***DEBUG begins. cbugcbug 9709 format ('nzeros=',i3) cbugcbug write ( 3, 9709) nzeros cbugcbugc***DEBUG ends. go to 140 endif c.... Non-zero digit found. Include effect of zeros after decimal point. 135 if (nzeros .gt. 0) then ! String has zeros after decimal. c.... Only allow exponents up to iemax. if (ndigit .gt. (iemax + ipt)) then ! Exponent overflows. nerr = 5 if (nchar .le. iamax) then mtype = 1 else mtype = 0 endif go to 210 endif c.... Only allow integers with up to idmax digits. if (ndigit .lt. idmax) then intval = 16 * intval elseif (ndigit .eq. idmax) then fintval = intval fintval = 16.0 * fintval else ! More than idmax digits. fintval = 16.0 * fintval endif c.... Insert zeroes before next number. ipt = ipt + 1 nzeros = nzeros - 1 ndigit = ndigit + 1 ndigall = ndigall + 1 cbugcbugc***DEBUG begins. cbugcbug 9710 format ('ipt=',i3,' nzeros=',i3,' ndigit=',i3,' ndigall=',i3) cbugcbug write ( 3, 9710) ipt, nzeros, ndigit, ndigall cbugcbugc***DEBUG ends. go to 135 endif ! Tested nzeros. endif ! Tested ipt. c.... Found a digit. ndigall = ndigall + 1 c.... Ignore leading zeros. if ((ndigit .eq. 0) .and. (ipt .lt. 0) .and. & (idig .eq. 1)) go to 140 c.... Update the mantissa. c.... Only allow exponents up to iemax. if (ndigit .gt. (iemax + max (0, ipt))) then ! Exponent overflows. nerr = 5 if (nchar .le. iamax) then mtype = 1 else mtype = 0 endif go to 210 endif c.... Only allow integers with up to idmax digits. if (ndigit .lt. idmax) then intval = 16 * intval + (idig - 1) elseif (ndigit .eq. idmax) then ! Start floating point equivalent. fintadd = idig - 1 fintval = intval fintval = 16.0 * fintval + fintadd else ! More than idmax digits. fintadd = idig - 1 fintval = 16.0 * fintval + fintadd endif ipt = ipt + 1 ndigit = ndigit + 1 140 continue ! End of loop over rest of string. go to 155 c=======================================================================-------- c.... The mantissa ended with a blank. Look for next non-blank character. 145 nbeg = nc do 150 nc = nbeg, nchar ! Loop over rest of string. achar = asrce(isrce+nc-1) if (achar .ne. ' ') go to 160 150 continue ! End of loop over rest of string. c=======================================================================-------- c.... Found the end of the mantissa, with no exponent field. c.... Return a character string if no digits were found. 155 if ((ndigall .le. 0) .and. (nzeros .le. 0)) go to 210 c.... See if a decimal point was found. if (ipt .lt. 0) then ! No decimal point. c.... Assume floating point if over idmax digits. if (ndigit .le. idmax) then ! Return integer and floating point. mtype = 2 ! Type integer. iword = isign * intval fword = iword else ! Return only floating point. mtype = 3 ! Type integer, but too many digits. fword = fsign * fintval nerr = 4 endif else ! A decimal point was found. mtype = 3 ! Type floating point. if (ndigit .le. idmax) then fword = isign * intval else ! Return only floating point. fword = fsign * fintval endif 158 if (ipt .gt. 80) then fword = fword / 16.0**80.0 ipt = ipt - 80 go to 158 endif if (ipt .gt. 0) then fword = fword / 16.0**ipt endif endif ! Tested ipt. go to 210 c=======================================================================-------- c.... Found the end of the mantissa. Look for the beginning of the exponent. c.... The exponent may start with "h", "H", "+", or "-". 160 ksign = 0 if ((achar .eq. 'h') .or. (achar .eq. 'H')) then nc = nc + 1 achar = asrce(isrce+nc-1) ksign = 1 ! Assume positive exponent. cbugcbugc***DEBUG begins. cbugcbug 9711 format ('Exponent begins. nc=',i3,' achar= ',a1,' ksign=',i3) cbugcbug write ( 3, 9711) nc, achar, ksign cbugcbugc***DEBUG ends. endif if (achar .eq. '+') then ! Exponent is positive. nc = nc + 1 ksign = 1 cbugcbugc***DEBUG begins. cbugcbug write ( 3, 9711) nc, achar, ksign cbugcbugc***DEBUG ends. elseif (achar .eq. '-') then ! Exponent is negative. nc = nc + 1 ksign = -1 cbugcbugc***DEBUG begins. cbugcbug write ( 3, 9711) nc, achar, ksign cbugcbugc***DEBUG ends. endif if ((nc .gt. nchar) .or. (ksign .eq. 0)) go to 210 ! Not an exponent. c=======================================================================-------- c.... Found the beginning of the exponent. Find the next non-blank character. nbeg = nc do 165 nc = nbeg, nchar ! Loop over rest of string. achar = asrce(isrce+nc-1) if (achar .ne. ' ') go to 170 165 continue ! End of loop over rest of string. go to 210 ! No digits in exponent. 170 kexp = 0 kdigit = 0 cbugcbugc***DEBUG begins. cbugcbug 9712 format ('Exponent contents. nc=',i3,' achar= ',a1,' ksign=',i3) cbugcbug write ( 3, 9712) nc, achar, ksign cbugcbugc***DEBUG ends. nbeg = nc do 180 nc = nbeg, nchar ! Loop over rest of string. achar = asrce(isrce+nc-1) cbugcbugc***DEBUG begins. cbugcbug write ( 3, 9712) nc, achar, ksign cbugcbugc***DEBUG ends. if (achar .eq. ' ') go to 185 ! Imbedded blank ends exponent. do 175 idig = 1, 16 ! Loop over digits. if ((achar .eq. adigit(idig)) .or. & (achar .eq. bdigit(idig))) then kexp = 16 * kexp + (idig - 1) kdigit = kdigit + 1 go to 180 endif 175 continue ! End of loop over digits. go to 210 ! Not a digit. Return character string. 180 continue ! End of loop over rest of string. go to 195 c=======================================================================-------- c.... Found imbedded blank in exponent. The rest of the string must be blank. 185 nbeg = nc do 190 nc = nbeg, nchar ! Loop over rest of string. achar = asrce(isrce+nc-1) if (achar .ne. ' ') go to 210 ! Illegal character in exponent field. 190 continue ! End of loop over rest of string. c=======================================================================-------- c.... Found the end of the exponent. c.... Return a character string if no digits were found in exponent field. 195 if (kdigit .le. 0) go to 210 c.... Translate the mantissa to floating point. mtype = 3 ! Type real, or integer > idmax. if (ndigit .le. idmax) then fword = isign * intval else fword = fsign * fintval endif c.... Find the exponent. kexp = ksign * kexp if (ipt .gt. 0) kexp = kexp - ipt if (abs (kexp + ndigit - 1) .gt. iemax) then nerr = 5 ! Exceeded maximum exponent. if (nchar .le. iamax) then mtype = 1 else mtype = 0 endif fword = 0.0 go to 210 endif c.... Find the floating point result, including the exponent. if (kexp .lt. 0) then ! Negative exponent. kexp = -kexp 200 if (kexp .gt. 80) then fword = fword / 16.0**80.0 kexp = kexp - 80 go to 200 endif if (kexp .ne. 0) then fword = fword / 16.0**kexp endif elseif (kexp .gt. 0) then ! Positive exponent. 205 if (kexp .gt. 80) then fword = fword * 16.0**80.0 kexp = kexp - 80 go to 205 endif if (kexp .ne. 0) then fword = fword * 16.0**kexp endif endif ! Tested kexp. 210 continue cbugc***DEBUG begins. cbug 9903 format (/ 'apthexd results: mtype=',i3,' nerr=',i3) cbug 9904 format (' aword=',80a1 / ' iword=',i16,' fword=',1pe22.14) cbug write ( 3, 9903) mtype, nerr cbug write ( 3, 9904) (aword(nc), nc = 1, 80), iword, fword cbugc***DEBUG ends. return c.... End of subroutine apthexd. (+1 line.) end UCRL-WEB-209832