PROGRAM InsertionSortLinked;
(************************************************
*                                              *
*      Insertion Sort with Linked List         *
*                                              *
*      From the book - PASCAL An Introduction  *
*      to Methodical Programming               *
*      Authors:                                *
*      W. Findlay and D.A. Watt                *
*                                              *
*      Entered by Ray Penley - 8 Dec 79        *
*                                              *
*      Heavely modified entire program to      *
*      be interactive with the console.        *
*                                              *
************************************************)
(* NOTE - This program can be eaisly adapted to sort single *
* characters, integer numbers, real numbers, months, or any*
* other items which can be ordered! It is only necessary to*
* change the definition of the type identifier ITEMS, the  *
* body of the procedure ReadItem, and possibly the body of *
* WriteItems.                                              *)

CONST
 NameLength    = 10;
 INPUT = 0;    (* PASCAL/Z ver 2.0 *)
 space = ' ';

TYPE
 Items  = PACKED ARRAY[1..NameLength] OF CHAR;
 ItemRecords  = record
                  item  :Items;
                  Next  :^ItemRecords
                end;
 ItemPointers = ^ItemRecords;

VAR
 ListHead  :ItemPointers;
 Newitem   :Items;
 EndOfList,
 done,
 error     :boolean;

PROCEDURE ReadItem(VAR  item  :Items);
(*      Valid Alphanumeric chars are:
        the space - CHR(32) to
        the tilde - CHR(126)   *)
VAR
pos  :0..NameLength;
dummy,
ch   :Char;

     Procedure ClearReadItem;
     begin
       FOR pos:=1 TO NameLength DO item[ pos ]:= space;
       pos := 0
     end;

begin
 ClearReadItem;
 EndOfList := FALSE;
 error := FALSE;
 REPEAT
   IF pos < NameLength THEN  (* GET VALID INPUTS *)
     begin
     READ( CH );
     If ch = '$' then
       EndOfList := true
     Else
       begin
       IF CH IN [' ' .. '~'] THEN (* valid character *)
         begin
         pos := pos +1;
         item [pos] := CH
         end(* if *)
       Else
         begin
         WRITELN(' Alphanumerics only - TURKEY');
         ClearReadItem;
         ERROR:=TRUE
         end(* else *)
       end(* else *)
     end(* If *)
   Else        (*   ERROR   *)
     begin
     READLN( dummy );
     WRITELN(' Maximum of ', NameLength:4, ' characters please!');
     ClearReadItem;
     ERROR:=TRUE
     end(* Else *)
 UNTIL EOLN(Input) OR EndOfList;
end(* SCANNER *);

PROCEDURE InsertItem( Newitem  :Items);
VAR
 entry,
 PriorEntry,
 Newentry      :ItemPointers;
 Searching     :boolean;
begin
 (* FIND the position where the New item will be Inserted *)
 entry := ListHead;
 Searching := TRUE;
 While Searching and (entry <> NIL) DO
   WITH entry^ DO
     IF Newitem < item then
       Searching := FALSE
     Else
       begin
       PriorEntry := entry;
       entry := Next
       end;
(* CREATE the New entry and Insert it in position *)
 New(Newentry);
 Newentry^.item := Newitem;
 Newentry^.Next := entry;
 IF entry = ListHead then
   ListHead := Newentry
 Else PriorEntry^.Next := Newentry;
end;  (* InsertItem *)

PROCEDURE WriteItems;
VAR
 entry  :ItemPointers;
begin
 entry := ListHead;
 While entry <> NIL DO
   WITH entry^ DO
     begin
     Writeln(item);
     entry := Next
     end
end; (* WriteItems *)

begin  (* MAIN PROGRAM *)
 ListHead := NIL;  (* MAKE the LIST EMPTY *)
 Writeln(' ':12,'Insertion Sort Using a Linked List');
 writeln;writeln;writeln;
 writeln('Enter your list after the prompt.');
 writeln('Enter a dollar sign <$> when complete.');
 writeln;writeln;writeln;

 REPEAT
   write('>>');
   ReadItem(Newitem); (* READ the First Item *)
   If NOT error then
     If NOT EndOfList then
       (* Insert the New item in its correct position *)
       InsertItem(Newitem);
 UNTIL EndOfList;

 Writeln(' ':12,'The Sorted List');
 writeln;
 (* Write all the Items in order *)
 WriteItems
end. (* SORTLIST *)