#!/bin/sh
# the next line restarts using the correct interpreter \
exec tclsh "$0" $"$@"


# Building the bib file of 3GPP specifications.
# $Id: 3gpp2bib.tcl, v1.0 2005-02-01

# This program does:
# 1) Get the latest index file of 3GPP specifications
# 2) Generates an Latex Bibliography file (bibtex) with those contents.
#
# execute: tclsh 3gpp2bib.tcl [--usecache] [--debug] [--help] [--version]
#
# (c) Miguel Garcia <ea1dof@gmail.com>
#
# 240208. The source file has change its location
#
# (c) Dan Forsberg <dforsberg@gmail.com>
#
# 221009. Added release and version information into the bib file,
# changed author field to include spec
#
########################### initialization   #########################

set 3gppFile http://www.3gpp.org/ftp/Specs/html-info/2003-04-10_webexp11a_status-report_special_select.txt
set usecache 0
set debug 0
set version 1.0
set bibFileName 3gpp-zot.bib

if {[catch {package require http 1.0}]} {
    if {[info exists httpold]} {
	catch {puts "Cannot load http 1.0 package"}
	::tcltest::cleanupTests
	return
    }
}

if {[catch {package require csv 0.4}]} {
    catch {puts "Cannot load csv 0.4 package"}
    ::cleanupTests
    return
}


########################### procedures   #########################

# Http_Proxy sets or queries the proxy

proc Http_Proxy {{new {}}} {

	global http

	if ![info exists http(proxy)] {
		return {}
	}

	if {[string length $new] == 0} {
		return $http(proxy):$http(proxyPort)
	} else {
		regexp {^([^:]+):([0-9]+)$} $new x \
			http(proxy) http(proxyPort)
	}
}

