############################################################################
#
#	File:     hufftab.icn
#
#	Subject:  Program to compute Huffman state transitions 
#
#	Author:   Gregg M. Townsend
#
#	Date:     November 14, 1994
#
############################################################################
#
#   This file is in the public domain.
#
############################################################################
#
#      Each input line should be a string of 0s & 1s followed by a value
#   field.  Output is a list of items in a form suitable for inclusion
#   by a C program as initialization for an array.  Each pair of items
#   indicates the action to be taken on receipt of a 0 or 1 bit from the
#   corresponding state; this is either a state number if more decoding
#   is needed or the value field from the input if not.  State 0 is the
#   initial state;  0 is output only for undefined states.  States are
#   numbered by two to facilitate use of a one-dimensional array.
#
#   sample input:		corresponding output:
#	00 a			    /*  0 */  2, c, a, 4, 0, b,
#	011 b
#	1 c			[new line started every 10 entries]
#
#   Interpretation:
#	from state 0,  input=0 => go to state 2,  input=1 => return c
#	from state 2,  input=0 => return a,  input=1 => go to state 4
#	from state 4,  input=0 => undefined,  input=1 => return b
#
############################################################################

global curstate, sttab, line

procedure main()
   local code, val, n

   sttab := list()
   put(sttab)
   put(sttab)
   while line := read() do {
      line ? {
         if ="#" | pos(0) then next
         (code := tab(many('01'))) | (write(&errout, "bad: ", line) & next)
         tab(many(' \t'))
         val := tab(0)
      }
      curstate := 1
      every bit(!code[1:-1])
      curstate +:= code[-1]
      if \sttab[curstate] then write(&errout, "dupl: ", line)
      sttab[curstate] := val
   }
   write("/* generated by machine -- do not edit! */")
   write()
   writes("/*  0 */")
   out(sttab[1])
   every n := 2 to *sttab do {
      if n % 10 = 1 then writes("\n/* ", n-1, " */")
      out(sttab[n])
   }
   write()
end


procedure bit(c)
   curstate +:= c
   if integer(sttab[curstate]) then {
      curstate := sttab[curstate]
      return
   }
   if type(sttab[curstate]) == "string" then write(&errout, "dupl: ", line)
   curstate := sttab[curstate] := *sttab + 1
   put(sttab)
   put(sttab)
end


procedure out(v)
   if type(v) == "integer" then
      writes(right(v-1, 6), ",")
   else
      writes(right(\v | "0", 6), ",")
end
