From 5b0a85fb2edd25d475bb9d773c2888ec9029cfad Mon Sep 17 00:00:00 2001 From: Ivan Pribec <ivan.pribec@gmail.com> Date: Sat, 28 Dec 2019 18:54:01 +0100 Subject: [PATCH] Place ASCII control characters in derived type; replace whitechar in IO module with is_blank. --- src/stdlib_experimental_ascii.f90 | 219 ++++++++++++++++-------------- src/stdlib_experimental_io.f90 | 21 +-- src/tests/ascii/test_ascii.f90 | 197 ++++++++++++++++++--------- 3 files changed, 254 insertions(+), 183 deletions(-) diff --git a/src/stdlib_experimental_ascii.f90 b/src/stdlib_experimental_ascii.f90 index fd7910790..19c173ef7 100644 --- a/src/stdlib_experimental_ascii.f90 +++ b/src/stdlib_experimental_ascii.f90 @@ -1,118 +1,135 @@ module stdlib_experimental_ascii - implicit none - private - - ! Character validation functions - public :: is_alpha, is_alphanum - public :: is_digit, is_hex_digit, is_octal_digit - public :: is_control, is_white, is_blank - public :: is_ascii, is_punctuation - public :: is_graphical, is_printable - public :: is_lower, is_upper - - ! Character conversion functions - public :: to_lower, to_upper - - ! All control characters in the ASCII table (see www.asciitable.com). - character(len=1), public, parameter :: NUL = achar(z'00') !! Null - character(len=1), public, parameter :: SOH = achar(z'01') !! Start of heading - character(len=1), public, parameter :: STX = achar(z'02') !! Start of text - character(len=1), public, parameter :: ETX = achar(z'03') !! End of text - character(len=1), public, parameter :: EOT = achar(z'04') !! End of transmission - character(len=1), public, parameter :: ENQ = achar(z'05') !! Enquiry - character(len=1), public, parameter :: ACK = achar(z'06') !! Acknowledge - character(len=1), public, parameter :: BEL = achar(z'07') !! Bell - character(len=1), public, parameter :: BS = achar(z'08') !! Backspace - character(len=1), public, parameter :: TAB = achar(z'09') !! Horizontal tab - character(len=1), public, parameter :: LF = achar(z'0A') !! NL line feed, new line - character(len=1), public, parameter :: VT = achar(z'0B') !! Vertical tab - character(len=1), public, parameter :: FF = achar(z'0C') !! NP form feed, new page - character(len=1), public, parameter :: CR = achar(z'0D') !! Carriage return - character(len=1), public, parameter :: SO = achar(z'0E') !! Shift out - character(len=1), public, parameter :: SI = achar(z'0F') !! Shift in - character(len=1), public, parameter :: DLE = achar(z'10') !! Data link escape - character(len=1), public, parameter :: DC1 = achar(z'11') !! Device control 1 - character(len=1), public, parameter :: DC2 = achar(z'12') !! Device control 2 - character(len=1), public, parameter :: DC3 = achar(z'13') !! Device control 3 - character(len=1), public, parameter :: DC4 = achar(z'14') !! Device control 4 - character(len=1), public, parameter :: NAK = achar(z'15') !! Negative acknowledge - character(len=1), public, parameter :: SYN = achar(z'16') !! Synchronous idle - character(len=1), public, parameter :: ETB = achar(z'17') !! End of transmission block - character(len=1), public, parameter :: CAN = achar(z'18') !! Cancel - character(len=1), public, parameter :: EM = achar(z'19') !! End of medium - character(len=1), public, parameter :: SUB = achar(z'1A') !! Substitute - character(len=1), public, parameter :: ESC = achar(z'1B') !! Escape - character(len=1), public, parameter :: FS = achar(z'1C') !! File separator - character(len=1), public, parameter :: GS = achar(z'1D') !! Group separator - character(len=1), public, parameter :: RS = achar(z'1E') !! Record separator - character(len=1), public, parameter :: US = achar(z'1F') !! Unit separator - character(len=1), public, parameter :: DEL = achar(z'7F') !! Delete - - ! Constant character sequences - character(len=*), public, parameter :: fullhex_digits = "0123456789ABCDEFabcdef" !! 0 .. 9A .. Fa .. f - character(len=*), public, parameter :: hex_digits = fullhex_digits(1:16) !! 0 .. 9A .. F - character(len=*), public, parameter :: lowerhex_digits = "0123456789abcdef" !! 0 .. 9a .. f - character(len=*), public, parameter :: digits = hex_digits(1:10) !! 0 .. 9 - character(len=*), public, parameter :: octal_digits = digits(1:8) !! 0 .. 7 - character(len=*), public, parameter :: letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" !! A .. Za .. z - character(len=*), public, parameter :: uppercase = letters(1:26) !! A .. Z - character(len=*), public, parameter :: lowercase = letters(27:) !! a .. z - character(len=*), public, parameter :: whitespace = " "//TAB//VT//CR//LF//FF !! ASCII _whitespace +implicit none +private + +! Character validation functions +public :: is_alpha, is_alphanum +public :: is_digit, is_hex_digit, is_octal_digit +public :: is_control, is_white, is_blank +public :: is_ascii, is_punctuation +public :: is_graphical, is_printable +public :: is_lower, is_upper + +! Character conversion functions +public :: to_lower, to_upper + +! Ascii control characters +public :: ascii_control_char + +! Constant character sequences +public :: fullhex_digits, hex_digits, lowerhex_digits, digits, octal_digits +public :: letters, uppercase, lowercase, whitespace + + +! All control characters in the ASCII table (see www.asciitable.com). +type :: ascii_control_char_t + character(len=1) :: NUL = achar(z'00') !! Null + character(len=1) :: SOH = achar(z'01') !! Start of heading + character(len=1) :: STX = achar(z'02') !! Start of text + character(len=1) :: ETX = achar(z'03') !! End of text + character(len=1) :: EOT = achar(z'04') !! End of transmission + character(len=1) :: ENQ = achar(z'05') !! Enquiry + character(len=1) :: ACK = achar(z'06') !! Acknowledge + character(len=1) :: BEL = achar(z'07') !! Bell + character(len=1) :: BS = achar(z'08') !! Backspace + character(len=1) :: TAB = achar(z'09') !! Horizontal tab + character(len=1) :: LF = achar(z'0A') !! NL line feed, new line + character(len=1) :: VT = achar(z'0B') !! Vertical tab + character(len=1) :: FF = achar(z'0C') !! NP form feed, new page + character(len=1) :: CR = achar(z'0D') !! Carriage return + character(len=1) :: SO = achar(z'0E') !! Shift out + character(len=1) :: SI = achar(z'0F') !! Shift in + character(len=1) :: DLE = achar(z'10') !! Data link escape + character(len=1) :: DC1 = achar(z'11') !! Device control 1 + character(len=1) :: DC2 = achar(z'12') !! Device control 2 + character(len=1) :: DC3 = achar(z'13') !! Device control 3 + character(len=1) :: DC4 = achar(z'14') !! Device control 4 + character(len=1) :: NAK = achar(z'15') !! Negative acknowledge + character(len=1) :: SYN = achar(z'16') !! Synchronous idle + character(len=1) :: ETB = achar(z'17') !! End of transmission block + character(len=1) :: CAN = achar(z'18') !! Cancel + character(len=1) :: EM = achar(z'19') !! End of medium + character(len=1) :: SUB = achar(z'1A') !! Substitute + character(len=1) :: ESC = achar(z'1B') !! Escape + character(len=1) :: FS = achar(z'1C') !! File separator + character(len=1) :: GS = achar(z'1D') !! Group separator + character(len=1) :: RS = achar(z'1E') !! Record separator + character(len=1) :: US = achar(z'1F') !! Unit separator + character(len=1) :: DEL = achar(z'7F') !! Delete +end type + +! A single instance of the ascii control characters (initialized to default values) +type(ascii_control_char_t), parameter :: ascii_control_char = ascii_control_char_t() + +! Constant character sequences +character(len=*), parameter :: fullhex_digits = "0123456789ABCDEFabcdef" !! 0 .. 9A .. Fa .. f +character(len=*), parameter :: hex_digits = fullhex_digits(1:16) !! 0 .. 9A .. F +character(len=*), parameter :: lowerhex_digits = "0123456789abcdef" !! 0 .. 9a .. f +character(len=*), parameter :: digits = hex_digits(1:10) !! 0 .. 9 +character(len=*), parameter :: octal_digits = digits(1:8) !! 0 .. 7 +character(len=*), parameter :: letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" !! A .. Za .. z +character(len=*), parameter :: uppercase = letters(1:26) !! A .. Z +character(len=*), parameter :: lowercase = letters(27:) !! a .. z +character(len=*), parameter :: whitespace = " "//ascii_control_char%TAB//& + ascii_control_char%VT//& + ascii_control_char%CR//& + ascii_control_char%LF//& + ascii_control_char%FF !! ASCII whitespace contains - !> Checks whether `c` is an ASCII letter (A .. Z, a .. z). - pure logical function is_alpha(c) +!> Checks whether `c` is an ASCII letter (A .. Z, a .. z). + elemental logical function is_alpha(c) character(len=1), intent(in) :: c !! The character to test. is_alpha = (c >= 'A' .and. c <= 'Z') .or. (c >= 'a' .and. c <= 'z') end function - !> Checks whether `c` is a letter or a number (0 .. 9, a .. z, A .. Z). - pure logical function is_alphanum(c) +!> Checks whether `c` is a letter or a number (0 .. 9, a .. z, A .. Z). + elemental logical function is_alphanum(c) character(len=1), intent(in) :: c !! The character to test. is_alphanum = (c >= '0' .and. c <= '9') .or. (c >= 'a' .and. c <= 'z') & .or. (c >= 'A' .and. c <= 'Z') end function - !> Checks whether or not `c` is in the ASCII character set - - ! i.e. in the range 0 .. 0x7F. - pure logical function is_ascii(c) +!> Checks whether or not `c` is in the ASCII character set - +! i.e. in the range 0 .. 0x7F. + elemental logical function is_ascii(c) character(len=1), intent(in) :: c !! The character to test. is_ascii = iachar(c) <= z'7F' end function - !> Checks whether `c` is a control character. - pure logical function is_control(c) +!> Checks whether `c` is a control character. + elemental logical function is_control(c) character(len=1), intent(in) :: c !! The character to test. integer :: ic ic = iachar(c) is_control = ic < z'20' .or. ic == z'7F' end function - !> Checks whether `c` is a digit (0 .. 9). - pure logical function is_digit(c) +!> Checks whether `c` is a digit (0 .. 9). + elemental logical function is_digit(c) character(len=1), intent(in) :: c !! The character to test. is_digit = ('0' <= c) .and. (c <= '9') end function - !> Checks whether `c` is a digit in base 8 (0 .. 7). - pure logical function is_octal_digit(c) +!> Checks whether `c` is a digit in base 8 (0 .. 7). + elemental logical function is_octal_digit(c) character(len=1), intent(in) :: c !! The character to test. is_octal_digit = (c >= '0') .and. (c <= '7'); end function - !> Checks whether `c` is a digit in base 16 (0 .. 9, A .. F, a .. f). - pure logical function is_hex_digit(c) +!> Checks whether `c` is a digit in base 16 (0 .. 9, A .. F, a .. f). + elemental logical function is_hex_digit(c) character(len=1), intent(in) :: c !! The character to test. is_hex_digit = (c >= '0' .and. c <= '9') .or. (c >= 'a' .and. c <= 'f') & .or. (c >= 'A' .and. c <= 'F') end function - !> Checks whether or not `c` is a punctuation character. That includes - ! all ASCII characters which are not control characters, letters, - ! digits, or whitespace. - pure logical function is_punctuation(c) +!> Checks whether or not `c` is a punctuation character. That includes +! all ASCII characters which are not control characters, letters, +! digits, or whitespace. + elemental logical function is_punctuation(c) character(len=1), intent(in) :: c !! The character to test. integer :: ic ic = iachar(c) ! '~' '!' @@ -120,58 +137,58 @@ pure logical function is_punctuation(c) (.not. is_alphanum(c)) end function - !> Checks whether or not `c` is a printable character other than the - ! space character. - pure logical function is_graphical(c) +!> Checks whether or not `c` is a printable character other than the +! space character. + elemental logical function is_graphical(c) character(len=1), intent(in) :: c !! The character to test. integer :: ic ic = iachar(c) ! '!' '~' is_graphical = (z'21' <= ic) .and. (ic <= z'7E') end function - !> Checks whether or not `c` is a printable character - including the - ! space character. - pure logical function is_printable(c) +!> Checks whether or not `c` is a printable character - including the +! space character. + elemental logical function is_printable(c) character(len=1), intent(in) :: c !! The character to test. integer :: ic ic = iachar(c) ! '~' is_printable = c >= ' ' .and. ic <= z'7E' end function - !> Checks whether `c` is a lowercase ASCII letter (a .. z). - pure logical function is_lower(c) +!> Checks whether `c` is a lowercase ASCII letter (a .. z). + elemental logical function is_lower(c) character(len=1), intent(in) :: c !! The character to test. is_lower = (c >= 'a') .and. (c <= 'z') end function - !> Checks whether `c` is an uppercase ASCII letter (A .. Z). - pure logical function is_upper(c) +!> Checks whether `c` is an uppercase ASCII letter (A .. Z). + elemental logical function is_upper(c) character(len=1), intent(in) :: c !! The character to test. is_upper = (c >= 'A') .and. (c <= 'Z') end function - !> Checks whether or not `c` is a whitespace character. That includes the - ! space, tab, vertical tab, form feed, carriage return, and linefeed - ! characters. - pure logical function is_white(c) +!> Checks whether or not `c` is a whitespace character. That includes the +! space, tab, vertical tab, form feed, carriage return, and linefeed +! characters. + elemental logical function is_white(c) character(len=1), intent(in) :: c !! The character to test. integer :: ic ic = iachar(c) ! TAB, LF, VT, FF, CR is_white = (c == ' ') .or. (ic >= z'09' .and. ic <= z'0D'); end function - !> Checks whether or not `c` is a blank character. That includes the - ! only the space and tab characters - pure logical function is_blank(c) +!> Checks whether or not `c` is a blank character. That includes +! the space and tab characters + elemental logical function is_blank(c) character(len=1), intent(in) :: c !! The character to test. integer :: ic ic = iachar(c) ! TAB is_blank = (c == ' ') .or. (ic == z'09'); end function - !> Returns the corresponding lowercase letter, if `c` is an uppercase - ! ASCII character, otherwise `c` itself. - pure function to_lower(c) result(t) +!> Returns the corresponding lowercase letter, if `c` is an uppercase +! ASCII character, otherwise `c` itself. + elemental function to_lower(c) result(t) character(len=1), intent(in) :: c !! A character. character(len=1) :: t integer :: diff @@ -181,9 +198,9 @@ pure function to_lower(c) result(t) if (is_upper(t)) t = achar(iachar(t) - diff) end function - !> Returns the corresponding uppercase letter, if `c` is a lowercase - ! ASCII character, otherwise `c` itself. - pure function to_upper(c) result(t) +!> Returns the corresponding uppercase letter, if `c` is a lowercase +! ASCII character, otherwise `c` itself. + elemental function to_upper(c) result(t) character(len=1), intent(in) :: c !! A character. character(len=1) :: t integer :: diff diff --git a/src/stdlib_experimental_io.f90 b/src/stdlib_experimental_io.f90 index 0e0ca6bab..66bd524ef 100644 --- a/src/stdlib_experimental_io.f90 +++ b/src/stdlib_experimental_io.f90 @@ -1,5 +1,6 @@ module stdlib_experimental_io use iso_fortran_env, only: sp=>real32, dp=>real64, qp=>real128 +use stdlib_experimental_ascii, only: is_blank implicit none private public :: loadtxt, savetxt @@ -224,16 +225,16 @@ integer function number_of_columns(s) integer :: ios character :: c - logical :: lastwhite + logical :: lastblank rewind(s) number_of_columns = 0 - lastwhite = .true. + lastblank = .true. do read(s, '(a)', advance='no', iostat=ios) c if (ios /= 0) exit - if (lastwhite .and. .not. whitechar(c)) number_of_columns = number_of_columns + 1 - lastwhite = whitechar(c) + if (lastblank .and. .not. is_blank(c)) number_of_columns = number_of_columns + 1 + lastblank = is_blank(c) end do rewind(s) @@ -244,7 +245,7 @@ integer function number_of_rows_numeric(s) integer,intent(in)::s integer :: ios - real::r + real :: r rewind(s) number_of_rows_numeric = 0 @@ -258,14 +259,4 @@ integer function number_of_rows_numeric(s) end function -logical function whitechar(char) ! white character -! returns .true. if char is space (32) or tab (9), .false. otherwise -character, intent(in) :: char -if (iachar(char) == 32 .or. iachar(char) == 9) then - whitechar = .true. -else - whitechar = .false. -end if -end function - end module diff --git a/src/tests/ascii/test_ascii.f90 b/src/tests/ascii/test_ascii.f90 index 5a535f2ce..88d2e9c88 100644 --- a/src/tests/ascii/test_ascii.f90 +++ b/src/tests/ascii/test_ascii.f90 @@ -6,7 +6,7 @@ program test_ascii whitespace, letters, is_alphanum, is_alpha, is_lower, is_upper, & is_digit, is_octal_digit, is_hex_digit, is_white, is_blank, & is_control, is_punctuation, is_graphical, is_printable, is_ascii, & - to_lower, to_upper, LF, TAB, NUL, DEL + to_lower, to_upper, ascii_control_char write(*,*) "Lowercase letters: ", lowercase write(*,*) "Uppercase letters: ", uppercase @@ -15,6 +15,7 @@ program test_ascii write(*,*) "Full hex digits: ", fullhex_digits write(*,*) "Hex digits: ", hex_digits write(*,*) "Lower hex digits: ", lowerhex_digits + write(*,*) call test_is_alphanum_short call test_is_alphanum_long @@ -64,7 +65,7 @@ program test_ascii call test_to_upper_short call test_to_upper_long - ! call test_ascii_table + call test_ascii_table contains @@ -248,8 +249,8 @@ subroutine test_is_hex_digit_long subroutine test_is_white_short write(*,*) "test_is_white_short" call assert(is_white(' ')) - call assert(is_white(TAB)) - call assert(is_white(LF)) + call assert(is_white(ascii_control_char%TAB)) + call assert(is_white(ascii_control_char%LF)) call assert(.not. is_white('1')) call assert(.not. is_white('a')) call assert(.not. is_white('#')) @@ -271,7 +272,7 @@ subroutine test_is_white_long subroutine test_is_blank_short write(*,*) "test_is_blank_short" call assert(is_blank(' ')) - call assert(is_blank(TAB)) + call assert(is_blank(ascii_control_char%TAB)) call assert(.not. is_blank('1')) call assert(.not. is_blank('a')) call assert(.not. is_blank('#')) @@ -282,7 +283,8 @@ subroutine test_is_blank_long character(len=:), allocatable :: clist write(*,*) "test_is_blank_long" do i = 1, len(whitespace) - if (whitespace(i:i) == ' ' .or. whitespace(i:i) == TAB) then + if (whitespace(i:i) == ' ' .or. & + whitespace(i:i) == ascii_control_char%TAB) then call assert(is_blank(whitespace(i:i))) else call assert(.not. is_blank(whitespace(i:i))) @@ -317,7 +319,7 @@ subroutine test_is_control_long do i = 0, 31 call assert(is_control(achar(i))) end do - call assert(is_control(DEL)) + call assert(is_control(ascii_control_char%DEL)) clist = digits//letters//' ' do i = 1, len(clist) @@ -339,8 +341,8 @@ subroutine test_is_punctuation_short call assert(.not. is_punctuation('1')) call assert(.not. is_punctuation('a')) call assert(.not. is_punctuation(' ')) - call assert(.not. is_punctuation(LF)) ! new line character - call assert(.not. is_punctuation(NUL)) + call assert(.not. is_punctuation(ascii_control_char%LF)) ! new line character + call assert(.not. is_punctuation(ascii_control_char%NUL)) ! N.B.: Non-ASCII Unicode punctuation characters are not recognized. ! write(*,*) is_punctuation('\u2012') ! (U+2012 = en-dash) @@ -366,8 +368,8 @@ subroutine test_is_graphical_short call assert(is_graphical('a')) call assert(is_graphical('#')) call assert(.not. is_graphical(' ')) ! whitespace is not graphical - call assert(.not. is_graphical(LF)) - call assert(.not. is_graphical(NUL)) + call assert(.not. is_graphical(ascii_control_char%LF)) + call assert(.not. is_graphical(ascii_control_char%NUL)) ! N.B.: Unicode graphical characters are not regarded as such. call assert(.not. is_graphical('ä')) @@ -393,7 +395,7 @@ subroutine test_is_printable_short call assert(is_printable('1')) call assert(is_printable('a')) call assert(is_printable('#')) - call assert(.not. is_printable(NUL)) ! control characters are not printable + call assert(.not. is_printable(ascii_control_char%NUL)) ! control characters are not printable ! N.B.: Printable non-ASCII Unicode characters are not recognized. call assert(.not. is_printable('ä')) @@ -478,65 +480,126 @@ subroutine test_to_upper_long() end do end subroutine - ! - ! This test reproduces the true/false table found at - ! https://en.cppreference.com/w/cpp/string/byte - ! + +!> This test reproduces the true/false table found at +! https://en.cppreference.com/w/cpp/string/byte +! by passing allocatable character arrays filled with subsets +! of ascii characters to the stdlib character validation functions. +! subroutine test_ascii_table integer :: i, j - character(len=1) :: c logical :: table(15,12) + character(len=7) :: col + + character(len=1), allocatable :: ca(:) + integer :: ic(16) ! 15 + 1 + + write(*,*) "test_ascii_table" + + ! 0-8 control codes + ! 9 tab + ! 10-13 whitespaces + ! 14-31 control codes + ! 32 space + ! 33-47 !"#$%&'()*+,-./ + ! 48-57 0123456789 + ! 58-64 :;<=>?@ + ! 65-70 ABCDEF + ! 71-90 GHIJKLMNOPQRSTUVWXYZ + ! 91-96 [\]^_` + ! 97-102 abcdef + ! 103-122 ghijklmnopqrstuvwxyz + ! 123-126 {|}~ + ! 127 backspace character + + ic = [0,9,10,14,32,33,48,58,65,71,91,97,103,123,127,128] + + do i = 1, 15 + ca = [(achar(j),j=ic(i),ic(i+1)-1)] + table(i,1) = all(is_control(ca)) + end do + + do i = 1, 15 + ca = [(achar(j),j=ic(i),ic(i+1)-1)] + table(i,2) = all(is_printable(ca)) + end do + + do i = 1, 15 + ca = [(achar(j),j=ic(i),ic(i+1)-1)] + table(i,3) = all(is_white(ca)) + end do + + do i = 1, 15 + ca = [(achar(j),j=ic(i),ic(i+1)-1)] + table(i,4) = all(is_blank(ca)) + end do + + do i = 1, 15 + ca = [(achar(j),j=ic(i),ic(i+1)-1)] + table(i,5) = all(is_graphical(ca)) + end do + + do i = 1, 15 + ca = [(achar(j),j=ic(i),ic(i+1)-1)] + table(i,6) = all(is_punctuation(ca)) + end do + + do i = 1, 15 + ca = [(achar(j),j=ic(i),ic(i+1)-1)] + table(i,7) = all(is_alphanum(ca)) + end do - abstract interface - pure logical function validation_func_interface(c) - character(len=1), intent(in) :: c - end function - end interface - - type :: proc_pointer_array - procedure(validation_func_interface), pointer, nopass :: pcf - end type proc_pointer_array - - type(proc_pointer_array) :: pcfs(12) - - pcfs(1)%pcf => is_control - pcfs(2)%pcf => is_printable - pcfs(3)%pcf => is_white - pcfs(4)%pcf => is_blank - pcfs(5)%pcf => is_graphical - pcfs(6)%pcf => is_punctuation - pcfs(7)%pcf => is_alphanum - pcfs(8)%pcf => is_alpha - pcfs(9)%pcf => is_upper - pcfs(10)%pcf => is_lower - pcfs(11)%pcf => is_digit - pcfs(12)%pcf => is_hex_digit - - ! loop through functions - do i = 1, 12 - table(1,i) = all([(pcfs(i)%pcf(achar(j)),j=0,8)]) ! control codes - table(2,i) = pcfs(i)%pcf(achar(9)) ! tab - table(3,i) = all([(pcfs(i)%pcf(achar(j)),j=10,13)]) ! whitespaces - table(4,i) = all([(pcfs(i)%pcf(achar(j)),j=14,31)]) ! control codes - table(5,i) = pcfs(i)%pcf(achar(32)) ! space - table(6,i) = all([(pcfs(i)%pcf(achar(j)),j=33,47)]) ! !"#$%&'()*+,-./ - table(7,i) = all([(pcfs(i)%pcf(achar(j)),j=48,57)]) ! 0123456789 - table(8,i) = all([(pcfs(i)%pcf(achar(j)),j=58,64)]) ! :;<=>?@ - table(9,i) = all([(pcfs(i)%pcf(achar(j)),j=65,70)]) ! ABCDEF - table(10,i) = all([(pcfs(i)%pcf(achar(j)),j=71,90)]) ! GHIJKLMNOPQRSTUVWXYZ - table(11,i) = all([(pcfs(i)%pcf(achar(j)),j=91,96)]) ! [\]^_` - table(12,i) = all([(pcfs(i)%pcf(achar(j)),j=97,102)]) ! abcdef - table(13,i) = all([(pcfs(i)%pcf(achar(j)),j=103,122)]) ! ghijklmnopqrstuvwxyz - table(14,i) = all([(pcfs(i)%pcf(achar(j)),j=123,126)]) ! {|}~ - table(15,i) = pcfs(i)%pcf(achar(127)) ! backspace character - end do - - ! output table for verification - write(*,'(5X,12(I4))') (i,i=1,12) - do j = 1, 15 - write(*,'(I3,2X,12(L4),2X,I3)') j, (table(j,i),i=1,12), count(table(j,:)) - end do - write(*,'(5X,12(I4))') (count(table(:,i)),i=1,12) + do i = 1, 15 + ca = [(achar(j),j=ic(i),ic(i+1)-1)] + table(i,8) = all(is_alpha(ca)) + end do + + do i = 1, 15 + ca = [(achar(j),j=ic(i),ic(i+1)-1)] + table(i,9) = all(is_upper(ca)) + end do + + do i = 1, 15 + ca = [(achar(j),j=ic(i),ic(i+1)-1)] + table(i,10) = all(is_lower(ca)) + end do + + do i = 1, 15 + ca = [(achar(j),j=ic(i),ic(i+1)-1)] + table(i,11) = all(is_digit(ca)) + end do + + do i = 1, 15 + ca = [(achar(j),j=ic(i),ic(i+1)-1)] + table(i,12) = all(is_hex_digit(ca)) + end do + + + ! Output true/false table for verification + write(*,*) + write(*,'(10X,A)') "is_control" + write(*,'(10X,A)') "| is_printable" + write(*,'(10X,A)') "| | is_whitespace" + write(*,'(10X,A)') "| | | is_blank" + write(*,'(10X,A)') "| | | | is_graphical" + write(*,'(10X,A)') "| | | | | is_punctuation" + write(*,'(10X,A)') "| | | | | | is_alphanum" + write(*,'(10X,A)') "| | | | | | | is_alpha" + write(*,'(10X,A)') "| | | | | | | | is_upper" + write(*,'(10X,A)') "| | | | | | | | | is_lower" + write(*,'(10X,A)') "| | | | | | | | | | is_digit" + write(*,'(A10,A)') " decimal ","| | | | | | | | | | | is_hex_digit" + write(*,*) "-------------------------------------------" + do i = 1, 15 + ! Process first column + if (ic(i) /= ic(i+1)-1) then + write(col,'(I0,"-",I0)') ic(i), ic(i+1)-1 + else + write(col,'(I0)') ic(i) + end if + + write(*,'(1X,A7,2X,12(L1,:,X),2X,I3)') adjustr(col), (table(i,j),j=1,12) + end do end subroutine end program \ No newline at end of file