proc Http_Open {url} {

	global http

	if {![regexp -nocase {^(http://)?([^:/]+)(:([0-9])+)?(/.*)} \
			$url x protocol server y port path]} {
		error "bogus URL: $url"

	}

	if {[string length $port] == 0} {
		set port 80
	}

	set sock [socket $server $port]
	puts $sock "GET $path HTTP/1.0"
	puts $sock "Host: $server"
	puts $sock "User-Agent: Tcl/Tk Http_Open"
	puts $sock ""
	flush $sock

	return $sock

}

proc progress {token total current} {
    puts -nonewline "."
    flush stdout
}

proc webscan {scanurl scanout} {
    global debug
    set token [http_get $scanurl -progress progress \
	    -headers {Pragma no-cache} -channel $scanout]
    puts ""
    
    # Print out the return header information
    if {$debug} {
	upvar #0 $token state
	puts $state(http)
	foreach {key value} $state(meta) {
	    puts "$key: $value"
	}
    }
}

proc downloadFile {resource filename} {
    global debug

    if {[file exist $filename]} {
	if {$debug} {
	    puts "Backing up $filename"
	}
	file rename -force $filename $filename\~
    }

    if [catch {open $filename w} out] {
	puts "\nError: Cannot open $out\nExecution aborted"
	exit
    }
    puts "Getting the latest 3GPP index file stored at $resource"
    webscan $resource $out
    close $out
}


# File format:
#
# The first line contains a header. Next and succesive lines contains the data 
# example below
#
# "statrepwdrwn"~"statreprel"~"statreptype"~"statrepspec"~"statreptitle"~"statrepvers"~"statrepwg"~"statrepremark"~"statrepdraft"~"statrepwebpage"~"statrepavailable"
#"active"~"Rel-7"~"TR"~"21.900"~"Technical Specification Group working methods"~"7.0.0"~"SP"~~""~"21900.htm"~"2005-01-04"
#
# In each Release, there is only one specification listed, the last version.
# But a given specification may appear in different Releases.




proc flushSpec {data} {
    global 3gppbibfile

    set 3gppstatus 0
    set 3gpprelease 1
    set 3gpptype 2
    set 3gppspec 3
    set 3gpptitle 4
    set 3gppversion 5
    set 3gppwg 6
    set 3gppremarks 7
    set 3gppdraft 8
    set 3gpphtml 9
    set 3gppdate 10


	# Dan (mod): Need to extend specSuffix to contain release and
	# possibly also version information.  Release information has
	# one of following formats: 'Rel-x', 'R9y', 'Ph1',
	# 'Ph2'. Version always 'x.y.z'. Relase could be in format
	# 'rXY' (r8, r9, r98, r97, rPh1)?
	set specVersion [lindex $data $3gppversion]
	set specRelease [lindex $data $3gpprelease]
	

## Dan: Add $specRel if you need the release also.
## But for now it is removed.
#	# One of these matches
#	if [ string match "Rel-*" $specRelease ] {
#		scan $specRelease "Rel-%s" specR
#		set specRel "r$specR"
#	} elseif [ string match "R*" $specRelease ] {
#		scan $specRelease "R%02d" specR
#		set specRel "R$specR"
#	} elseif [ string match "Ph*" $specRelease ] {
#		scan $specRelease "Ph%d" specR
#		set specRel "Ph$specR"
#	} else {
#		puts "ERROR: Release not identified"
#	}
#

    puts $3gppbibfile "@book\{3gpp.[lindex $data $3gppspec],"

    puts $3gppbibfile "  author = \"3GPP\","
    puts $3gppbibfile "  title = \"\{[lindex $data $3gpptitle]\}\","
    puts $3gppbibfile "  type = \"[lindex $data $3gpptype]\","
    puts $3gppbibfile "  series = \"[lindex $data $3gpptype]\","
    puts $3gppbibfile "  institution = \"{3rd Generation Partnership Project (3GPP)}\","
    puts $3gppbibfile "  number = \"\{[lindex $data $3gpptype][lindex $data $3gppspec]\}\","
    # Dan: Put the release and version information in the bib entry
    puts $3gppbibfile "  note = \"\{$specRelease v$specVersion\}\","
    set year ""
    set month ""
    set day ""
    scan [lindex $data $3gppdate] "%04d-%02d-%02d" year month day
    switch $month {
	1 {set month "jan"}
	2 {set month "feb"}
	3 {set month "mar"}
	4 {set month "apr"}
	5 {set month "may"}
	6 {set month "jun"}
	7 {set month "jul"}
	8 {set month "aug"}
	9 {set month "sep"}
	10 {set month "oct"}
	11 {set month "nov"}
	12 {set month "dec"}
	default {}
    }  
    if {[string length $day] != 0} {
	puts $3gppbibfile "  days = $day,"
    }
    if {[string length $month] != 0} {
	puts $3gppbibfile "  month = $month,"
    }
    if {[string length $year] != 0} {
	puts $3gppbibfile "  year = $year,"
    }
    puts $3gppbibfile "  url = \"http:\/\/www.3gpp.org\/ftp\/Specs\/html-info\/[lindex $data $3gpphtml]\","
    puts $3gppbibfile "\}\n"

}

###########
# M A I N #
###########

# If you are using a proxy, configure it here and remove the comment
# in the next line

# http_config -proxyhost your.proxy.com -proxyport 8080


# get the 3GPP index file 

global 3gppbibfile
set url $3gppFile
set localfile 3gpp.csv

foreach opt $argv {
    switch -- $opt {
	-debug -
        --debug {
	    set debug 1
	}

	-h -
	-help -
	--help {
	    puts "$argv0 \[--usecache\] \[--debug\] \[--help\] \[--version\]"
	    puts "Converts the 3GPP index file to bib format (Latex)"
	    exit
	}

	-usecache -
	--usecache {
	    set usecache 1
	}

        -version -
	--version {
	    puts stderr "$argv0 version $version"
	    exit
	}
    }
}


if {!$usecache} {
	downloadFile $url $localfile
}

   

# loop to convert from xml to bibtex format

if [catch {open $localfile r} csvfile] {
    puts "\nError: Cannot open $csvfile\nExecution aborted"
    exit
}

# initialize array and line counter
set lineCounter 0
set debugCounter 0

if [catch {open $bibFileName w} 3gppbibfile] {
    puts "\nError: Cannot open $localfile\nExecution aborted"
    exit
}

puts $3gppbibfile "@COMMENT{{This is the BibTex library for 3GPP Specifications)}}"
puts -nonewline $3gppbibfile "@COMMENT{{This file was automatically generated on "
puts -nonewline $3gppbibfile [clock format [clock seconds]]
puts $3gppbibfile " with $argv0 $version}}"
puts $3gppbibfile "@COMMENT{{(c) Miguel Garcia, ea1dof (at) gmail}}\n"
puts $3gppbibfile "@COMMENT{{(c) Dan Forsberg (mods), dforsber (at) gmail (Zotero mod)}}\n\n"
puts "\n"

while {[gets $csvfile line] >= 0} {
    incr lineCounter
    if {$debug} {
	if {$debugCounter < 10} {
	    puts "Line $lineCounter: $line"
	    incr debugCounter
	}
    }

    # skip the first line that contains headers (if contains headers)
    if {$lineCounter == 1} {
	if {[string equal $line "\"statrepwdrwn\"~\"statreprel\"~\"statreptype\"~\"statrepspec\"~\"statreptitle\"~\"statrepvers\"~\"statrepwg\"~\"statrepremark\"~\"statrepdraft\"~\"statrepwebpage\"~\"statrepavailable\""] == 0} {
	    puts "Warning: Missing or changed header in file $localfile"
	    puts "Has the file structure changed?"
	    puts "Execution aborted"
	    exit
	}

    } else {
    # main scanning loop begins

	set listLine [::csv::split $line ~]
	set 3gpprelease 1
	set 3gppspec 3
	set 3gppversion 5

	set specNumber [lindex $listLine $3gppspec]
	scan $specNumber "%02d.%s" specSeries specSuff

	# Miguel: Now we need to find out if the Spec is already
	# listed in hash table (because it appeared in a previous
	# release.  This assumes that later releases (newer) are
	# listed at the top of the CSV file, because we don't check
	# the actual release.

	# Dan (mod): Need to extend specSuffix to contain release and
	# possibly also version information.  Release information has
	# one of following formats: 'Rel-x', 'R9y', 'Ph1',
	# 'Ph2'. Version always 'x.y.z'. Relase could be in format
	# 'rXY' (r8, r9, r98, r97, rPh1)?
	set specVersion [lindex $listLine $3gppversion]
	set specRelease [lindex $listLine $3gpprelease]
	
	# One of these matches
	if [ string match "Rel-*" $specRelease ] {
		scan $specRelease "Rel-%s" specR
		set specRel "r$specR"
	} elseif [ string match "R*" $specRelease ] {
		scan $specRelease "R%02d" specR
		set specRel "R$specR"
	} elseif [ string match "Ph*" $specRelease ] {
		scan $specRelease "Ph%d" specR
		set specRel "Ph$specR"
	} else {
		puts "ERROR: Release not identified"
	}


        # Dan: revert back to the original scheme, where only the
        #  newest releases are stored on the same spec
	set specSuffix "$specSuff"    
	#set specSuffix "$specSuff$specRel"

	#
	# Hash table structure
	# hash ($specSeries) = list-of {$specSuffix}
	#
	if {[array names hash $specSeries] == ""} {
	    # hash($specSeries) does not exist yet, so the spec is new
	    lappend hash($specSeries) $specSuffix
	    flushSpec $listLine
	} else {
	    # hash($specSeries) exists, but is the spec listed?
	    if {[lsearch $hash($specSeries) $specSuffix] == -1} {
		# the spec is not listed
		lappend hash($specSeries) $specSuffix
		flushSpec $listLine
	    }
	}
    }
}



close $3gppbibfile
puts "File $bibFileName successfully created"
close $csvfile

