#%TITLE% STLIST.MAC
#
#%NAME%
# STLIST.MAC - Macros for list handling
#
#%OVERVIEW%
# This macro file provides a set of functions to handle lists of elements
# with optional parameters.%BR%
# A list is data structure stored in an associative array that is composed
# of a number of elements. Each element is a string that occupies a certain
# position in the list, numeric elements are not allowed.
# An element can be referenced by it name (string) or by its position in
# the list (number).%BR%
# Each element in the list can have an arbitrary number of parameters
# associated to it.
# Each parameter has a name (a string) and a value (a number or a string).%BR%
# This macro set provides functions to initialise the list and add elements
# and parameters to it. It also provides functions to retrieve information
# from the list.%BR%
# %BR%
# When retrieving information it may be convenient to use shortcuts to
# access directily the content of the list instead of going through the
# macro functions. In this case there is no error checking but performance
# is considerably increased.%BR%
# if LIST[] is the associative array that holds the list, the following
# expressions can be used:
#%UL%
#%LI% (LIST[0]) evaluates to the number of elements in the list.
#%LI% (elem in LIST) is true if the string elem is a valid element.
#%LI% (LIST[n]) returns the element in position n (>0).
#%LI% (LIST[elem][par]) returns the value of the parameter par of element elem.
#%XUL%
#
#%ATTENTION%
# This macro set overrides some macros previously included in %B%stlocal.mac%B%.
#%EXAMPLE%
#%DL%
#%DT%list_add(mylist, \"el1\")
#%DD% Adds the element "el1" to the list stored in the associative array
# mylist.
#%DT%list_add(mylist, \"el1\", \"par1\")
#%DD% Adds the parameter "par1" to the item "el1".
#%DT%list_setpar(mylist, \"el1\", \"par1\", 5312)
#%DD% Sets the parameter "par1" of the item "el1" to 5312.
#%DT%list_list(mylist)
#%DD% Prints on the screen the current content of the list mylist.
#%DD%
#%XDL%
#
#%END%
#%UU% <list>
#%MDESC%
# This macro checks if <list> is an associative array and if not
# initialises it to be ready to contain a list. It does nothing if
# <list> was already initialised.
#
def list_test 'if (!(whatis("$1") & 0x01000000)) {$1[0]=0}'
#%UU% <list>
#%MDESC%
# This macro clears and iniatilises <list> to contain a list. The information
# contained (if any) is lost.
#
def list_init '{
local i
if (whatis("$1") & 0x01000000) {
for (i in $1)
delete $1[i]
}
$1[0]=0
}'
#%UU% (<list>)
#%MDESC%
# This function returns the number of elements contained in the list
# specified as parameter. <list> must be an associative array (old-style
# array), if not the function returns -1.
#
def list_n(list) '{
local wl
wl = whatis("list")
if (wl) {
if (wl & 0x01000000){
return(list[0]+0)
}else
return (-1)
} else
return(0)
}'
#%UU% (<list>, <item>)
#%MDESC%
# This function checks if <item> is contained in <list> and returns its
# current position. If <item> is not in the list the function returns
# zero.%BR%
# <list> must be an associative array (old-style array), if not the
# function returns -1.%BR%
# <item> is either a string or a number. If a number is used it refers to
# the position of the element in the list.
#
def list_check(list, item) '{
local i
if (list_n(list) < 0)
return(-1)
if (item + 0 == item) {
i = (item < 0) ? 0 : int(item)
} else {
i = (item in list)? list[item] : 0
}
if (i <= list[0])
return(i)
else
return(0)
}'
#%UU% (<list>, <item>)
#%MDESC%
# This function adds a new element to the list. The element is specified
# by the string <item>. If such element already exists it is moved to the
# end of the list but no new elements are appended.%BR%
# The function returns the position in the list of the element recently
# added. This value is always the size of the list.%BR%
# <item> cannot be a numeric value.%BR%
# If <item> is a number, the element is not added and the function
# returns 0. If <list> is not a valid list the function returns -1.
#
def list_add(list, item) '{
local N
if (item == (item+0))
return(0)
if (item in list) {
for (N = list[item]; N < list[0]; N++) {
list[N] = list[N+1]
list[list[N+1]] = N
}
list[list[0]] = item
list[item] = list[0]
} else {
list[++list[0]] = item
list[item] = list[0]
}
return(list[0])
}'
#%UU% (<list>, <string> [,<separator>])
#%MDESC%
# This function adds new elements to <list> in the same way than
# %B%list_add%B% but several elements can be appended in the same function
# call. The element specifiers are
# obtained by spliting <string> by means of the %B%spec%B% function split().
# If no <separator> is specified space characters are used as delimiters.%BR%
# The function returns the number of elements added to the list. If an error
# happens -1 is returned and <list> is not modified.
def list_splitadd(list, str, sep) '{
local i larr[] llist[] n
if (list_n(list) < 0)
return(-1)
if (whatis("sep") & 0x08000000)
n = split(str, larr)
else
n = split(str, larr, sep)
for (i = 0; i < n; i++) if (list_add(llist, larr[i]) <= 0) return(-1)
for (i = 0; i < n; i++) list_add(list, larr[i])
return(llist[0])
}'
#%UU% (<list>, <item>, <param>, <value>)
#%MDESC%
# This function sets the value of a parameter for a particular element in
# a list.%BR%
# <list> and <item> must follow the rules explained for the
# function %BR%list_check()%BR%.
# <param> is a string that specifies the parameter, if a number is used it is
# internally converted to string. <value> can be a number or a string. %BR%
# If no error is found, the function returns 1, otherwise it returns -1.
#
def list_setpar(list, item, param, value) '{
local N parlist
if ((N = list_check(list, item)) > 0) {
item = list[N]
parid = item "\034" param
list[parid] = value
return(1)
} else
return(-1)
}'
#%UU% (<list>, <item>, <param_list>)
#%MDESC%
# This function creates an auxiliary list that contains all the parameters
# associated to a given element in a list.%BR%
# <list> and <item> must follow the rules explained for the
# function %BR%list_check()%BR%.
# The auxiliary list is created in <param_list> that must be also an
# associative array as <list>. When the function returns, the elements of
# <param_list> are the identifiers of all the parameters associated to the
# element <item> in <list>. Each element of <param_list> has a single
# parameter called `value' that is set to the actual value of the
# corresponding parameter in <list>.%BR%
# The function returns the total number of parameters associated to <item>,
# i.e. the total number of elements in <param_list>, or -1 if an error
# happens.
#
def list_getparlist(list, item, parlist) '{
local N npar i len parid
if ((N = list_check(list, item)) <= 0)
return(-1)
list_init parlist
parid = list[N] "\034"
len = length(parid)
for (i in list) {
if (length(i) >= len && substr(i, 1, len) == parid) {
N = list_add(parlist, substr(i, len+1))
list_setpar(parlist, N, "value", list[i])
}
}
return(parlist[0])
}'
#%UU% (<list>, <item>, <param>)
#%MDESC%
# This function returns the value of a particular parameter associated to
# an element of a list.
# <list>, <item> and <param> must follow the rules explained for the
# function %BR%list_setpar()%BR%.
# If an error is found the function returns -1.
#
def list_getpar(list, item, param) '{
local par
if ((N = list_check(list, item)) <= 0)
return(-1)
par = list[N] "\034" param
return((par in list)? list[par] : -1)
}'
#%UU% (<list>, <item> [, <param>])
#%MDESC%
# This function removes a parameter associated to an element of a list.
# If <param> is not especified, all the parameters associated with the
# element <item> are removed.
#
def list_removepar(list, item, param) '{
local parid len i
parid = item "\034"
len = length(parid)
if (whatis("param") & 0x08000000) {
for (i in list)
if (length(i) >= len && substr(i, 1, len) == parid)
delete list[i]
} else {
parid = parid param
if (parid in list)
delete list[parid]
else
return(-1)
}
return(0)
}'
#%UU% (<list>, <item>)
#%MDESC%
# This function deletes a particular element in a list and returns its
# position in the list before deletion.%BR%
# If <item> is not in the list the function returns zero.
# <list> must be an associative array (old-style array), if not the
# function returns -1.%BR%
#
def list_remove(list, item) '{
local N i len
list_removepar(list, item)
if ((N = list_check(list, item)) > 0){
item = list[N]
for (i=N; i<list[0]; i++) {
list[i] = list[i+1]
list[list[i+1]] = i
}
delete list[i]
delete list[item]
list[0] = list[0] - 1
}
return(N)
}'
#%UU% (<list>, <item>)
#%MDESC%
# This function returns -1 if the element <item> is not included in <list>
# or if an error happens. If <item> is a valid element the function returns
# the element identifier (that may be different from <item> if a number is
# used).%BR%
#
def list_item(list, item) '{
local N
if ((N = list_check(list, item)) > 0)
return(list[N])
else
return(-1)
}'
#%UU% (<list>)
#%MDESC%
# This function prints on the screen all the elements in a list along with
# the associated parameters. It is intended for debugging purposes.%BR%
# It returns the number of eleemnts in the list or -1 if an error happens.
#
def list_list(list) '{
local N i j parlist[]
if ((N = list_n(list)) < 0){
return(-1)
}
if (N == 0)
print "List is empty"
else {
printf("List contains %d element%s:\n", N, N>1?"s":"")
parlist[0]=0
for (i=1; i<=N; i++) {
printf("%3d - %10s ", i, list[i])
if (npar = list_getparlist(list, list[i], parlist) <= 0)
print "No parameters"
else {
for (j = 1; j <= parlist[0]; j++)
printf("%s:<%s> ", parlist[j], list_getpar(parlist, j, "value"))
print
}
}
}
return(N)
}'
#%MACROS%
#%DEPENDENCIES%
# No dependencies
#%AUTHOR% P. Fajardo, (Original 3/96 in stlocal.mac). %BR%
# $Revision: 1.1 $ / $Date: 2008/11/17 12:39:27 $
#%TOC%
|