############################################################################
#
#	File:     irsort.icn
#
#	Subject:  Program to sort Icon record declaration
#
#	Author:   Ralph E. Griswold
#
#	Date:     June 23, 2000
#
############################################################################
#
#   This file is in the public domain.
#
############################################################################
#  
#     This program reads an Icon program and writes an equivalent
#  program with the record declaration sorted alphabetically at the
#  end. Global, link, invocable, and procedure declarations come in the order
#  they appear in the original program.
#  
#     Comments and white space between declarations are attached to
#  the next following declaration.
#  
#  Limitations: This program only recognizes declarations that start
#  at the beginning of a line.
#  
#     Comments and interline white space between declarations may
#  not come out as intended.
#
#  Note:  This program is still raw.  White space and comments related
#  to records may not come out as expected.  A closed parenthesis in
#  a comment in the midst of a record declaration will cause havok.
#
############################################################################


procedure main(args)
   local line, x, i, recordtable, recordlist, comments, recordname 

   comments := []			# list of comment lines
   recordtable := table()		# table of record declarations

   while line := read() do {
     line ? {
        if ="record" &			#  record declaration
           tab(many('\t ')) &
           recordname := tab(upto('(')) | stop("*** bad syntax: ",line)
        then {				# if main, force sorting order
           recordtable[recordname] := x := []
           put(x, line)
           if upto(')', line) then next else while line := read() do {
              put(x, line)
              if upto(')', line) then break next
              }
           }
					#  other declarations
         else if =("global" | "procedure" | "link" | "invocable")
         then {
            while write(get(comments))
            write(line)
            }
         else put(comments, line)
         }
      }

   while write(get(comments))

   recordlist := sort(recordtable, 3)		#  sort record

   while get(recordlist) do
      every write(!get(recordlist))

end
