PROGRAM Internet_Addresses !----------------------------------------------------------------------------- ! Program to read TCP/IP addresses from a file and produce a list of distinct ! addresses and a count of how many times each appeared in the file. The ! addresses and counts are stored in a linked list. ! Variables used are: ! FileName : name of data file containing addresses ! OpenStatus : status variable for OPEN statement ! InputStatus : status variable for READ statement ! Address : an address read from the file ! AddressList : pointer to first node in the linked list of addresses ! Subroutines used to process linked list: ! Add_To_List, Search, Output_Addresses ! ! Input (keyboard): FileName ! Input (file): Addresses ! Output: A list of distinct addresses and their counts !----------------------------------------------------------------------------- IMPLICIT NONE ! Define an address node type TYPE List_Node CHARACTER(15) :: TCP_IP_Address ! Address data INTEGER :: Count ! Counter for this address TYPE(List_Node), POINTER :: Next ! Pointer to next node END TYPE List_Node CHARACTER(15) :: Address, FileName*20 INTEGER :: OpenStatus, InputStatus TYPE(List_Node), POINTER :: AddressList ! Get name of data file and open it for reading WRITE (*, '(1X, A)', ADVANCE = "NO") "Enter name of file of addresses: " READ *, FileName OPEN (UNIT = 10, FILE = FileName, STATUS = "OLD", IOSTAT = OpenStatus) IF (OpenStatus > 0) STOP "*** Cannot open address file ***" ! Create empty linked list NULLIFY(AddressList) ! Read addresses from the file and store them in the list, ! until end of file reached DO READ(10, '(A)', IOSTAT = InputStatus) Address IF (InputStatus > 0) STOP "*** Input error ***" IF (InputStatus < 0) EXIT ! end of file CALL Add_To_List(AddressList, Address) ENDDO CALL Output_Addresses(AddressList) CONTAINS !--------------------------------------------------------------------------- ! This subroutine determines if Address is already in the linked list ! AddressList (using Search). If it is not, it is added at the beginning ! of the list; if it is, its count is incremented by 1. Local variables: ! AllocateStatus : status variable for OPEN statement ! LocPtr : pointer to a node containing Address or null if ! not found ! In_the_List : indicates if Address is already in AddressList ! Accepts: AddressList and Address ! Returns: Modified AddressList !--------------------------------------------------------------------------- SUBROUTINE Add_To_List(AddressList, Address) TYPE(List_Node), POINTER :: AddressList CHARACTER(*), INTENT(IN) :: Address TYPE(List_Node), POINTER :: LocPtr INTEGER :: AllocateStatus LOGICAL :: In_the_List IF (.NOT. ASSOCIATED(AddressList)) THEN ! List is empty ALLOCATE(AddressList, STAT = AllocateStatus) IF (AllocateStatus /= 0) STOP "*** Out of memory *** " AddressList%TCP_IP_Address = Address AddressList%Count = 1 NULLIFY(AddressList%Next) ELSE ! List not empty -- determine if Address is already in the list CALL Search(AddressList, Address, LocPtr, In_the_List) IF (In_the_List) THEN ! Increment its count by 1 LocPtr%Count = LocPtr%Count + 1 ELSE ! Create a new node and insert it at the front ALLOCATE(LocPtr, STAT = AllocateStatus) IF (AllocateStatus /= 0) STOP "*** Out of memory *** " LocPtr%TCP_IP_Address = Address LocPtr%Count = 1 LocPtr%Next => AddressList AddressList => LocPtr END IF END IF END SUBROUTINE Add_To_List !--------------------------------------------------------------------------- ! This subroutine searches AddressList for a node containing Address. ! If it is found, LocPtr points to the node and In_the_List is set to ! true; otherwise LocPtr is NULL and In_the_List is false. ! ! Accepts: AddressList, Address ! Returns: LocPtr, In_the_List !--------------------------------------------------------------------------- SUBROUTINE Search(AddressList, Address, LocPtr, In_the_List) TYPE(List_Node), POINTER :: AddressList, LocPtr CHARACTER(*), INTENT(IN) :: Address LOGICAL,INTENT(OUT) :: In_the_List LocPtr => AddressList In_the_List = .FALSE. ! Traverse the list until the address is found ! or the end of list is encountered DO IF( In_the_List .OR. .NOT. ASSOCIATED(LocPtr)) EXIT ! Address found or end of list -- terminate repetition IF(LocPtr%TCP_IP_Address == Address) THEN ! Address found In_the_List = .TRUE. ELSE ! Move to next node LocPtr => LocPtr%Next END IF END DO END SUBROUTINE Search !--------------------------------------------------------------------------- ! This subroutine prints the contents of the linked list pointed to by ! AddressList. For each node, it prints the address and count. Local ! variable used: ! Ptr : pointer that runs through the list ! ! Accepts: AddressList ! Output: Addresses and counts stored in nodes of AddressList !--------------------------------------------------------------------------- SUBROUTINE Output_Addresses(AddressList) TYPE(List_Node), POINTER :: AddressList, Ptr Ptr => AddressList PRINT *, "Summary of Internet address data" PRINT * PRINT *, " Address Count " PRINT *, "--------------------------- " ! Print node information until end of list reached DO IF (.NOT. ASSOCIATED(Ptr)) EXIT ! End of list reached ! Otherwise display contents of node pointed to by Ptr PRINT '(1X, A, 4X, I4)', Ptr%TCP_IP_Address, Ptr%Count ! Move to next node Ptr => Ptr%Next END DO END SUBROUTINE Output_Addresses END PROGRAM Internet_Addresses