#******************************************************************************
#
#       Copyright:      2005-2010 Paul Obermeier (obermeier@tcl3d.org)
#
#                       See the file "Tcl3D_License.txt" for information on
#                       usage and redistribution of this file, and for a
#                       DISCLAIMER OF ALL WARRANTIES.
#
#       Module:         Tcl3D -> tcl3dOgl
#       Filename:       createStateList.tcl
#
#       Author:         Paul Obermeier
#
#       Description:    Tcl script to convert the ASCII representation of the
#                       OpenGL state variables (contained in directory glSpec)
#                       into Tcl package code.
# 
#                       Usage: tclsh8.4 createStateList.tcl 
#                              GLSpec/glSpec20.txt tclfiles/tcl3dStateList.tcl
#
#******************************************************************************

package require Tk

# The state list is created in a boots-trapping process.
# If building from scatch, we don't have package tcl3dOgl
# installed, so we load it directly.
set tcl3dOglLib [format "tcl3dOgl%s" [info sharedlibextension]]
load [file join "../tcl3dOgl" $tcl3dOglLib] tcl3dogl

if { $argc <= 1 } {
    puts ""
    puts "Usage: $argv0 glSpecFile TclListFile"
    puts ""
    exit 1
}

proc tclCreateFunc {} {
}

proc tclDisplayFunc {} {
}

proc tclReshapeFunc { w h } {
}

# Element index 0: Get value (Enumeration name without "GL_" prefix)
# Element index 1: Type
# Element index 2: Get command (GL command without "gl" prefix)
# Element index 3: Initial value
# Element index 4: Description
# Element index 5: OpenGL Reference manual section
# Element index 6: Attribute group

proc ParseOneElem { fp } {
    set i 0
    set elemList {}
    while { $i < 7 && ![eof $fp] } {
        gets $fp line
        incr ::lineNum
        if { [string match "#*" $line] || \
             [string length $line] == 0 } {
            continue
        }
        set elem [string trim $line " ()"]
        # Variable name
        if { $i == 0 && ![string match "-*" $elem] } {
            set elem [format "GL_%s" $elem]
        # Query command
        } elseif { $i == 2 } {
            set elem [string trim [lindex [split $elem ","] end] " "]
            set elem [format "gl%s" $elem]
        }
        lappend elemList $elem
        incr i
    }
    return $elemList
}

frame .fr
pack .fr -expand 1 -fill both
togl .fr.toglwin -width 400 -height 400
listbox .fr.usage -height 8
grid .fr.toglwin -row 0 -column 0 -sticky news
grid .fr.usage   -row 1 -column 0 -sticky news
grid rowconfigure .fr 0 -weight 1
grid columnconfigure .fr 0 -weight 1

set glCmdList  [info commands gl*]
set glEnumList [info globals GL_*]

set inFile [lindex $argv 0]
set inFp [open $inFile "r"]
set ::lineNum 1

set outFile [lindex $argv 1]
set fp [open $outFile "w"]

puts $fp "proc tcl3dGetStateList {} {"
puts $fp "return {"

set extList { "ARB" "EXT" "NV" "ATI" }
set elemNum 0

while { 1 } {
    set elem [ParseOneElem $inFp]
    # puts "Found elem: <$elem>"
    if { [llength $elem] != 7 } {
        puts "Error in element description <$elem>"
        break
    }
    set enumVal [lindex $elem 0]
    set glCmd   [lindex $elem 2]
    set descr   [lindex $elem 4]
    set initVal [lindex $elem 3]

    if { [string compare $initVal "Identity"] == 0 } {
        set numVals 16
    } elseif { [lsearch -exact $glEnumList $initVal] >= 0 } {
        set numVals 1
        set tmp [format "\$::%s" $initVal]
        set initVal [expr $tmp]
    } else {
        set initValList [split $initVal ","]
        set numVals [llength $initValList]
    }
    
    set found 0
    if { [string equal $glCmd "gl-"] } {
        puts "No command specified for <$descr>"
    } elseif { [lsearch -exact $glCmdList $glCmd] >= 0 } {
        set found 1
    } else {
        puts "$::lineNum : Command NOT found: $glCmd"
        foreach ext $extList {
            set cmdExt [format "%s%s" $glCmd $ext]
            if { [lsearch -exact $glCmdList $cmdExt] >= 0 } {
                puts "Found $cmdExt instead"
            }
        }
        set found 1
    }

    if { [string equal $enumVal "-"] } {
        puts "No enumeration specified for <$descr>"
        set found 1
    } elseif { [lsearch -exact $glEnumList $enumVal] >= 0 } {
        set found 1
    } else {
        puts "$::lineNum : Enum NOT found: $enumVal"
        foreach ext $extList {
            set enumExt [format "%s_%s" $enumVal $ext]
            if { [lsearch -exact $glEnumList $enumExt] >= 0 } {
                puts "Found $enumExt instead"
            }
        }
        set found 1
    }
    if { $found } {
        # puts "Found $glCmd $enumVal $numVals"
        puts $fp "{ $glCmd $enumVal $numVals [list $initVal] }"
    }
    incr elemNum
}
puts $fp "}"
puts $fp "}"

puts "Converted $elemNum elements"

exit 0
