#! /bin/sed -nf

#----------------- gather the lines in hold space

H
$!b

#----------------- sort them

# Append a new-line and the look-up table to hold space, get everything
# in pattern space
s/.*/° !"#$%\&'()*+,-.\/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~/
H
g

t sort
:sort
# This regexp performs an insertion sort pass!!!
# It searches for two lines with a common (possibly empty) prefix and
# compares the first differing char using a lookup table -- if the
# order is wrong, the regexp matches and the RHS of the s command
# swaps the lines
#
# \1 = line after the one to be inserted
# \2 = common part to the two lines     
# \3 = first differing char (in \1)     
# \4 = lines between the two lines      
# \5 = line to be inserted              
# \6 = first differing char (in \5)     
# \7 = lines after the second line + the lookup table

s/\(\n\([ -~]*\)\([ -~]\)[ -~]*\)\(\n.*\)\?\(\n\2\([ -~]\)[ -~]*\)\(\n.*°.*\6.*\3\)/\5\1\4\7/
#   1----------------------------  4---      5------------------    7------------
#       2-----    3----                            6----
t sort

# Remove the last new-line and the lookup table
# Leave the leading new-line
s/^\(.*\)\n°.*$/\1/

#----------------- delimit and number them

:number

# Remove the first line, move the last number to the beginning of the
# new first line together with the lookup table
s/\([0-9]*\)[ -~]*\n/\1;9876543210990090 /
     
# This regexp does the incrementing -- see tutorials for its explanation
s/\([0-8]\{0,1\}\)\(9*\);[^1]*\(.\)\1[0-9]*X*\2\(0*\)[^ ]*/\3\4/
P

# If the first char changes, we replace the first line with
# a single new-line character.  The pattern space will look the
# same as when we leave the sorting section, and the counter
# will be restarted.
# The leading new-line is printed by the second line, which
# can only match if the first did (if it didn't, the first 
# character will still be a digit).
/^[0-9]* \(.\).*\n\1/ !s/[ -~]*//
/^\n/P

/./b number
