# # KEHOME/src/utility.icn # Oct/16/2005 # Aug/30/2008 more arg error checking # Aug/31/2008 average function # Sep/2/2008 list_dollar # utility functions for list/table/nest/... # includes sum, scaning, ... global TypeComment global OutputFiles # table procedure list_dollar(tuple,dollar_tuple) #======================================== # set $1,$2,... for list members # adapted from nrel_dollar() in relation.icn # used for dovalue list in everydo.icn local i,dvar,dval static info,warning initial { info := "INFO: list_dollar: " warning := "WARNING: list_dollar: " } /dollar_tuple := table() every i := 1 to *tuple do { if i < 10 then { dvar := "$"||i } else { dvar := "${"||i||"}" # a la KornShell } dval := tuple[i] case *dval of { default: { } 0: { dval := &null writes_type_all(dval,warning||"null value: "||dvar||" = ") } 1: { if dval[1] == "" then # empty string dval[1] := "''" } } # end case *dval insert(dollar_tuple,dvar,dval) # $i = argi } # end every i return dollar_tuple end # list procedure list_delete(L,x) #========================= # L ::= list of string # called by hwalk() in hwalk.icn local y,z z := [] every y := !L do if y ~== x then put(z,y) return z end # string procedure random(arglist) #======================== # do random od concept:1,... done; # do random od concept:1 done; # choose random element of list # called by command() in command.icn local choice,clist,q,ctype,uset clist := arglist case *clist of { 1: { # concept - get units, species, members, alternatives q := new_concept(!clist) ctype := KNIT[q].ctype case ctype of { default: { uset := KNIT[q].unit ++ KNIT[q].species choice := ?uset } ("ingroup"|"list"|"set"|"multiset"|"sequence"): { uset := KNIT[q].member choice := ?uset } ("exgroup"|"enum"): { uset := KNIT[q].alternative choice := ?uset } } # end case ctype } # end 1 default: { # concept list choice := ?clist } } # end case *clist choice := unparse(choice) write(myout,choice) return choice end procedure table_writes(fd,x,head,tail,lsep,lend,nvsep) #===================================================== /head := "" /tail := "" /lsep := "," /lend := " " /nvsep := " "||NVSEPARATOR||" " writes(fd,head) writes(fd,table_unparse(x,lsep,lend,nvsep)) # unparse.icn writes(fd,tail) end procedure list_writes(fd,x,sep,head,tail,join,list0,list1,list2,string0) #======================================================================= local t,n,i,y local list0left,list0right local list1left,list1right local list2left,list2right static info,ierror initial { info := "INFO: list_writes: " ierror := "Internal ERROR: list_writes: " } /sep := "," /head := "" /tail := "" /join := NVSEPARATOR /list0 := "[]" # length 0 /list1 := "" # length 1 /list2 := "[]" # length 2 or more /string0 := "\"\"" # length 0 list0left := list0[1] | "" list0right := list0[2] | "" list1left := list1[1] | "" list1right := list1[2] | "" list2left := list2[1] | "" list2right := list2[2] | "" #writes(mybug,TypeComment||info||"list2 <",list2,">\n") case t := type(x) of { "list": { } default: { writes_type(myerr,x,ierror||"not list: x") writes_type(mylog,x,ierror||"not list: x") fail } } writes(fd,head) n := *x i := 0 case n of { 0: { writes(fd,list0left) } 1: { writes(fd,list1left) } default: { writes(fd,list2left) } # length 2 or more } every y := ! x do { i +:= 1 writes_any(fd,y,sep,"","",join,list0,list1,list2,string0) if i < n then writes(fd,sep) # original comma separator removed by map_symbol() } case n of { 0: { writes(fd,list0right) } 1: { writes(fd,list1right) } default: { writes(fd,list2right) } # length 2 or more } writes(fd,tail) end procedure set_writes(fd,x,sep,head,tail,join,list0,list1,list2,string0) #====================================================================== # like list_writes(), but sort members local y static info initial { info := "INFO: set_writes: " } /sep := "," /head := "" /tail := "" /join := NVSEPARATOR /list0 := "[]" # length 0 /list1 := "" # length 1 /list2 := "[]" # length 2 or more /string0 := "\"\"" # length 0 #writes(mybug,TypeComment||info||"list2 <",list2,">\n") y := sort(x) list_writes(fd,y,sep,head,tail,join,list0,list1,list2) end procedure writes_object(fd,x,sep,head,tail,join,list0,list1,list2,string0) #========================================================================= static info initial { info := "INFO: writes_object: " } /sep := "," /head := "" /tail := "" /join := NVSEPARATOR /list0 := "[]" # length 0 /list1 := "" # length 1 /list2 := "" # length 2 or more /string0 := "\"\"" # length 0 #writes(mybug,TypeComment||info||"list2 <",list2,">\n") writes_any(fd,x,sep,head,tail,join,list0,list1,list2,string0) end procedure writes_value(fd,x,sep,head,tail,join,list0,list1,list2,string0) #======================================================================== local tcol static info initial { info := "INFO: writes_value: " } #####tcol := "\n"||repl(" ",4) #####case CHARFORMAT of { #####default: { /sep := "," } #####"line": { /sep := "," } #####"column": { /sep := ","||tcol } #####} # end case CHARFORMAT /sep := "," /head := "" /tail := "" /join := NVSEPARATOR /list0 := "[]" # length 0 /list1 := "" # length 1 /list2 := "[]" # length 2 or more /string0 := "\"\"" # length 0 #writes(mybug,TypeComment||info||"list2 <",list2,">\n") writes_any(fd,x,sep,head,tail,join,list0,list1,list2,string0) end procedure writes_type_all(var,label,tail) #======================================== # writes_type() to myout,myerr,mylog local fd,OutputFiles /tail := ">\n" OutputFiles := [myout,myerr,mylog] every fd := !OutputFiles do { case fd of { default: { writes_type(fd,var,label,tail) } myerr: { if \namein ~== "input" then { writes_type(fd,var,label,tail) } } } # end case fd } # end every fd end procedure writes_any_all(var,sep,label,tail) #======================================== # writes_any() to myout,myerr,mylog local fd,OutputFiles /sep := "," /tail := ">\n" OutputFiles := [myout,myerr,mylog] every fd := !OutputFiles do { case fd of { default: { writes_any(fd,var,sep,label,tail) } myerr: { if \namein ~== "input" then { writes_any(fd,var,sep,label,tail) } } } # end case fd } # end every fd end procedure writes_all(x,tail) #=========================== # x ::= list of any # write() to myout,myerr,mylog local fd,outfiles initial { OutputFiles := [myout,myerr,mylog] } case namein of { "input": { outfiles := [myout,mylog] } default: { outfiles := OutputFiles } } /tail := "\n" every fd := !outfiles do { every writes_any(fd,!x); writes(fd,tail) } end procedure writes_type(fd,x,label,tail) #===================================== # write x & its type # typical TypeComment ::= TypeComment | "" | "\n" local sep,head,join local t,typeANDsize initial { /TypeComment := TypeComment } /label := "type" sep := "," t := type(x) typeANDsize := t case t of { ("string"|"list"|"set"|"table"): { typeANDsize ||:= "["||*x||"]" } } head := TypeComment||label ||"("||typeANDsize||") <" /tail := ">\n" join := NVSEPARATOR writes_any(fd,x,sep,head,tail,join) end procedure writes_any(fd,x,sep,head,tail,join,list0,list1,list2,string0,option) #============================================================================= # bracket all list/set local s,L,B,S,E local tcol,t,n,i,j,k,name,op,value,y local thead,tcont,tsep,ttail static q,info initial { q := "\"" info := "INFO: writes_any: " } /sep := "," /head := "" /tail := "" /join := NVSEPARATOR /list0 := "[]" # length 0 /list1 := "" # length 1 /list2 := "[]" # length 2 or more /string0 := "\"\"" # length 0 option := "nobad" tcol := "\n"||repl(" ",4) case CHARFORMAT of { default: { thead := ""; tcont := sep; tsep := ""; ttail := "" } "column": { thead := tcol; tcont := sep||tcol; tsep := ""; ttail := "" } } #writes(mybug,TypeComment||info||"list2 <",list2,">\n") writes(fd,head) case t := type(x) of { default: { writes(fd,"UNEXPECTED TYPE <",t,">") } # record types "htmlstate": { print_htmlstate(fd,x) } # htmltest.icn "htmlinput": { print_htmlinput(fd,x) } # htmltest.icn "htmloutput": { print_htmloutput(fd,x) }# htmltest.icn "PHRASE": { phrase_writes(fd,x) } # symbol.icn "NVPHRASE": { nv_writes(fd,x) } # nvlist.icn "AAPHRASE": { aa_writes(fd,x) } # array.icn "BSE": { bse_writes(fd,x) } # bselist.icn "PPOBJECT": { ppobject_writes(fd,x) } # pplist.icn "GROUP": { group_writes(fd,x) } # begin.icn "HOUNIT": { ho_writes(fd,x) } # hwalk.icn "RELUNIT": { nrel_writes(fd,x) } # relation.icn "WORD": { writes(fd,"WORD(",x.wtype,",") writes(fd,x.wvalue) writes(fd,")") } "TOKEN": { writes(fd,"TOKEN(",x.ttype,",") writes(fd,x.tvalue) writes(fd,")") } "SYMBOL": { writes(fd,"SYMBOL(",x.stype,",") case x.stype of { default: { writes_any(fd,x.svalue,",") } #"nv": { writes_any(fd,x.svalue," ") } # list: [name,=,value] #"wp": { writes_any(fd,x.svalue," ") } # string: phrase # <== obsolete } writes(fd,")") } "XMLNS": { writes(fd,"XMLNS(",x.nsname,",") writes_any(fd,x.nsfile) writes(fd,")") } "posix_stat": { writes(fd,"posix_stat(") n := *x every i := 1 to n-1 do writes(fd,x[i],tcont) writes(fd,x[n]) writes(fd,")") } # other Icon types "null": { writes(fd,"&null") } "procedure": { writes(fd,image(x)) } "co-expression": { writes(fd,image(x)) } "window": { writes(fd,image(x)) } "file": { writes(fd,image(x)) } "cset": { writes(fd,image(x)) } "integer": { writes(fd,x) } "real": { writes(fd,x) } "string": { if *x = 0 then writes(fd,string0) else writes(fd,x) } # end "string" "list": { list_writes(fd,x,sep,"","",join,list0,list1,list2) } "set": { set_writes(fd,x,sep,"","",join,list0,list1,list2) } "table":{ writes(fd,table_unparse(x)) # unparse.icn ##### n := *x ##### i := 0; j := 0 ##### if n > 0 then writes(fd,thead) ##### every k := sort_key(x) do { ##### i +:= 1 ##### name := k # name := sym2string(name) ##### op := join ##### value := x[k] # value := sym2string(value) ##### if option=="nobad" & bad_value(value) then { } else { ##### j +:= 1 ##### if j > 1 then writes(fd,tcont) ##### writes_any(fd,name) ##### writes(fd,op) ##### # quote separator values - for later read ##### case name of { ##### default: { } ##### "hoseparator": { value := forcequote(value) } # hierarchy ##### "mseparator": { value := forcequote(value) } # method ##### "nvseparator": { value := forcequote(value) } # namevalue ##### "pseparator": { value := forcequote(value) } # phrase ##### "relseparator": { value := forcequote(value) } # relation ##### "roleseparator": { value := forcequote(value) } # role ##### ##### "automatic": { value := forcequote(value) } # "isa","isa*" ##### "kcase": { value := forcequote(value) } # "no" ##### "stv": { value := forcequote(value) } # "SPACE,TIME,VIEW" ##### } # end case name ##### writes_any(fd,value,sep,"","",join,"[]","",list2,"[]") ##### #if i < n then ##### # writes(fd,tsep) ##### } # end if ##### } # end every k ##### if n > 0 then writes(fd,ttail) } # end "table" } # end case type writes(fd,tail) end #-----------------------------------------------------------# # SYMBOL procedure get_nv(cname,charname,chartype) #======================================== # for context: space,time,view local value,charvalue static info initial { info := "INFO: get_nv: " } /chartype := "attr" if DEBUG=="NV" then { writes_type(mybug,cname,info||"cname") writes_type(mybug,charname,info||"charname") } cname := unparse(cname) charname := unparse(charname) if charvalue := get_char(chartype,cname,charname) then { if DEBUG=="NV" then { writes_type(mybug,charvalue,info||"charvalue") } #value := unparse(charvalue) #return SYMBOL("nv",[charname,NVSEPARATOR,value]) return new_nv([charname,NVSEPARATOR,charvalue]) } else { fail } end procedure put_nv(cname,nv,chartype) #================================== # for context: space,time,view local t,st local nov,charname,op,charvalue static info,ierror initial { info := "INFO: put_nv: " ierror := "Internal ERROR: put_nv: " } /chartype := "attr" if DEBUG=="NV" then { writes_type(mybug,cname,info||"cname") writes_type(mybug,nv,info||"nv") writes_type(mylog,cname,info||"cname") writes_type(mylog,nv,info||"nv") } set_charnest(cname,[nv],chartype) end procedure writes_nv(fd,nv) #========================= local nov,charname,op,charvalue static ierror initial { ierror := "Internal ERROR: writes_nv: " } nv_writes(fd,nv) # nvlist.icn return #==============# case type(nv) of { default: { writes_type(mylog,nv,ierror||"unexpected type: nv") fail } "SYMBOL": { case nv.stype of { default: { writes_type(mylog,nv,ierror||"unexpected stype: nv") fail } "nv": { nov := nv.svalue } "nvnull": { nov := [nv.svalue,NVSEPARATOR,""] } } # end "SYMBOL" } # end case stype } # end case type charname := nov[1] op := nov[2] charvalue := nov[3] charvalue := parse_list(charvalue) writes_any(fd,charname) case op of { "=": { } ("+="|"-="|"*="): { writes(fd," ") } # for proper parsing as input } writes_any(fd,op) writes_any(fd,charvalue) end # SYMBOL procedure copy_nv(x) #=================== # called by copy_event() in knit.icn local y static info,ierror initial { info := "INFO: copy_nv: " ierror := "Internal ERROR: copy_nv: " } if DEBUG=="COPY" then writes_type(mybug,x,info||"input") case type(x) of { default: { writes_type(mylog,x,ierror||"unexpected type") return x } "string": { return copy(x) } "integer": { return copy(x) } "real": { return copy(x) } "list": { y := []; every put(y,copy_nv(!x)); return y } "set": { y := []; every insert(y,copy_nv(!x)); return y } "PHRASE": { return PHRASE(copy(phrase_list(x))) } # end "PHRASE" "NVPHRASE": { return new_nv(copy_nv(nv_novlist(x))) } # end "NVPHRASE" "SYMBOL": { case x.stype of { default: { writes_type(mylog,x,ierror||"unexpected stype") return x } "pplist": { return SYMBOL("pplist",copy_nv(x.svalue)) } "pp": { return SYMBOL("pp", copy_nv(x.svalue)) } "nv": { return SYMBOL("nv", copy_nv(x.svalue)) } "nvnull": { return SYMBOL("nvnull",copy_nv(x.svalue)) } "nvobject": { return SYMBOL("nvobject",copy_nv(x.svalue)) } } # end case stype } # end "SYMBOL" } # end case type end #-------------------------------------------------------# #-------------------------------------------------------# # string procedure mapquote(s,quotes) #=========================== local q,qlist,qpair,qbegin,qend,qmark local i static info,ierror initial { info := "INFO: mapquote: " ierror := "Internal ERROR: mapquote: " } /quotes := "\"\"" q := repl("n",*s) case type(quotes) of { default: { writes_type(mylog,quotes,ierror||"unexpected quotes") return q } "string": { qlist := [quotes] } "list": { qlist := quotes } } every qpair := !qlist do { case *qpair of { default: { writes_type(mylog,qpair,ierror||"unexpected qpair") } 2: { qbegin := qpair[1] qend := qpair[2] qmark := "n" every i := 1 to *s do { case qmark of { "n": { case s[i] of { qbegin: { q[i] := "y"; qmark := "y" } default:{ } } } "y": { case s[i] of { qend: { q[i] := "y"; qmark := "n" } default:{ q[i] := "y" } } } } # end case qmark } # end every i } # end 2 } # end case *qpair } # end every qpair if DEBUG=="QUOTE" then { writes_type(mybug,s,info||"s") writes_type(mybug,q,info||"q") } return q end #-----------------------------------------------------------# #-----------------------------------------------------------# procedure write_nest(fd,nest,nsep,nhead,ntail) #============================================= # nest is list of x local sep,head,tail,n,i local x sep := \nsep | "" head := \nhead | "{" tail := \ntail | "}" writes(fd,head) n := *nest i := 0 every x := ! nest do { i +:= 1 case type(x) of { "string": { writes(fd,x) } "list": { write_list(fd,x,"/","{","}") } "set": { write_set (fd,x,"/","{","}") } #"PHRASE": { write_list (fd,x.pvalue," "," "," ") } default: { writes(fd,"UNEXPECTED TYPE") } } if i < n then writes(fd,sep) } writes(fd,tail) end #-----------------------------------------------------------# #-----------------------------------------------------------# procedure nest_find(word,symbol,quote) #===================================== # find string s in nest of string local i,j,k,gsym,sym,inquote /quote := "\"\"" # do NOT match inside quote every i := 1 to *symbol do { gsym := symbol[i] every j := 1 to *gsym do { sym := gsym[j] inquote := mapquote(sym,quote) if k := find(word,sym) & inquote[k] == "n" then suspend [i,j,k] } } fail end procedure list_find(s,L,quote) #============================= # find string s in list of string local i,j,inquote /quote := "\"\"" # do NOT match inside quote every i := 1 to *L do { inquote := mapquote(L[i],quote) if j := find(s,L[i]) & inquote[j] == "n" then { suspend [i,j] } } fail end procedure nest_match(word,symbol,quote) #====================================== # match string s in nest of string local i,j,k,gsym,sym,inquote /quote := "\"\"" # do NOT match inside quote every i := 1 to *symbol do { gsym := symbol[i] every j := 1 to *gsym do { sym := gsym[j] inquote := mapquote(sym,quote) #write(mybug,"nest_match: word <",word,"> sym <",sym,"> inquote <",inquote,">") if k := match(word,sym) & inquote[k - *word] == "n" then return [i,j,k] } } fail end procedure nest_rmatch(word,symbol,quote) #======================================= # match string s in nest of string # scan backwards to find last occurrence local i,j,k,gsym,sym,inquote /quote := "\"\"" # do NOT match inside quote every i := *symbol to 1 by -1 do { gsym := symbol[i] every j := *gsym to 1 by -1 do { sym := gsym[j] inquote := mapquote(sym,quote) #write(mybug,"nest_match: word <",word,"> sym <",sym,"> inquote <",inquote,">") if k := match(word,sym) & inquote[k - *word] == "n" then return [i,j,k] } } fail end procedure list_match(s,L,quote) #============================== # match string s in list of string local i,j,inquote /quote := "\"\"" # do NOT match inside quote every i := 1 to *L do { inquote := mapquote(L[i],quote) if j := match(s,L[i]) & inquote[j - *s] == "n" then { return [i,j] } } fail end #-----------------------------------------------------------# #-----------------------------------------------------------# # list procedure keylist(T) #=================== # sorted list of keys of table local x,L,S L := [] every x := key(T) do put(L,x) S := sort(L) return S end procedure sort_key(T) #==================== # generate sorted keys of table local x,L,S L := [] every x := key(T) do put(L,x) S := sort(L) every x := ! S do suspend x end procedure sort_gen(G,object) #=========================== # sort output of generator local L L := [] every put(L, G(object)) suspend ! sort(L) end procedure reverse_list(L) #======================== return reverse(L) #####local R #####R := [] #####every x := ! L do ##### push(R,x) #####return R end #-----------------------------------------------------------# #-----------------------------------------------------------# # time operations # string procedure to_ymd(time) #===================== local ymd ymd := parse_time(time) ymd := list2value(ymd," ") return trimws(ymd) end # string procedure to_dmy(time) #===================== local ymd,dmy ymd := parse_time(time) dmy := reverse(ymd) dmy := list2value(dmy," ") return trimws(dmy) end # string procedure to_mdy(time) #===================== local ymd,mdy ymd := parse_time(time) mdy := [ymd[2],ymd[3],ymd[1]] mdy := list2value(mdy," ") return trimws(mdy) end # string or list procedure get_date(cmd,time) #=========================== local result case cmd of { default: { result := parse_time(time) } "ymd": { result := to_ymd(time) } "dmy": { result := to_dmy(time) } "mdy": { result := to_dmy(time) } "year": { result := get_year(time) } "month": { result := get_month(time) } "day": { result := get_day(time) } } return result end # list procedure parse_time(time) #========================= # time ::= # year/mon/day # year mon day local year,month,day,date static sep,MONTH initial { sep := '/' ++ ' ' MONTH := ["Jan","Feb","Mar","Apr","May","Jun", "Jul","Aug","Sep","Oct","Nov","Dec"] } if upto(sep,time) then { } else return [time,"",""] year := time month := "" day := "" time ?:= { year := tab(upto(sep)) & move(1) & month := tab(0) } time ?:= { month := tab(upto(sep)) & move(1) & day := tab(0) } if *month > 0 & is_number(month) then month := MONTH[month] date := [year,month,day] # check for different orders if *day = 4 then # day/mon/year => year/mon/day date[1] :=: date[3] if numeric(date[2]) then # year/day/mon => year/mon/day date[2] :=: date[3] return date end # string procedure get_year(time) #======================= # year of time return parse_time(time)[1] end # string procedure get_month(time) #======================= # month of time return parse_time(time)[2] end # string procedure get_day(time) #======================= # day of time return parse_time(time)[3] end #-----------------------------------------------------------# #-----------------------------------------------------------# # numeric operations # arglist ::= nest procedure get_numeric(cmd,arglist) #================================= local result if DEBUG=="NUMERIC" then writes_type(mybug,arglist,"INFO: get_numeric: "||cmd||" arglist") case cmd of { default: { write(myerr,arglist,,"# WARNING: illegal numeric command <"||cmd||" ",">\n") fail } "min": { result := min_list(arglist) } "max": { result := max_list(arglist) } "sum": { result := list_sum(arglist) } } if DEBUG=="NUMERIC" then writes_type(mybug,result,"INFO: get_numeric: "||cmd||" result") return result end procedure min_list(L) #==================== # minimum of units of list or set # L ::= nest local min, u, newmin if *L = 0 then fail min := numeric(L[1][1]) every u := !L do { u := !u u := unparse(u) newmin := numeric(u) if newmin < min then min := newmin } return min end procedure max_list(L) #==================== # maximum of units of list or set # L ::= nest local max, u, newmax if *L = 0 then fail max := numeric(L[1][1]) every u := !L do { u := !u u := unparse(u) newmax := numeric(u) if newmax > max then max := newmax } return max end # real procedure list_average(L) #======================== # average of numbers in list or set # L ::= list | set | gname local avg,num,den local u,gtype,arity,uset static info,warning initial { info := "INFO: list_average: " warning := "WARNING: list_average: " } if DEBUG == "AVERAGE" then { writes_type_all(L,info||"L") } num := list_sum(L) case type(L) of { default:{ fail } "null": { fail } "list": { den := *L } "set": { den := *L } "string": { # group name u := unparse(L) if DEBUG == "AVERAGE" then writes_type_all(u,info||"u") den := size_member(u) } # end "string" "relation": { arity := get_arity(L) if arity = 1 then { uset := get_unit(L) den := *uset if DEBUG=="AVERAGE" then writes_type_all(uset,info||"uset") } else { writes_type_all(arity,warning||"unexpected relation: arity") fail } # end if } } # end case type(L) if /den then fail if den = 0 then fail avg := div(num,den) if DEBUG == "AVERAGE" then { writes_type_all(num,info||"num") writes_type_all(den,info||"den") writes_type_all(avg,info||"avg") } return avg end # integer procedure list_sum(L) #==================== # sum of numbers in list or set # L ::= list | set | gname # calls is_number() in newword.icn local sum static info,warning initial { info := "INFO: list_sum: " warning := "WARNING: list_sum: " } sum := numeric(0) case type(L) of { default:{ } "null": { } "list": { every sum +:= numeric(!L) } "set": { every sum +:= numeric(!L) } "string": { # group name sum := list_sum(get_member(L)) } } # end case type(L) if DEBUG=="SUM" then { writes_type_all(sum,info||"sum") } return sum end #-----------------------------------------------------------# #-----------------------------------------------------------# # size operations procedure table_sum(T,zero) #========================== # sum of table of count # also known as bag or counted set local z,x,sum z := \zero | 0 sum := z every x := key(T) do sum +:= T[x] return sum end procedure list_count(L,zero,increment) #===================================== # table of count of list unit # also known as bag or counted set local z,i,count,u z := \zero | 0 i := \increment | 1 count := table(integer(z)) every u := !L do count[u] +:= i return count end procedure size_nest(N,zero) #========================== # list of size of nest unit local ns,u /zero := 0 ns := [] every u := !N do put(ns,*u+zero) return ns end #-----------------------------------------------------------# #-----------------------------------------------------------# # copy procedure copy_nest(N) #===================== local nest,L static warning initial { warning := "WARNING: copy_nest: " } case type(N) of { default: { writes_type_all(N,warning||"unexpected type: N") } "null": { fail } "list": { } } nest := [] every L := ! N do put(nest,copy_list(L)) return nest end procedure copy_set(S) #==================== return set(copy_list(S)) end procedure copy_list(L) #===================== # 2-level copy local newlist,t static warning initial { warning := "WARNING: copy_list: " } case t := type(L) of { "null": { fail } default: { writes_type_all(L,warning||"unexpected type: L") } "string": { writes_type(mylog,L,warning||"unexpected type: L") return L } "list": { } "set": { } "BSE": { return bse_copy(L) } } newlist := [] every put(newlist,copy(!L)) return newlist end procedure copy_table(T,tdefault) #=============================== local newtab,k static warning initial { warning := "WARNING: copy_table: " } case type(T) of { default: { writes_type_all(T,warning||"unexpected type: T") } "null": { fail } "table": { } } newtab := table(tdefault) every k := key(T) do newtab[k] := T[k] return newtab end #-----------------------------------------------------# #-----------------------------------------------------# # windows procedure dump_wattrib(fd,win,head,tail) #======================================= # print window attributes local mlabel,miconlabel local msize,mresize,mcursor,mecho,mcanvas local mfont,mbg,mfg local awin static info,warning initial { info := "INFO: dump_wattr: " warning := "WARNING: dump_wattr: " } /head := "" /tail := "" #awin := active_windows() #every w := !awin do write(fd,"# INFO: ",image(w)) write(fd,TypeComment,head) case type(win) of { "null": { writes_type(fd,win,info||"null window") } default: { writes_type(fd,win,warning||"not window") } "window": { mbg := WAttrib(win,"bg") mcanvas := WAttrib(win,"canvas") mcursor := WAttrib(win,"cursor") mecho := WAttrib(win,"echo") mfg := WAttrib(win,"fg") mfont := Font(win) miconlabel := WAttrib(win,"iconlabel") mlabel := WAttrib(win,"label") mresize := WAttrib(win,"resize") msize := WAttrib(win,"size") write(fd,"# window <",image(win),">") write(fd,"# label <",miconlabel,">") write(fd,"# iconlabel <",miconlabel,">") write(fd,"# canvas <",mcanvas,">") write(fd,"# size <",msize,">") write(fd,"# resize <",mresize,">") write(fd,"# cursor <",mcursor,">") write(fd,"# echo <",mecho,">") write(fd,"# font <",mfont,">") write(fd,"# bg <",mbg,">") write(fd,"# fg <",mfg,">") } # end "window" } # end case type write(fd,TypeComment,tail) end #