#!/bin/sh
# -*-tcl-*-
# the next line restarts using tclsh \
exec tclsh "${0}" "${@}"

####################################
# Parse a ChangeLog files into a tcl structure.

proc main {} {
    global argv
    set in [lindex $argv 0]
    set out [cl:parse [read [set fh [open $in r]]][close $fh]]

    #puts [join $out \n] -- Test code
    #exit
    puts $out
}

proc cl:parse {data} {
    set state         unknown
    set chunk(date)   {}
    set chunk(person) {}
    set chunk(items)  {}
    set idata         {}

    foreach line [split $data \n] {
	if {[cl:parse:chunk_intro $line date person]} {
	    cl:parse:close_last_item
	    cl:parse:close_last_chunk
	    cl:parse:init_chunk $date $person
	    continue
	}
	if {[cl:parse:item_line $line data]} {
	    cl:parse:close_last_item
	    cl:parse:init_item $data
	    continue
	}
	if {[cl:parse:item_followup $line data]} {
	    cl:parse:add2item $data
	    continue
	}
	# ignore all other lines.
    }

    cl:parse:close_last_item
    cl:parse:close_last_chunk

    return $result
}

proc cl:parse:chunk_intro {line datevar personvar} {
    if {![regexp "^\[^\t \]" $line]} {
	return 0
    }

    upvar $datevar d $personvar p

    if {[regexp -indices -- {^([0-9]+-[0-9-]+)} $line -> di]} {
	foreach {da de} $di break ; # lassign

	regsub -all "\[ \t\]+" [string trim [string range $line $da $de]]       { } d
	regsub -all "\[ \t\]+" [string trim [string range $line [incr de] end]] { } p

	#puts stderr "$line +--> ($d | $p)"

	return 1
    }

    regsub -all "\[\t \]+" $line { } line

    set line [split $line]
    set d [join [lrange $line 0 4]]
    set p [join [lrange $line 5 end]]

    #puts stderr "$line |--> ($d | $p)"

    return 1
}

proc cl:parse:close_last_chunk {} {
    upvar result r chunk c

    if {$c(date) != {}} {
	lappend r [list $c(date) $c(person) $c(items)]
	set c(date)   {}
	set c(person) {}
	set c(items)  {}

    }
    return
}

proc cl:parse:init_chunk {date person} {
    upvar chunk c
    set c(date)   $date
    set c(person) $person
    set c(items)  {}
    return
}

proc cl:parse:item_line {line itemvar} {
    if {![regexp "^\[\t \]+\\*" $line]} {
	return 0
    }

    upvar $itemvar i

    set line [string trimleft [string trimright $line] "\t *"]
    set i $line
    return 1
}

if {0} {
    return 1
}

proc cl:parse:close_last_item {} {
    upvar chunk c idata i

    if {$i != {}} {
	set ke [string first : $i]
	if {$ke < 0} {
	    set ke -1 ; # No key at all, pure comment
	}

	set k  [string trim [string range $i 0 [incr ke -1]]]
	set co [string trim [string range $i [incr ke 2] end]]

	lappend c(items) [list $k $co]
	set i {}

    }
    return
}

proc cl:parse:init_item {comment} {
    upvar idata i
    set i $comment
    return
}

proc cl:parse:item_followup {line commentvar} {
    upvar $commentvar c

    set line [string trim $line]
    if {$line == {}} {
	return 0
    }

    set c $line
    return 1
}

proc cl:parse:add2item {comment} {
    upvar idata i
    append i " $comment"
}

##########################################################

main
exit 0


syntax highlighted by Code2HTML, v. 0.9.1